From d69b9c940c764d6650a265146c4dccd3b19625d0 Mon Sep 17 00:00:00 2001 From: leiyuwei <249304969@qq.com> Date: Sat, 20 Jun 2026 00:16:23 +0800 Subject: [PATCH] init --- .gitignore | 39 + .idea/.gitignore | 5 + .idea/ApifoxUploaderProjectSetting.xml | 6 + .idea/encodings.xml | 21 + .idea/misc.xml | 15 + .idea/vcs.xml | 6 + README.md | 27 + bpm-starter/README.md | 29 + bpm-starter/pom.xml | 64 ++ .../flow/category/DetailFlowCategoryBo.java | 48 + .../category/QueryFlowCategoryTreeBo.java | 30 + .../definition/DetailFlowDefinitionBo.java | 66 ++ .../definition/FlowDefinitionSelectorBo.java | 63 ++ .../definition/QueryFlowDefinitionBo.java | 78 ++ .../instance/QueryBusinessFlowInstanceBo.java | 36 + .../bpm/bo/flow/task/QueryInstanceListBo.java | 147 +++ .../bpm/bo/flow/task/QueryMyTaskListBo.java | 147 +++ .../bpm/bo/flow/task/QueryTodoTaskListBo.java | 132 +++ .../bpm/config/BpmBeanAutoConfiguration.java | 57 + .../config/BpmSwaggerAutoConfiguration.java | 18 + .../bpm/controller/BpmSelectorController.java | 75 ++ .../controller/FlowCategoryController.java | 128 +++ .../controller/FlowDefinitionController.java | 193 ++++ .../controller/FlowInstanceController.java | 68 ++ .../bpm/controller/FlowTaskController.java | 151 +++ .../starter/bpm/dto/FlowInstanceExtDto.java | 22 + .../starter/bpm/dto/FlowTaskDto.java | 93 ++ .../starter/bpm/entity/FlowCategory.java | 30 + .../starter/bpm/entity/FlowCuApproveHis.java | 77 ++ .../starter/bpm/entity/FlowCuInstance.java | 42 + .../bpm/entity/FlowDefinitionWrapper.java | 99 ++ .../bpm/entity/FlowInstanceWrapper.java | 102 ++ .../starter/bpm/entity/FlowTaskWrapper.java | 85 ++ .../starter/bpm/enums/FlowCooperateType.java | 34 + .../enums/FlowDefinitionActivityStatus.java | 31 + .../bpm/enums/FlowDefinitionExtBizType.java | 31 + .../bpm/enums/FlowDefinitionIsPublish.java | 31 + .../starter/bpm/enums/FlowInstanceStatus.java | 40 + .../starter/bpm/enums/FlowNodeType.java | 36 + .../starter/bpm/enums/FlowSkipType.java | 36 + .../bpm/handlers/BpmChartExtService.java | 63 ++ .../bpm/handlers/BpmDataFillHandler.java | 21 + .../bpm/handlers/BpmHandlerSelectService.java | 230 +++++ .../bpm/handlers/BpmPermissionHandler.java | 70 ++ .../exception/FlowExceptionConverter.java | 19 + .../bpm/impl/FlowCategoryServiceImpl.java | 59 ++ .../bpm/impl/FlowCuApproveHisServiceImpl.java | 14 + .../bpm/impl/FlowCuInstanceServiceImpl.java | 14 + .../FlowDefinitionWrapperServiceImpl.java | 75 ++ .../impl/FlowInstanceWrapperServiceImpl.java | 26 + .../bpm/impl/FlowTaskWrapperServiceImpl.java | 186 ++++ .../starter/bpm/listeners/BpmBizListener.java | 65 ++ .../bpm/listeners/BpmGlobalListener.java | 368 +++++++ .../bpm/mappers/FlowCategoryMapper.java | 8 + .../bpm/mappers/FlowCuApproveHisMapper.java | 8 + .../bpm/mappers/FlowCuInstanceMapper.java | 8 + .../mappers/FlowDefinitionWrapperMapper.java | 19 + .../mappers/FlowInstanceWrapperMapper.java | 8 + .../bpm/mappers/FlowTaskWrapperMapper.java | 39 + .../bpm/service/FlowCategoryService.java | 33 + .../bpm/service/FlowCuApproveHisService.java | 8 + .../bpm/service/FlowCuInstanceService.java | 8 + .../service/FlowDefinitionWrapperService.java | 35 + .../service/FlowInstanceWrapperService.java | 15 + .../bpm/service/FlowTaskWrapperService.java | 79 ++ .../bpm/transfers/FlowCuInstanceTransfer.java | 18 + .../flow/category/CreateFlowCategoryVo.java | 23 + .../flow/category/DetailFlowCategoryBo.java | 48 + .../flow/category/GetFlowCategoryListVo.java | 10 + .../category/QueryFlowCategoryTreeBo.java | 30 + .../flow/category/UpdateFlowCategoryVo.java | 24 + .../definition/CreateFlowDefinitionVo.java | 37 + .../definition/DetailFlowDefinitionBo.java | 66 ++ .../definition/FlowDefinitionSelectorBo.java | 63 ++ .../definition/FlowDefinitionSelectorVo.java | 31 + .../definition/QueryFlowDefinitionBo.java | 78 ++ .../definition/QueryFlowDefinitionVo.java | 49 + .../SetFlowDefinitionActivityStatusVo.java | 31 + .../SetFlowDefinitionPublishVo.java | 31 + .../definition/UpdateFlowDefinitionVo.java | 36 + .../instance/QueryBusinessFlowInstanceBo.java | 36 + .../vo/flow/instance/QueryInstanceListVo.java | 31 + .../bpm/vo/flow/task/ApprovePassTaskVo.java | 36 + .../bpm/vo/flow/task/ApproveRefuseTaskVo.java | 36 + .../bpm/vo/flow/task/QueryInstanceListBo.java | 147 +++ .../bpm/vo/flow/task/QueryMyTaskListBo.java | 147 +++ .../bpm/vo/flow/task/QueryMyTaskListVo.java | 31 + .../bpm/vo/flow/task/QueryTodoTaskListBo.java | 132 +++ .../bpm/vo/flow/task/QueryTodoTaskListVo.java | 31 + .../bpm/vo/flow/task/RejectTaskVo.java | 36 + .../starter/bpm/vo/flow/task/UndoTaskVo.java | 36 + bpm-starter/src/main/java/lombok.config | 2 + .../main/resources/META-INF/spring.factories | 3 + ...ot.autoconfigure.AutoConfiguration.imports | 2 + .../mappers/FlowDefinitionWrapperMapper.xml | 27 + .../mappers/FlowTaskWrapperMapper.xml | 114 ++ common/README.md | 40 + common/pom.xml | 77 ++ .../starter/common/constants/PatternPool.java | 145 +++ .../common/constants/ResponseConstants.java | 79 ++ .../starter/common/constants/StringPool.java | 108 ++ .../common/exceptions/BaseException.java | 37 + .../common/exceptions/ClientException.java | 14 + .../common/exceptions/SysException.java | 14 + .../impl/AccessDeniedException.java | 23 + .../exceptions/impl/AuthExpiredException.java | 18 + .../impl/DefaultClientException.java | 17 + .../exceptions/impl/DefaultSysException.java | 22 + .../exceptions/impl/InputErrorException.java | 23 + .../impl/ParameterNotFoundException.java | 11 + .../impl/RepeatRequestException.java | 18 + .../exceptions/impl/UserLoginException.java | 12 + .../starter/common/functions/SFunction.java | 17 + .../starter/common/locker/LockBuilder.java | 14 + .../starter/common/locker/Locker.java | 8 + .../starter/common/utils/ArrayUtil.java | 12 + .../starter/common/utils/Assert.java | 39 + .../starter/common/utils/BeanUtil.java | 12 + .../starter/common/utils/CollectionUtil.java | 39 + .../starter/common/utils/DateUtil.java | 385 +++++++ .../starter/common/utils/FileUtil.java | 33 + .../starter/common/utils/IdWorker.java | 82 ++ .../starter/common/utils/MailUtil.java | 12 + .../starter/common/utils/NumberUtil.java | 381 +++++++ .../starter/common/utils/ObjectUtil.java | 12 + .../starter/common/utils/ReflectUtil.java | 70 ++ .../starter/common/utils/RegUtil.java | 28 + .../starter/common/utils/StringUtil.java | 76 ++ .../starter/common/utils/ThreadUtil.java | 12 + .../starter/common/utils/XmlUtil.java | 361 +++++++ .../starter/common/utils/ZipUtil.java | 12 + common/src/main/java/lombok.config | 2 + mq-starter/README.md | 13 + mq-starter/activemq-starter/README.md | 12 + mq-starter/activemq-starter/pom.xml | 39 + .../config/ActiveMqAutoConfiguration.java | 17 + .../ActiveMqTenantInterceptor.java | 29 + .../activemq/producer/ActiveMqProducer.java | 126 +++ .../queue/ActiveMqQueueDefinition.java | 17 + .../src/main/java/lombok.config | 2 + .../main/resources/META-INF/spring.factories | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + mq-starter/mq-core/README.md | 13 + mq-starter/mq-core/pom.xml | 27 + .../mq/core/bo/ExportingExportTaskBo.java | 54 + .../starter/mq/core/bo/FailExportTaskBo.java | 40 + .../mq/core/bo/SuccessExportTaskBo.java | 58 ++ .../components/export/ExportTaskWorker.java | 47 + .../core/config/MqBeanAutoConfiguration.java | 25 + .../config/MqSwaggerAutoConfiguration.java | 18 + .../core/controller/ExportTaskController.java | 107 ++ .../starter/mq/core/dto/AddExportTaskDto.java | 31 + .../mq/core/dto/ExecuteExportTaskDto.java | 16 + .../mq/core/dto/ExportTaskSummaryDto.java | 18 + .../starter/mq/core/entity/ExportTask.java | 107 ++ .../mq/core/enums/ExportTaskStatus.java | 34 + .../mq/core/events/ExportTaskNotifyEvent.java | 15 + .../mq/core/handlers/ExportTaskHandler.java | 164 +++ .../mq/core/impl/ExportTaskServiceImpl.java | 128 +++ .../mq/core/mappers/ExportTaskMapper.java | 24 + .../starter/mq/core/producer/MqProducer.java | 83 ++ .../mq/core/queue/QueueDefinition.java | 8 + .../mq/core/service/ExportTaskService.java | 67 ++ .../mq/core/service/MqProducerService.java | 46 + .../starter/mq/core/utils/ExportTaskUtil.java | 28 + .../mq/core/vo/QueryFailExportTaskVo.java | 15 + .../mq/core/vo/QuerySuccessExportTaskVo.java | 15 + .../main/resources/META-INF/spring.factories | 2 + ...ot.autoconfigure.AutoConfiguration.imports | 2 + .../resources/mappers/ExportTaskMapper.xml | 13 + mq-starter/pom.xml | 40 + mq-starter/rabbitmq-starter/README.md | 14 + mq-starter/rabbitmq-starter/pom.xml | 32 + .../config/RabbitMqAutoConfiguration.java | 98 ++ .../config/TenantMethodInterceptor.java | 63 ++ .../rabbitmq/constants/RabbitMqConstants.java | 40 + .../constants/RabbitMqStringPool.java | 39 + .../impl/RabbitMqProducerServiceImpl.java | 42 + .../app/ExportTaskNotifyListener.java | 41 + .../listeners/mq/ExportTaskListener.java | 125 +++ .../listeners/mq/SysMailMessageListener.java | 131 +++ .../listeners/mq/SysNotifyListener.java | 175 ++++ .../listeners/mq/SysSiteMessageListener.java | 92 ++ .../rabbitmq/producer/RabbitMqProducer.java | 139 +++ .../queue/RabbitMQQueueDefinition.java | 27 + .../src/main/java/lombok.config | 2 + .../main/resources/META-INF/spring.factories | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + pom.xml | 427 ++++++++ web-starter/README.md | 59 ++ web-starter/pom.xml | 221 ++++ .../web/config/CacheAutoConfiguration.java | 53 + .../web/config/KaptchaAutoConfiguration.java | 28 + .../web/config/LettuceAutoConfiguration.java | 86 ++ .../web/config/LockAutoConfiguration.java | 44 + .../config/MagicCustomAutoConfiguration.java | 75 ++ .../web/config/MailAutoConfiguration.java | 44 + .../web/config/MybatisAutoConfiguration.java | 42 + .../config/MybatisBeanAutoConfiguration.java | 14 + .../PasswordEncoderAutoConfiguration.java | 24 + .../web/config/RedisAutoConfiguration.java | 58 ++ .../web/config/SaTokenAutoConfiguration.java | 145 +++ .../web/config/SecurityAutoConfiguration.java | 26 + .../web/config/SwaggerAutoConfiguration.java | 47 + .../web/config/TenantAutoConfiguration.java | 93 ++ ...antDynamicDataSourceAutoConfiguration.java | 66 ++ .../config/TransactionAutoConfiguration.java | 70 ++ .../web/config/UploadAutoConfiguration.java | 35 + .../web/config/WebAutoConfiguration.java | 242 +++++ .../web/config/WebBeanAutoConfiguration.java | 375 +++++++ .../config/WebCommonAutoConfiguration.java | 14 + .../web/config/WebMvcAutoConfiguration.java | 20 + .../config/WebSwaggerAutoConfiguration.java | 29 + .../web/config/WsAutoConfiguration.java | 84 ++ .../config/properties/CacheProperties.java | 21 + .../properties/DefaultSettingProperties.java | 19 + .../config/properties/KaptchaProperties.java | 325 ++++++ .../web/config/properties/MailProperties.java | 50 + .../config/properties/SecretProperties.java | 14 + .../properties/SecurityUploadProperties.java | 19 + .../config/properties/UploadProperties.java | 24 + .../web/config/properties/WebProperties.java | 24 + .../web/config/properties/WsProperties.java | 24 + .../core/annotations/constants/EncryType.java | 22 + .../annotations/convert/EncryptConvert.java | 21 + .../core/annotations/convert/EnumConvert.java | 15 + .../annotations/convert/IgnoreConvert.java | 13 + .../web/core/annotations/ds/CurTenantDs.java | 14 + .../core/annotations/excel/ExcelRequired.java | 10 + .../core/annotations/locker/EnableLock.java | 24 + .../web/core/annotations/locker/LockType.java | 5 + .../web/core/annotations/openapi/OpenApi.java | 19 + .../web/core/annotations/oplog/OpLog.java | 51 + .../permission/DataPermission.java | 13 + .../permission/DataPermissionGroup.java | 11 + .../permission/DataPermissions.java | 15 + .../annotations/security/HasPermission.java | 36 + .../web/core/annotations/sort/Sort.java | 32 + .../web/core/annotations/sort/Sorts.java | 11 + .../timeline/OrderTimeLineLog.java | 58 ++ .../web/core/aop/ControllerAspector.java | 100 ++ .../starter/web/core/aop/OpLogAspector.java | 190 ++++ .../starter/web/core/aop/OpenApiAspect.java | 75 ++ .../web/core/aop/OrderTimeLineLogAspect.java | 223 ++++ .../web/core/aop/PermissionAspect.java | 44 + .../starter/web/core/bo/BaseBo.java | 61 ++ .../starter/web/core/bo/ExcelImportBo.java | 54 + .../starter/web/core/bo/SuperBo.java | 8 + .../core/components/cache/CacheVariables.java | 28 + .../components/captcha/CaptchaValidator.java | 53 + .../components/excel/ExcelEventListener.java | 15 + .../components/excel/ExcelImportListener.java | 264 +++++ .../web/core/components/excel/ExcelModel.java | 10 + .../excel/RequiredFieldStyleHandler.java | 42 + .../generator/GenerateCodeFactory.java | 112 ++ .../handler/GenerateCodeRuleHandler.java | 45 + ...urrentDateTimeRuleGenerateCodeHandler.java | 44 + ...ustomRandomStrGenerateCodeRuleHandler.java | 64 ++ .../impl/FlowGenerateCodeRuleHandler.java | 114 ++ .../SnowFlakeGenerateCodeRuleHandler.java | 39 + .../StaticStrGenerateCodeRuleHandler.java | 41 + .../impl/UUIDGenerateCodeRuleHandler.java | 34 + .../rule/AbstractGenerateCodeRule.java | 16 + .../generator/rule/GenerateCodeRule.java | 5 + .../impl/CurrentDateTimeGenerateCodeRule.java | 21 + .../impl/CustomRandomStrGenerateCodeRule.java | 26 + .../rule/impl/FlowGenerateCodeRule.java | 42 + .../rule/impl/RandomIntGenerateCodeRule.java | 25 + .../rule/impl/SnowFlakeGenerateCodeRule.java | 16 + .../rule/impl/StaticStrGenerateCodeRule.java | 21 + .../rule/impl/UUIDGenerateCodeRule.java | 16 + .../components/locker/DefaultLockBuilder.java | 85 ++ .../core/components/locker/LockFactory.java | 37 + .../components/locker/RedisLockBuilder.java | 186 ++++ .../MagicCustomAuthorizationInterceptor.java | 62 ++ .../magic/MagicCustomJsonValueProvider.java | 39 + .../magic/MagicCustomMagicFunction.java | 27 + .../components/magic/MagicCustomSqlCache.java | 33 + .../core/components/notify/SysNotifyRule.java | 15 + .../components/notify/SysNotifyRuleEmail.java | 25 + .../components/notify/SysNotifyRuleSys.java | 25 + .../web/core/components/oplog/OpLogType.java | 11 + .../permission/DataPermissionHandlerImpl.java | 183 ++++ .../SysDataPermissionDataPermissionType.java | 11 + .../core/components/qrtz/DynamicQrtzJob.java | 59 ++ .../web/core/components/qrtz/QrtzHandler.java | 313 ++++++ .../web/core/components/qrtz/QrtzJob.java | 53 + .../core/components/redis/RedisHandler.java | 551 ++++++++++ .../core/components/resp/InvokeResult.java | 40 + .../components/resp/InvokeResultBuilder.java | 112 ++ .../resp/InvokeResultErrorBuilderWrapper.java | 37 + .../web/core/components/resp/PageResult.java | 68 ++ .../web/core/components/resp/Response.java | 10 + .../components/resp/ResponseErrorBuilder.java | 52 + .../security/AbstractUserDetails.java | 131 +++ .../security/AbstractUserDetailsService.java | 81 ++ .../security/CheckPermissionHandler.java | 17 + .../security/CheckPermissionHandlerImpl.java | 64 ++ .../security/DefaultUserDetails.java | 15 + .../security/PasswordEncoderWrapper.java | 20 + .../security/PermissionCalcType.java | 8 + .../components/security/PermitAllService.java | 86 ++ .../security/SecurityConstants.java | 34 + .../components/security/SecurityUtil.java | 119 +++ .../core/components/security/UserDetails.java | 62 ++ .../security/UserDetailsService.java | 15 + .../security/UserTokenResolver.java | 28 + .../security/UserTokenResolverImpl.java | 25 + .../components/sign/CheckSignFactory.java | 6 + .../components/sign/CheckSignHandler.java | 10 + .../sign/DefaultCheckSignFactory.java | 11 + .../sign/handler/DefaultCheckSignHandler.java | 79 ++ .../core/components/sign/util/SignUtil.java | 98 ++ .../tenant/TenantContextHolder.java | 41 + .../components/tenant/TenantInterceptor.java | 12 + .../components/threads/DefaultCallable.java | 61 ++ .../components/threads/DefaultRunnable.java | 59 ++ .../timeline/OrderTimeLineBizType.java | 15 + .../components/trace/DefaultTraceBuilder.java | 23 + .../core/components/trace/TraceBuilder.java | 24 + .../upload/UploadHandlerFactory.java | 40 + .../upload/client/UploadClient.java | 28 + .../upload/client/config/CosUploadConfig.java | 23 + .../client/config/LocalUploadConfig.java | 17 + .../upload/client/config/ObsUploadConfig.java | 21 + .../upload/client/config/OssUploadConfig.java | 23 + .../upload/client/dto/UploadDto.java | 23 + .../upload/client/impl/CosUploadClient.java | 156 +++ .../upload/client/impl/LocalUploadClient.java | 97 ++ .../upload/client/impl/ObsUploadClient.java | 92 ++ .../upload/client/impl/OssUploadClient.java | 126 +++ .../upload/handler/SecurityUploadHandler.java | 44 + .../upload/handler/UploadHandler.java | 26 + .../impl/CosSecurityUploadHandler.java | 55 + .../upload/handler/impl/CosUploadHandler.java | 43 + .../impl/LocalSecurityUploadHandler.java | 54 + .../handler/impl/LocalUploadHandler.java | 37 + .../impl/ObsSecurityUploadHandler.java | 47 + .../upload/handler/impl/ObsUploadHandler.java | 35 + .../impl/OssSecurityUploadHandler.java | 46 + .../upload/handler/impl/OssUploadHandler.java | 34 + .../components/validation/CodeValidator.java | 23 + .../components/validation/EnumValidator.java | 34 + .../core/components/validation/IsCode.java | 24 + .../core/components/validation/IsEnum.java | 28 + .../core/components/validation/IsJson.java | 24 + .../components/validation/IsJsonArray.java | 24 + .../components/validation/IsJsonObject.java | 24 + .../validation/IsNumberPrecision.java | 26 + .../validation/JsonArrayValidator.java | 19 + .../validation/JsonObjectValidator.java | 19 + .../components/validation/JsonValidator.java | 19 + .../validation/NumberPrecisionValidator.java | 34 + .../core/components/validation/Pattern.java | 31 + .../validation/PatternValidator.java | 34 + .../components/validation/TypeMismatch.java | 11 + .../core/components/validation/UploadUrl.java | 24 + .../validation/UploadUrlValidator.java | 21 + .../web/core/constants/MyBatisStringPool.java | 44 + .../web/core/constants/MybatisConstants.java | 14 + .../core/constants/SqlMethodConstants.java | 14 + .../web/core/controller/BaseController.java | 75 ++ .../controller/DefaultBaseController.java | 21 + .../starter/web/core/dto/BaseDto.java | 10 + .../web/core/dto/GenerateCaptchaDto.java | 29 + .../starter/web/core/dto/GenerateCodeDto.java | 23 + .../starter/web/core/dto/VoidDto.java | 8 + .../starter/web/core/entity/BaseEntity.java | 16 + .../starter/web/core/enums/BaseEnum.java | 26 + .../web/core/event/ClearTenantEvent.java | 16 + .../web/core/event/DataChangeEvent.java | 25 + .../core/event/DataChangeEventBuilder.java | 66 ++ .../web/core/event/DataChangeType.java | 5 + .../web/core/event/ReloadTenantEvent.java | 70 ++ .../web/core/event/SetTenantEvent.java | 20 + .../DefaultBaseEntityFillHandler.java | 95 ++ .../exception/WebExceptionConverter.java | 52 + .../exception/WebExceptionHandler.java | 122 +++ .../web/core/impl/BaseMpServiceImpl.java | 135 +++ .../MybatisPlusUpdateAllColumnInjector.java | 112 ++ .../interceptors/CustomSortInterceptor.java | 133 +++ .../core/interceptors/LoginInterceptor.java | 70 ++ .../interceptors/TenantInterceptorImpl.java | 71 ++ .../web/core/listeners/TenantListener.java | 59 ++ .../starter/web/core/mapper/BaseMapper.java | 72 ++ .../web/core/service/BaseMpService.java | 140 +++ .../starter/web/core/service/BaseService.java | 15 + .../web/core/utils/ApplicationUtil.java | 177 ++++ .../starter/web/core/utils/BoUtil.java | 146 +++ .../starter/web/core/utils/CacheUtil.java | 72 ++ .../starter/web/core/utils/CronUtil.java | 83 ++ .../web/core/utils/DataSourceUtil.java | 137 +++ .../starter/web/core/utils/EncryptUtil.java | 92 ++ .../starter/web/core/utils/EnumUtil.java | 169 +++ .../web/core/utils/ExcelImportUtil.java | 142 +++ .../starter/web/core/utils/ExcelUtil.java | 246 +++++ .../web/core/utils/FieldEncryptUtil.java | 91 ++ .../starter/web/core/utils/GroovyUtil.java | 105 ++ .../starter/web/core/utils/HttpUtil.java | 971 ++++++++++++++++++ .../starter/web/core/utils/IdUtil.java | 46 + .../starter/web/core/utils/JsonUtil.java | 228 ++++ .../starter/web/core/utils/OpLogUtil.java | 204 ++++ .../web/core/utils/PageHelperUtil.java | 55 + .../web/core/utils/PageResultUtil.java | 172 ++++ .../starter/web/core/utils/RequestUtil.java | 222 ++++ .../starter/web/core/utils/ResponseUtil.java | 137 +++ .../starter/web/core/utils/SimpleMap.java | 150 +++ .../starter/web/core/utils/SpelUtil.java | 63 ++ .../starter/web/core/utils/TenantUtil.java | 21 + .../web/core/utils/TransactionUtil.java | 54 + .../starter/web/core/utils/UploadUtil.java | 208 ++++ .../starter/web/core/utils/ValidateUtil.java | 54 + .../starter/web/core/utils/VideoUtil.java | 81 ++ .../starter/web/core/vo/BaseVo.java | 9 + .../starter/web/core/vo/PageVo.java | 29 + .../starter/web/core/vo/SortPageVo.java | 22 + .../web/inner/bo/auth/CollectMenuBo.java | 34 + .../inner/bo/auth/ForgetPswUserInfoBo.java | 27 + .../starter/web/inner/bo/auth/LoginBo.java | 63 ++ .../starter/web/inner/bo/auth/MenuBo.java | 115 +++ .../web/inner/bo/auth/TelephoneLoginBo.java | 43 + .../web/inner/bo/auth/TenantRequireBo.java | 21 + .../inner/bo/oplog/OpLogInUserCenterBo.java | 54 + .../starter/web/inner/bo/qrtz/GetQrtzBo.java | 101 ++ .../web/inner/bo/qrtz/QueryQrtzBo.java | 63 ++ .../inner/bo/system/dept/GetSysDeptBo.java | 55 + .../bo/system/dept/SysDeptSelectorBo.java | 43 + .../inner/bo/system/dept/SysDeptTreeBo.java | 37 + .../inner/bo/system/dic/GetSysDataDicBo.java | 64 ++ .../bo/system/dic/QuerySysDataDicBo.java | 64 ++ .../bo/system/dic/SysDataDicSelectorBo.java | 35 + .../dic/category/GetSysDataDicCategoryBo.java | 38 + .../category/QuerySysDataDicCategoryBo.java | 38 + .../SysDataDicCategorySelectorBo.java | 35 + .../system/dic/item/GetSysDataDicItemBo.java | 50 + .../dic/item/QuerySysDataDicItemBo.java | 50 + .../bo/system/dic/item/SysDataDicItemBo.java | 48 + .../system/generate/GetSysGenerateCodeBo.java | 64 ++ .../generate/QuerySysGenerateCodeBo.java | 45 + .../inner/bo/system/menu/GetSysMenuBo.java | 180 ++++ .../inner/bo/system/menu/QuerySysMenuBo.java | 93 ++ .../bo/system/menu/SysMenuSelectorBo.java | 39 + .../message/mail/GetSysMailMessageBo.java | 45 + .../message/mail/QuerySysMailMessageBo.java | 70 ++ .../message/site/GetSysSiteMessageBo.java | 45 + .../message/site/QueryMySysSiteMessageBo.java | 55 + .../message/site/QuerySysSiteMessageBo.java | 84 ++ .../bo/system/module/QuerySysModuleBo.java | 46 + .../bo/system/notice/GetSysNoticeBo.java | 57 + .../bo/system/notice/QueryMySysNoticeBo.java | 55 + .../bo/system/notice/QuerySysNoticeBo.java | 90 ++ .../bo/system/notify/GetSysNotifyGroupBo.java | 89 ++ .../system/notify/QuerySysNotifyGroupBo.java | 93 ++ .../notify/SysNotifyGroupSelectorBo.java | 31 + .../bo/system/open/GetSysOpenDomainBo.java | 57 + .../bo/system/open/QuerySysOpenDomainBo.java | 57 + .../system/open/SysOpenDomainSelectorBo.java | 35 + .../web/inner/bo/system/oplog/GetOpLogBo.java | 66 ++ .../inner/bo/system/oplog/QueryOpLogBo.java | 60 ++ .../system/parameter/GetSysParameterBo.java | 54 + .../system/parameter/QuerySysParameterBo.java | 74 ++ .../QuerySysDataPermissionModelDetailBo.java | 95 ++ .../SysDataPermissionModelDetailBo.java | 61 ++ .../inner/bo/system/role/GetSysRoleBo.java | 55 + .../inner/bo/system/role/QueryRoleMenuBo.java | 85 ++ .../inner/bo/system/role/QuerySysRoleBo.java | 83 ++ .../bo/system/role/SysRoleSelectorBo.java | 37 + .../role/category/GetSysRoleCategoryBo.java | 38 + .../role/category/QuerySysRoleCategoryBo.java | 38 + .../category/SysRoleCategorySelectorBo.java | 35 + .../inner/bo/system/tenant/GetTenantBo.java | 67 ++ .../inner/bo/system/tenant/QueryTenantBo.java | 67 ++ .../bo/system/tenant/TenantSelectorBo.java | 37 + .../inner/bo/system/user/GetSysUserBo.java | 139 +++ .../inner/bo/system/user/QuerySysUserBo.java | 153 +++ .../inner/bo/system/user/QueryUserRoleBo.java | 49 + .../bo/system/user/SysUserSelectorBo.java | 43 + .../system/user/group/GetSysUserGroupBo.java | 68 ++ .../user/group/QuerySysUserGroupBo.java | 67 ++ .../user/group/SysUserGroupSelectorBo.java | 37 + .../web/inner/bo/usercenter/UserInfoBo.java | 61 ++ .../inner/components/oplog/AuthOpLogType.java | 12 + .../components/oplog/OtherOpLogType.java | 12 + .../components/oplog/SystemOpLogType.java | 12 + ...OrderDataPermissionDataPermissionType.java | 14 + ...oductDataPermissionDataPermissionType.java | 15 + .../ApprovePassOrderTimeLineBizType.java | 11 + .../ApproveReturnOrderTimeLineBizType.java | 11 + .../CancelApproveOrderTimeLineBizType.java | 11 + .../timeline/CreateOrderTimeLineBizType.java | 11 + .../timeline/NormalOrderTimeLineBizType.java | 11 + .../timeline/SendOrderTimeLineBizType.java | 11 + .../timeline/UpdateOrderTimeLineBizType.java | 11 + .../web/inner/controller/AuthController.java | 627 +++++++++++ .../web/inner/controller/QrtzController.java | 165 +++ .../controller/UserCenterController.java | 187 ++++ .../system/DefaultSysSelectorController.java | 487 +++++++++ .../controller/system/OpLogController.java | 84 ++ .../system/SysDataDicCategoryController.java | 142 +++ .../system/SysDataDicController.java | 146 +++ .../system/SysDataDicItemController.java | 181 ++++ .../SysDataPermissionDataController.java | 95 ++ ...ysDataPermissionModelDetailController.java | 150 +++ .../controller/system/SysDeptController.java | 140 +++ .../system/SysGenerateCodeController.java | 156 +++ .../system/SysMailMessageController.java | 84 ++ .../controller/system/SysMenuController.java | 269 +++++ .../system/SysModuleController.java | 98 ++ .../system/SysNoticeController.java | 171 +++ .../system/SysNotifyGroupController.java | 127 +++ .../system/SysOpenDomainController.java | 126 +++ .../system/SysParameterController.java | 154 +++ .../system/SysRoleCategoryController.java | 112 ++ .../controller/system/SysRoleController.java | 128 +++ .../system/SysRoleMenuController.java | 95 ++ .../system/SysSiteMessageController.java | 136 +++ .../controller/system/SysUserController.java | 150 +++ .../system/SysUserDeptController.java | 45 + .../system/SysUserGroupController.java | 127 +++ .../system/SysUserRoleController.java | 45 + .../controller/system/TenantController.java | 140 +++ .../web/inner/dto/dic/city/DicCityDto.java | 41 + .../inner/dto/message/SysMailMessageDto.java | 36 + .../inner/dto/message/SysNoticeTaskDto.java | 50 + .../inner/dto/message/SysSiteMessageDto.java | 36 + .../dto/message/site/SiteMessageDto.java | 35 + .../web/inner/dto/notify/SysNotifyDto.java | 32 + .../inner/dto/notify/SysNotifyParamsDto.java | 17 + .../inner/dto/order/ApprovePassOrderDto.java | 38 + .../starter/web/inner/dto/qrtz/QrtzDto.java | 79 ++ .../web/inner/dto/system/LoginDto.java | 54 + .../starter/web/inner/dto/system/MenuDto.java | 83 ++ .../web/inner/dto/system/MenuMetaDto.java | 34 + .../web/inner/dto/system/UserInfoDto.java | 52 + .../notice/QuerySysNoticeByUserDto.java | 38 + .../inner/dto/system/notice/SysNoticeDto.java | 35 + .../starter/web/inner/entity/DicCity.java | 51 + .../starter/web/inner/entity/OpLogs.java | 67 ++ .../web/inner/entity/OrderTimeLine.java | 65 ++ .../web/inner/entity/RecursionMapping.java | 43 + .../inner/entity/SecurityUploadRecord.java | 55 + .../starter/web/inner/entity/SysDataDic.java | 82 ++ .../web/inner/entity/SysDataDicCategory.java | 77 ++ .../web/inner/entity/SysDataDicItem.java | 87 ++ .../inner/entity/SysDataPermissionData.java | 44 + .../entity/SysDataPermissionModelDetail.java | 67 ++ .../starter/web/inner/entity/SysDept.java | 101 ++ .../web/inner/entity/SysGenerateCode.java | 39 + .../web/inner/entity/SysMailMessage.java | 93 ++ .../starter/web/inner/entity/SysMenu.java | 150 +++ .../starter/web/inner/entity/SysModule.java | 80 ++ .../web/inner/entity/SysModuleTenant.java | 43 + .../starter/web/inner/entity/SysNotice.java | 101 ++ .../web/inner/entity/SysNoticeLog.java | 48 + .../web/inner/entity/SysNotifyGroup.java | 93 ++ .../inner/entity/SysNotifyGroupReceiver.java | 35 + .../web/inner/entity/SysOpenDomain.java | 92 ++ .../web/inner/entity/SysParameter.java | 80 ++ .../starter/web/inner/entity/SysRole.java | 98 ++ .../web/inner/entity/SysRoleCategory.java | 77 ++ .../starter/web/inner/entity/SysRoleMenu.java | 38 + .../web/inner/entity/SysSiteMessage.java | 97 ++ .../starter/web/inner/entity/SysUser.java | 119 +++ .../starter/web/inner/entity/SysUserDept.java | 38 + .../web/inner/entity/SysUserGroup.java | 87 ++ .../web/inner/entity/SysUserGroupDetail.java | 35 + .../starter/web/inner/entity/SysUserRole.java | 36 + .../web/inner/entity/SysUserTelephone.java | 28 + .../starter/web/inner/entity/Tenant.java | 78 ++ .../web/inner/enums/system/Available.java | 32 + .../web/inner/enums/system/Gender.java | 31 + .../web/inner/enums/system/NodeType.java | 7 + .../web/inner/enums/system/QrtzJobType.java | 33 + .../system/SysDataPermissionDataBizType.java | 31 + .../SysDataPermissionModelDetailCalcType.java | 39 + ...ataPermissionModelDetailConditionType.java | 43 + ...SysDataPermissionModelDetailInputType.java | 33 + .../SysDataPermissionModelDetailNodeType.java | 32 + .../inner/enums/system/SysDeptNodeType.java | 20 + .../system/SysMailMessageSendStatus.java | 32 + .../enums/system/SysMenuComponentType.java | 32 + .../inner/enums/system/SysMenuDisplay.java | 32 + .../enums/system/SysNotifyMessageType.java | 32 + .../enums/system/SysNotifyReceiverType.java | 32 + .../web/inner/enums/system/TriggerState.java | 34 + .../web/inner/enums/system/UploadType.java | 31 + .../events/system/DeleteSysDeptEvent.java | 17 + .../system/DeleteSysNotifyGroupEvent.java | 17 + .../events/system/DeleteSysRoleEvent.java | 17 + .../events/system/DeleteSysUserEvent.java | 17 + .../system/DeleteSysUserGroupEvent.java | 17 + .../AccessDeniedExceptionConverter.java | 22 + .../exception/BindExceptionConverter.java | 57 + .../exception/ClientExceptionConverter.java | 27 + ...ConstraintViolationExceptionConverter.java | 31 + .../exception/ExceptionConverter.java | 24 + .../FileUploadExceptionConverter.java | 25 + ...pMessageNotReadableExceptionConverter.java | 28 + ...tMethodNotSupportedExceptionConverter.java | 28 + ...hodArgumentNotValidExceptionConverter.java | 31 + .../NotPermissionExceptionConverter.java | 28 + .../exception/SysExceptionConverter.java | 28 + .../TypeMismatchExceptionConverter.java | 47 + .../UnexpectedTypeExceptionConverter.java | 29 + .../inner/impl/DefaultUserDetailsService.java | 27 + .../web/inner/impl/DicCityServiceImpl.java | 63 ++ .../inner/impl/GenerateCodeServiceImpl.java | 36 + .../web/inner/impl/MailServiceImpl.java | 63 ++ .../web/inner/impl/OpLogsServiceImpl.java | 121 +++ .../inner/impl/OrderTimeLineServiceImpl.java | 46 + .../web/inner/impl/QrtzServiceImpl.java | 202 ++++ .../impl/RecursionMappingServiceImpl.java | 113 ++ .../impl/SecurityUploadRecordServiceImpl.java | 30 + .../web/inner/impl/SysModuleServiceImpl.java | 15 + .../impl/SysModuleTenantServiceImpl.java | 94 ++ .../web/inner/impl/TenantServiceImpl.java | 182 ++++ .../system/SysDataDicCategoryServiceImpl.java | 131 +++ .../system/SysDataDicItemServiceImpl.java | 157 +++ .../impl/system/SysDataDicServiceImpl.java | 146 +++ .../SysDataPermissionDataServiceImpl.java | 34 + ...sDataPermissionModelDetailServiceImpl.java | 146 +++ .../inner/impl/system/SysDeptServiceImpl.java | 285 +++++ .../system/SysGenerateCodeServiceImpl.java | 142 +++ .../system/SysMailMessageServiceImpl.java | 43 + .../inner/impl/system/SysMenuServiceImpl.java | 484 +++++++++ .../impl/system/SysNoticeLogServiceImpl.java | 29 + .../impl/system/SysNoticeServiceImpl.java | 259 +++++ .../SysNotifyGroupReceiverServiceImpl.java | 32 + .../system/SysNotifyGroupServiceImpl.java | 271 +++++ .../impl/system/SysOpenDomainServiceImpl.java | 108 ++ .../impl/system/SysParameterServiceImpl.java | 221 ++++ .../system/SysRoleCategoryServiceImpl.java | 133 +++ .../impl/system/SysRoleMenuServiceImpl.java | 123 +++ .../inner/impl/system/SysRoleServiceImpl.java | 273 +++++ .../system/SysSiteMessageServiceImpl.java | 121 +++ .../impl/system/SysUserDeptServiceImpl.java | 128 +++ .../system/SysUserGroupDetailServiceImpl.java | 27 + .../impl/system/SysUserGroupServiceImpl.java | 184 ++++ .../impl/system/SysUserRoleServiceImpl.java | 106 ++ .../inner/impl/system/SysUserServiceImpl.java | 400 ++++++++ .../system/SysUserTelephoneServiceImpl.java | 14 + .../inner/listeners/OpLogTimerListener.java | 87 ++ ...ifyGroupForDeleteSysUserGroupListener.java | 24 + .../SysUserDeptForDeleteSysDeptListener.java | 27 + .../SysUserRoleForDeleteSysRoleListener.java | 31 + .../web/inner/mappers/DicCityMapper.java | 33 + .../web/inner/mappers/GenerateCodeMapper.java | 8 + .../web/inner/mappers/OpLogsMapper.java | 42 + .../inner/mappers/OrderTimeLineMapper.java | 12 + .../starter/web/inner/mappers/QrtzMapper.java | 31 + .../inner/mappers/RecursionMappingMapper.java | 20 + .../mappers/SecurityUploadRecordMapper.java | 13 + .../web/inner/mappers/SysModuleMapper.java | 8 + .../inner/mappers/SysModuleTenantMapper.java | 8 + .../web/inner/mappers/TenantMapper.java | 34 + .../web/inner/mappers/UserDetailsMapper.java | 20 + .../system/SysDataDicCategoryMapper.java | 33 + .../mappers/system/SysDataDicItemMapper.java | 31 + .../mappers/system/SysDataDicMapper.java | 39 + .../system/SysDataPermissionDataMapper.java | 9 + .../SysDataPermissionModelDetailMapper.java | 9 + .../inner/mappers/system/SysDeptMapper.java | 34 + .../mappers/system/SysGenerateCodeMapper.java | 26 + .../mappers/system/SysMailMessageMapper.java | 26 + .../inner/mappers/system/SysMenuMapper.java | 114 ++ .../mappers/system/SysNoticeLogMapper.java | 15 + .../inner/mappers/system/SysNoticeMapper.java | 45 + .../mappers/system/SysNotifyGroupMapper.java | 41 + .../system/SysNotifyGroupReceiverMapper.java | 22 + .../mappers/system/SysOpenDomainMapper.java | 41 + .../mappers/system/SysParameterMapper.java | 32 + .../mappers/system/SysRoleCategoryMapper.java | 33 + .../inner/mappers/system/SysRoleMapper.java | 60 ++ .../mappers/system/SysRoleMenuMapper.java | 16 + .../mappers/system/SysSiteMessageMapper.java | 35 + .../mappers/system/SysUserDeptMapper.java | 41 + .../system/SysUserGroupDetailMapper.java | 15 + .../mappers/system/SysUserGroupMapper.java | 42 + .../inner/mappers/system/SysUserMapper.java | 100 ++ .../mappers/system/SysUserRoleMapper.java | 33 + .../system/SysUserTelephoneMapper.java | 8 + .../web/inner/service/DicCityService.java | 33 + .../inner/service/GenerateCodeService.java | 31 + .../inner/service/GroovySupportService.java | 10 + .../web/inner/service/MailService.java | 75 ++ .../web/inner/service/OpLogsService.java | 59 ++ .../inner/service/OrderTimeLineService.java | 26 + .../web/inner/service/QrtzService.java | 80 ++ .../service/RecursionMappingService.java | 63 ++ .../service/SecurityUploadRecordService.java | 19 + .../web/inner/service/SysConfService.java | 80 ++ .../web/inner/service/SysModuleService.java | 7 + .../inner/service/SysModuleTenantService.java | 31 + .../web/inner/service/TenantService.java | 69 ++ .../system/SysDataDicCategoryService.java | 64 ++ .../service/system/SysDataDicItemService.java | 82 ++ .../service/system/SysDataDicService.java | 76 ++ .../system/SysDataPermissionDataService.java | 27 + .../SysDataPermissionModelDetailService.java | 30 + .../inner/service/system/SysDeptService.java | 57 + .../system/SysGenerateCodeService.java | 72 ++ .../service/system/SysMailMessageService.java | 37 + .../inner/service/system/SysMenuService.java | 142 +++ .../service/system/SysNoticeLogService.java | 20 + .../service/system/SysNoticeService.java | 109 ++ .../system/SysNotifyGroupReceiverService.java | 25 + .../service/system/SysNotifyGroupService.java | 80 ++ .../service/system/SysOpenDomainService.java | 54 + .../service/system/SysParameterService.java | 64 ++ .../system/SysRoleCategoryService.java | 64 ++ .../service/system/SysRoleMenuService.java | 15 + .../inner/service/system/SysRoleService.java | 74 ++ .../service/system/SysSiteMessageService.java | 77 ++ .../service/system/SysUserDeptService.java | 41 + .../system/SysUserGroupDetailService.java | 17 + .../service/system/SysUserGroupService.java | 71 ++ .../service/system/SysUserRoleService.java | 32 + .../inner/service/system/SysUserService.java | 131 +++ .../system/SysUserTelephoneService.java | 8 + .../web/inner/vo/openapi/OpenApiReqVo.java | 43 + .../web/inner/vo/oplogs/CreateOpLogsVo.java | 52 + .../web/inner/vo/oplogs/QueryOpLogsVo.java | 48 + .../web/inner/vo/qrtz/CreateQrtzVo.java | 92 ++ .../web/inner/vo/qrtz/QueryQrtzVo.java | 42 + .../web/inner/vo/qrtz/UpdateQrtzVo.java | 32 + .../vo/system/config/UpdateSysConfigVo.java | 97 ++ .../inner/vo/system/dept/CreateSysDeptVo.java | 49 + .../vo/system/dept/SysDeptSelectorVo.java | 12 + .../vo/system/dept/SysUserDeptSettingVo.java | 32 + .../inner/vo/system/dept/UpdateSysDeptVo.java | 56 + .../vo/system/dic/CreateSysDataDicVo.java | 44 + .../vo/system/dic/QuerySysDataDicVo.java | 37 + .../vo/system/dic/SysDataDicSelectorVo.java | 29 + .../vo/system/dic/UpdateSysDataDicVo.java | 51 + .../category/CreateSysDataDicCategoryVo.java | 38 + .../category/QuerySysDataDicCategoryVo.java | 21 + .../SysDataDicCategorySelectorVo.java | 23 + .../category/UpdateSysDataDicCategoryVo.java | 45 + .../dic/item/CreateSysDataDicItemVo.java | 52 + .../dic/item/QuerySysDataDicItemVo.java | 39 + .../dic/item/UpdateSysDataDicItemVo.java | 52 + .../generate/CreateSysGenerateCodeVo.java | 29 + .../generate/PreviewSysGenerateCodeVo.java | 23 + .../generate/QuerySysGenerateCodeVo.java | 23 + .../generate/SettingSysGenerateCodeVo.java | 31 + .../generate/UpdateSysGenerateCodeVo.java | 29 + .../inner/vo/system/menu/CreateSysMenuVo.java | 121 +++ .../inner/vo/system/menu/QuerySysMenuVo.java | 21 + .../vo/system/menu/SysMenuSelectorVo.java | 30 + .../inner/vo/system/menu/UpdateSysMenuVo.java | 31 + .../message/mail/QuerySysMailMessageVo.java | 48 + .../site/QuerySysSiteMessageByUserVo.java | 49 + .../message/site/QuerySysSiteMessageVo.java | 43 + .../vo/system/module/SysModuleTenantVo.java | 51 + .../vo/system/notice/CreateSysNoticeVo.java | 39 + .../system/notice/QuerySysNoticeByUserVo.java | 49 + .../vo/system/notice/QuerySysNoticeVo.java | 43 + .../vo/system/notice/UpdateSysNoticeVo.java | 53 + .../system/notify/CreateSysNotifyGroupVo.java | 54 + .../system/notify/QuerySysNotifyGroupVo.java | 36 + .../notify/SysNotifyGroupSelectorVo.java | 20 + .../system/notify/UpdateSysNotifyGroupVo.java | 18 + .../vo/system/open/CreateSysOpenDomainVo.java | 42 + .../vo/system/open/QuerySysOpenDomainVo.java | 32 + .../system/open/SysOpenDomainSelectorVo.java | 32 + .../open/UpdateSysOpenDomainSecretVo.java | 29 + .../vo/system/open/UpdateSysOpenDomainVo.java | 50 + .../parameter/CreateSysParameterVo.java | 44 + .../system/parameter/QuerySysParameterVo.java | 45 + .../parameter/UpdateSysParameterVo.java | 41 + .../CreateSysDataPermissionDataVo.java | 46 + .../SysDataPermissionModelDetailVo.java | 66 ++ .../inner/vo/system/role/CreateSysRoleVo.java | 49 + .../inner/vo/system/role/QuerySysRoleVo.java | 32 + .../vo/system/role/SysRoleMenuSettingVo.java | 25 + .../vo/system/role/SysRoleSelectorVo.java | 26 + .../inner/vo/system/role/UpdateSysRoleVo.java | 56 + .../category/CreateSysRoleCategoryVo.java | 30 + .../category/SysRoleCategorySelectorVo.java | 23 + .../category/UpdateSysRoleCategoryVo.java | 38 + .../vo/system/tenant/CreateTenantVo.java | 56 + .../inner/vo/system/tenant/QueryTenantVo.java | 32 + .../vo/system/tenant/TenantSelectorVo.java | 32 + .../vo/system/tenant/UpdateTenantVo.java | 67 ++ .../inner/vo/system/user/CreateSysUserVo.java | 91 ++ .../system/user/GetLoginCaptchaRequireVo.java | 36 + .../user/GetTelephoneLoginCaptchaVo.java | 24 + .../web/inner/vo/system/user/LoginVo.java | 55 + .../inner/vo/system/user/QuerySysUserVo.java | 50 + .../inner/vo/system/user/RegistUserVo.java | 52 + .../vo/system/user/SysUserRoleSettingVo.java | 34 + .../vo/system/user/SysUserSelectorVo.java | 38 + .../vo/system/user/TelephoneBindUserVo.java | 44 + .../vo/system/user/TelephoneLoginVo.java | 34 + .../inner/vo/system/user/UpdateSysUserVo.java | 92 ++ .../user/group/CreateSysUserGroupVo.java | 41 + .../user/group/QuerySysUserGroupVo.java | 42 + .../user/group/SysUserGroupSelectorVo.java | 26 + .../user/group/UpdateSysUserGroupVo.java | 18 + .../components/WsDataPushWorker.java | 92 ++ .../websocket/components/WsDataPusher.java | 13 + .../components/WsDataPusherImpl.java | 80 ++ .../components/WsSessionManager.java | 82 ++ .../web/websocket/constants/WsPool.java | 20 + .../starter/web/websocket/dto/WsPushData.java | 67 ++ .../web/websocket/entity/WsSession.java | 33 + .../websocket/events/UserConnectEvent.java | 31 + .../websocket/events/UserDisConnectEvent.java | 28 + .../web/websocket/handler/WsHandler.java | 113 ++ .../interceptor/WsHandshakeInterceptor.java | 38 + .../listener/WsUserConnectListener.java | 42 + .../listener/WsUserDisConnectListener.java | 44 + .../service/WsDataProcessService.java | 16 + .../starter/web/websocket/vo/WsVo.java | 22 + web-starter/src/main/java/lombok.config | 2 + .../main/resources/META-INF/spring.factories | 23 + ...ot.autoconfigure.AutoConfiguration.imports | 22 + .../main/resources/mappers/DicCityMapper.xml | 31 + .../resources/mappers/GenerateCodeMapper.xml | 8 + .../main/resources/mappers/OpLogsMapper.xml | 49 + .../src/main/resources/mappers/QrtzMapper.xml | 43 + .../mappers/RecursionMappingMappre.xml | 12 + .../resources/mappers/SysParameterMapper.xml | 46 + .../main/resources/mappers/TenantMapper.xml | 43 + .../resources/mappers/UserDetailsMapper.xml | 21 + .../system/SysDataDicCategoryMapper.xml | 46 + .../mappers/system/SysDataDicItemMapper.xml | 48 + .../mappers/system/SysDataDicMapper.xml | 63 ++ .../mappers/system/SysDeptMapper.xml | 22 + .../mappers/system/SysGenerateCodeMapper.xml | 31 + .../system/SysMailMessageMapper.xml.xml | 35 + .../mappers/system/SysMenuMapper.xml | 181 ++++ .../mappers/system/SysNoticeLogMapper.xml | 22 + .../mappers/system/SysNoticeMapper.xml | 101 ++ .../mappers/system/SysNotifyGroupMapper.xml | 39 + .../system/SysNotifyGroupReceiverMapper.xml | 17 + .../mappers/system/SysOpenDomainMapper.xml | 43 + .../mappers/system/SysRoleCategoryMapper.xml | 29 + .../mappers/system/SysRoleMapper.xml | 58 ++ .../mappers/system/SysSiteMessageMapper.xml | 56 + .../mappers/system/SysUserDeptMapper.xml | 32 + .../mappers/system/SysUserGroupMapper.xml | 45 + .../mappers/system/SysUserMapper.xml | 95 ++ .../mappers/system/SysUserRoleMapper.xml | 24 + 844 files changed, 52164 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/ApifoxUploaderProjectSetting.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 README.md create mode 100644 bpm-starter/README.md create mode 100644 bpm-starter/pom.xml create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/DetailFlowCategoryBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/QueryFlowCategoryTreeBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/DetailFlowDefinitionBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/FlowDefinitionSelectorBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/QueryFlowDefinitionBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/instance/QueryBusinessFlowInstanceBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryInstanceListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryMyTaskListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryTodoTaskListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmBeanAutoConfiguration.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmSwaggerAutoConfiguration.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/controller/BpmSelectorController.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowCategoryController.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowDefinitionController.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowInstanceController.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowTaskController.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowInstanceExtDto.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowTaskDto.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCategory.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuApproveHis.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuInstance.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowDefinitionWrapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowInstanceWrapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowTaskWrapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowCooperateType.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionActivityStatus.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionExtBizType.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionIsPublish.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowInstanceStatus.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowNodeType.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowSkipType.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmChartExtService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmDataFillHandler.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmHandlerSelectService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmPermissionHandler.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/exception/FlowExceptionConverter.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCategoryServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuApproveHisServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuInstanceServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowDefinitionWrapperServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowInstanceWrapperServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowTaskWrapperServiceImpl.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmBizListener.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmGlobalListener.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCategoryMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuApproveHisMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuInstanceMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowDefinitionWrapperMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowInstanceWrapperMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowTaskWrapperMapper.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCategoryService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuApproveHisService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuInstanceService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowDefinitionWrapperService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowInstanceWrapperService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowTaskWrapperService.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/transfers/FlowCuInstanceTransfer.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/CreateFlowCategoryVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/DetailFlowCategoryBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/GetFlowCategoryListVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/QueryFlowCategoryTreeBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/UpdateFlowCategoryVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/CreateFlowDefinitionVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/DetailFlowDefinitionBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionActivityStatusVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionPublishVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/UpdateFlowDefinitionVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryBusinessFlowInstanceBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryInstanceListVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApprovePassTaskVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApproveRefuseTaskVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryInstanceListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListBo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/RejectTaskVo.java create mode 100644 bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/UndoTaskVo.java create mode 100644 bpm-starter/src/main/java/lombok.config create mode 100644 bpm-starter/src/main/resources/META-INF/spring.factories create mode 100644 bpm-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 bpm-starter/src/main/resources/mappers/FlowDefinitionWrapperMapper.xml create mode 100644 bpm-starter/src/main/resources/mappers/FlowTaskWrapperMapper.xml create mode 100644 common/README.md create mode 100644 common/pom.xml create mode 100644 common/src/main/java/com/lframework/starter/common/constants/PatternPool.java create mode 100644 common/src/main/java/com/lframework/starter/common/constants/ResponseConstants.java create mode 100644 common/src/main/java/com/lframework/starter/common/constants/StringPool.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/BaseException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/ClientException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/SysException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/AccessDeniedException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/AuthExpiredException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultClientException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultSysException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/InputErrorException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/ParameterNotFoundException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/RepeatRequestException.java create mode 100644 common/src/main/java/com/lframework/starter/common/exceptions/impl/UserLoginException.java create mode 100644 common/src/main/java/com/lframework/starter/common/functions/SFunction.java create mode 100644 common/src/main/java/com/lframework/starter/common/locker/LockBuilder.java create mode 100644 common/src/main/java/com/lframework/starter/common/locker/Locker.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/ArrayUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/Assert.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/BeanUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/CollectionUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/DateUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/FileUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/IdWorker.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/MailUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/NumberUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/ObjectUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/ReflectUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/RegUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/StringUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/ThreadUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/XmlUtil.java create mode 100644 common/src/main/java/com/lframework/starter/common/utils/ZipUtil.java create mode 100644 common/src/main/java/lombok.config create mode 100644 mq-starter/README.md create mode 100644 mq-starter/activemq-starter/README.md create mode 100644 mq-starter/activemq-starter/pom.xml create mode 100644 mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/config/ActiveMqAutoConfiguration.java create mode 100644 mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/interceptors/ActiveMqTenantInterceptor.java create mode 100644 mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/producer/ActiveMqProducer.java create mode 100644 mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/queue/ActiveMqQueueDefinition.java create mode 100644 mq-starter/activemq-starter/src/main/java/lombok.config create mode 100644 mq-starter/activemq-starter/src/main/resources/META-INF/spring.factories create mode 100644 mq-starter/activemq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 mq-starter/mq-core/README.md create mode 100644 mq-starter/mq-core/pom.xml create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/ExportingExportTaskBo.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/FailExportTaskBo.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/SuccessExportTaskBo.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java create mode 100644 mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java create mode 100644 mq-starter/mq-core/src/main/resources/META-INF/spring.factories create mode 100644 mq-starter/mq-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml create mode 100644 mq-starter/pom.xml create mode 100644 mq-starter/rabbitmq-starter/README.md create mode 100644 mq-starter/rabbitmq-starter/pom.xml create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java create mode 100644 mq-starter/rabbitmq-starter/src/main/java/lombok.config create mode 100644 mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories create mode 100644 mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 pom.xml create mode 100644 web-starter/README.md create mode 100644 web-starter/pom.xml create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/CacheAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/KaptchaAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/TransactionAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/CacheProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/KaptchaProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/MailProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/SecretProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/UploadProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/WebProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/aop/OpenApiAspect.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/aop/OrderTimeLineLogAspect.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/aop/PermissionAspect.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/bo/BaseBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/bo/ExcelImportBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/bo/SuperBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/cache/CacheVariables.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/captcha/CaptchaValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelEventListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelImportListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelModel.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/excel/RequiredFieldStyleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/GenerateCodeFactory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/GenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CurrentDateTimeRuleGenerateCodeHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CustomRandomStrGenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/FlowGenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/SnowFlakeGenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/StaticStrGenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/UUIDGenerateCodeRuleHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/AbstractGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/GenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CurrentDateTimeGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CustomRandomStrGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/FlowGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/RandomIntGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/SnowFlakeGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/StaticStrGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/UUIDGenerateCodeRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/locker/DefaultLockBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/locker/LockFactory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/locker/RedisLockBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomAuthorizationInterceptor.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomJsonValueProvider.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomMagicFunction.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomSqlCache.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleEmail.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleSys.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/oplog/OpLogType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/permission/DataPermissionHandlerImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/permission/SysDataPermissionDataPermissionType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/DynamicQrtzJob.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzJob.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/redis/RedisHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResult.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultErrorBuilderWrapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/PageResult.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/Response.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/resp/ResponseErrorBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetails.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetailsService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandlerImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/DefaultUserDetails.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/PasswordEncoderWrapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermissionCalcType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermitAllService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityConstants.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetails.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetailsService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolver.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolverImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignFactory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/sign/DefaultCheckSignFactory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/sign/handler/DefaultCheckSignHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/sign/util/SignUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantContextHolder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantInterceptor.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultCallable.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultRunnable.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/timeline/OrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/trace/DefaultTraceBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/trace/TraceBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/UploadHandlerFactory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/UploadClient.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/CosUploadConfig.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/LocalUploadConfig.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/ObsUploadConfig.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/OssUploadConfig.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/dto/UploadDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/CosUploadClient.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/LocalUploadClient.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/ObsUploadClient.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/OssUploadClient.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/SecurityUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/UploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosSecurityUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalSecurityUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsSecurityUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssSecurityUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssUploadHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/CodeValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/EnumValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsCode.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsEnum.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJson.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonArray.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonObject.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsNumberPrecision.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonArrayValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonObjectValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/NumberPrecisionValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/Pattern.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/PatternValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/TypeMismatch.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrlValidator.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/constants/MyBatisStringPool.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/constants/MybatisConstants.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/constants/SqlMethodConstants.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/controller/BaseController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/controller/DefaultBaseController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/dto/BaseDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCaptchaDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCodeDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/dto/VoidDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/entity/BaseEntity.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/enums/BaseEnum.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/ClearTenantEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEventBuilder.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/ReloadTenantEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/event/SetTenantEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/handlers/DefaultBaseEntityFillHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/impl/BaseMpServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/injectors/MybatisPlusUpdateAllColumnInjector.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/interceptors/CustomSortInterceptor.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/interceptors/LoginInterceptor.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/interceptors/TenantInterceptorImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/listeners/TenantListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/mapper/BaseMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/service/BaseMpService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/service/BaseService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/ApplicationUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/BoUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/CacheUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/CronUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/DataSourceUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/EncryptUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/EnumUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelImportUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/FieldEncryptUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/GroovyUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/HttpUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/IdUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/JsonUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/OpLogUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/PageHelperUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/PageResultUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/RequestUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/ResponseUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/SimpleMap.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/SpelUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/TenantUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/TransactionUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/UploadUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/ValidateUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/utils/VideoUtil.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/vo/BaseVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/vo/PageVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/core/vo/SortPageVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/CollectMenuBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/ForgetPswUserInfoBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/LoginBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/MenuBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TelephoneLoginBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TenantRequireBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/oplog/OpLogInUserCenterBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/GetQrtzBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/QueryQrtzBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/GetSysDeptBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptTreeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/GetSysDataDicBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/QuerySysDataDicBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/SysDataDicSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/GetSysDataDicItemBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/QuerySysDataDicItemBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/SysDataDicItemBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/GetSysGenerateCodeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/QuerySysGenerateCodeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/GetSysMenuBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/QuerySysMenuBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/SysMenuSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/GetSysMailMessageBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/QuerySysMailMessageBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/GetSysSiteMessageBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QueryMySysSiteMessageBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QuerySysSiteMessageBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/module/QuerySysModuleBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/GetSysNoticeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QueryMySysNoticeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QuerySysNoticeBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/GetSysNotifyGroupBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/QuerySysNotifyGroupBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/SysNotifyGroupSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/GetSysOpenDomainBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/QuerySysOpenDomainBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/SysOpenDomainSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/GetOpLogBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/QueryOpLogBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/GetSysParameterBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/QuerySysParameterBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/SysDataPermissionModelDetailBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/GetSysRoleBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QueryRoleMenuBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QuerySysRoleBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/SysRoleSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/GetSysRoleCategoryBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/QuerySysRoleCategoryBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/SysRoleCategorySelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/GetTenantBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/QueryTenantBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/TenantSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/GetSysUserBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QuerySysUserBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QueryUserRoleBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/SysUserSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/GetSysUserGroupBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/QuerySysUserGroupBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/SysUserGroupSelectorBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/bo/usercenter/UserInfoBo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/AuthOpLogType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/OtherOpLogType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/SystemOpLogType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/OrderDataPermissionDataPermissionType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/ProductDataPermissionDataPermissionType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApprovePassOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApproveReturnOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CancelApproveOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CreateOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/NormalOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/SendOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/UpdateOrderTimeLineBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/AuthController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/QrtzController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/UserCenterController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/DefaultSysSelectorController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/OpLogController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicCategoryController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicItemController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionDataController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionModelDetailController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDeptController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysGenerateCodeController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMailMessageController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMenuController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysModuleController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNoticeController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNotifyGroupController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysOpenDomainController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysParameterController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleCategoryController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleMenuController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysSiteMessageController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserDeptController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserGroupController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserRoleController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/TenantController.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/dic/city/DicCityDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysMailMessageDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysNoticeTaskDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysSiteMessageDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/site/SiteMessageDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyParamsDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/order/ApprovePassOrderDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/qrtz/QrtzDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/LoginDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuMetaDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/UserInfoDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/QuerySysNoticeByUserDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/SysNoticeDto.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/DicCity.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/OpLogs.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/OrderTimeLine.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/RecursionMapping.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SecurityUploadRecord.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDic.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicCategory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicItem.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionData.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionModelDetail.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDept.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysGenerateCode.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMailMessage.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMenu.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModule.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModuleTenant.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotice.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNoticeLog.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroup.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroupReceiver.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysOpenDomain.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysParameter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRole.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleCategory.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleMenu.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysSiteMessage.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUser.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserDept.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroup.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroupDetail.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserRole.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserTelephone.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/entity/Tenant.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Available.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Gender.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/NodeType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/QrtzJobType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionDataBizType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailCalcType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailConditionType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailInputType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailNodeType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDeptNodeType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMailMessageSendStatus.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuComponentType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuDisplay.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyMessageType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyReceiverType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/TriggerState.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/UploadType.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysDeptEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysNotifyGroupEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysRoleEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserGroupEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/AccessDeniedExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/BindExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ClientExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ConstraintViolationExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/FileUploadExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpMessageNotReadableExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpRequestMethodNotSupportedExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/MethodArgumentNotValidExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/NotPermissionExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/SysExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/TypeMismatchExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/UnexpectedTypeExceptionConverter.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/DefaultUserDetailsService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/DicCityServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/GenerateCodeServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/MailServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/OpLogsServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/OrderTimeLineServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/QrtzServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/RecursionMappingServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/SecurityUploadRecordServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleTenantServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/TenantServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicCategoryServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicItemServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionDataServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionModelDetailServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDeptServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysGenerateCodeServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMailMessageServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMenuServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeLogServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupReceiverServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysOpenDomainServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysParameterServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleCategoryServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleMenuServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysSiteMessageServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserDeptServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupDetailServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserRoleServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserTelephoneServiceImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/listeners/OpLogTimerListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysNotifyGroupForDeleteSysUserGroupListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserDeptForDeleteSysDeptListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserRoleForDeleteSysRoleListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/DicCityMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/GenerateCodeMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OpLogsMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OrderTimeLineMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/QrtzMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/RecursionMappingMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SecurityUploadRecordMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleTenantMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/TenantMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/UserDetailsMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicCategoryMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicItemMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionDataMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionModelDetailMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDeptMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysGenerateCodeMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMailMessageMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMenuMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeLogMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupReceiverMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysOpenDomainMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysParameterMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleCategoryMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMenuMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysSiteMessageMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserDeptMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupDetailMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserRoleMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserTelephoneMapper.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/DicCityService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/GenerateCodeService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/GroovySupportService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/MailService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/OpLogsService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/OrderTimeLineService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/QrtzService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/RecursionMappingService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/SecurityUploadRecordService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/SysConfService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleTenantService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/TenantService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicCategoryService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicItemService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionDataService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionModelDetailService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDeptService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysGenerateCodeService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMailMessageService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMenuService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeLogService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupReceiverService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysOpenDomainService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysParameterService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleCategoryService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleMenuService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysSiteMessageService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserDeptService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupDetailService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserRoleService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserTelephoneService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/openapi/OpenApiReqVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/CreateOpLogsVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/QueryOpLogsVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/CreateQrtzVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/QueryQrtzVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/UpdateQrtzVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/config/UpdateSysConfigVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/CreateSysDeptVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysDeptSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysUserDeptSettingVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/UpdateSysDeptVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/CreateSysDataDicVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/QuerySysDataDicVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/SysDataDicSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/UpdateSysDataDicVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/QuerySysDataDicCategoryVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/CreateSysDataDicItemVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/QuerySysDataDicItemVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/CreateSysGenerateCodeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/PreviewSysGenerateCodeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/QuerySysGenerateCodeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/SettingSysGenerateCodeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/UpdateSysGenerateCodeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/CreateSysMenuVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/QuerySysMenuVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/SysMenuSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/UpdateSysMenuVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/mail/QuerySysMailMessageVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageByUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/module/SysModuleTenantVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/CreateSysNoticeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeByUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/UpdateSysNoticeVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/CreateSysNotifyGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/QuerySysNotifyGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/SysNotifyGroupSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/UpdateSysNotifyGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/CreateSysOpenDomainVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/QuerySysOpenDomainVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/SysOpenDomainSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/CreateSysParameterVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/QuerySysParameterVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/UpdateSysParameterVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/CreateSysDataPermissionDataVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/SysDataPermissionModelDetailVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/CreateSysRoleVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/QuerySysRoleVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleMenuSettingVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/UpdateSysRoleVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/CreateSysRoleCategoryVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/SysRoleCategorySelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/UpdateSysRoleCategoryVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/CreateTenantVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/QueryTenantVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/TenantSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/UpdateTenantVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/CreateSysUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetLoginCaptchaRequireVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/LoginVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/QuerySysUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/RegistUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserRoleSettingVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneBindUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneLoginVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/UpdateSysUserVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/CreateSysUserGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/QuerySysUserGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/SysUserGroupSelectorVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/UpdateSysUserGroupVo.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPushWorker.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusher.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusherImpl.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsSessionManager.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/constants/WsPool.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/dto/WsPushData.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/entity/WsSession.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserConnectEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserDisConnectEvent.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/handler/WsHandler.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/interceptor/WsHandshakeInterceptor.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserConnectListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserDisConnectListener.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/service/WsDataProcessService.java create mode 100644 web-starter/src/main/java/com/lframework/starter/web/websocket/vo/WsVo.java create mode 100644 web-starter/src/main/java/lombok.config create mode 100644 web-starter/src/main/resources/META-INF/spring.factories create mode 100644 web-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 web-starter/src/main/resources/mappers/DicCityMapper.xml create mode 100644 web-starter/src/main/resources/mappers/GenerateCodeMapper.xml create mode 100644 web-starter/src/main/resources/mappers/OpLogsMapper.xml create mode 100644 web-starter/src/main/resources/mappers/QrtzMapper.xml create mode 100644 web-starter/src/main/resources/mappers/RecursionMappingMappre.xml create mode 100644 web-starter/src/main/resources/mappers/SysParameterMapper.xml create mode 100644 web-starter/src/main/resources/mappers/TenantMapper.xml create mode 100644 web-starter/src/main/resources/mappers/UserDetailsMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysDataDicItemMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysDataDicMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysDeptMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysGenerateCodeMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysMailMessageMapper.xml.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysMenuMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysNoticeLogMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysNoticeMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysNotifyGroupMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysNotifyGroupReceiverMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysOpenDomainMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysRoleCategoryMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysRoleMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysSiteMessageMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysUserDeptMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysUserGroupMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysUserMapper.xml create mode 100644 web-starter/src/main/resources/mappers/system/SysUserRoleMapper.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/ApifoxUploaderProjectSetting.xml b/.idea/ApifoxUploaderProjectSetting.xml new file mode 100644 index 0000000..b6d5d14 --- /dev/null +++ b/.idea/ApifoxUploaderProjectSetting.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..6b044a6 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..514252d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,15 @@ + + + + {} + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7cb8bbe --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# framework —— 苍穹 ERP 基础开发框架 + +## 概述 + +framework 是苍穹 ERP 的基础开发框架层,基于 Spring Boot 3.2 / Spring Cloud 2023.0.5,提供 ERP 业务模块所需的通用能力整合。各模块以 starter 方式提供自动配置,业务模块只需引入对应依赖即可使用。 + +## 模块构成 + +| 模块 | 说明 | +|------|------| +| [common](./common) | 公共工具库(Hutool 封装、日志、邮件、HTTP 客户端、XML 解析、加密、ID 生成) | +| [web-starter](./web-starter) | Web 框架整合(MyBatis-Plus、Druid、Sa-Token、Redis、Quartz、EasyExcel、OSS、Magic-API、Knife4j、WebSocket) | +| [mq-starter](./mq-starter) | 消息队列抽象及实现(mq-core 抽象层 + activemq / rabbitmq 具体实现) | +| [bpm-starter](./bpm-starter) | 工作流引擎整合(Warm-Flow) | + +## 构建方式 + +```bash +cd framework +mvn clean install -DskipTests +``` + +## 技术要求 + +- Java 17 +- Maven 3.6+ +- Spring Boot 3.2.12 diff --git a/bpm-starter/README.md b/bpm-starter/README.md new file mode 100644 index 0000000..3f1a2db --- /dev/null +++ b/bpm-starter/README.md @@ -0,0 +1,29 @@ +# bpm-starter —— 工作流引擎集成 + +## 概述 + +bpm-starter 整合了 Warm-Flow 工作流引擎,为苍穹 ERP 提供审批流程能力。 + +## 核心能力 + +### 工作流引擎集成 +- **Warm-Flow** —— 国产工作流引擎,支持流程定义、实例管理、任务审批 +- **逻辑删除支持** —— 流程数据软删除配置 +- **数据自动填充** —— 操作人、操作时间等公共字段自动赋值 + +### 流程管理 API +- **流程分类管理** —— 流程分类的增删改查 +- **流程定义管理** —— 流程模型的部署、发布、版本管理 +- **流程实例管理** —— 发起、作废、查看流程实例 +- **流程任务管理** —— 待办任务、已办任务、我的发起 + +### 流程审批能力 +- **审批通过/驳回** —— 支持常规审批操作 +- **转办** —— 将任务转给他人处理 +- **审批历史** —— 完整的审批轨迹记录 +- **开始/结束节点回调** —— 流程事件监听 + +## 依赖 + +- Warm-Flow 1.7.4(MyBatis-Plus 版) +- Warm-Flow UI 插件(提供流程设计器 Web 界面) diff --git a/bpm-starter/pom.xml b/bpm-starter/pom.xml new file mode 100644 index 0000000..01c87b9 --- /dev/null +++ b/bpm-starter/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + com.lframework + framework + 1.0.0 + + + bpm-starter + + + + + com.lframework + mq-starter + ${jugg.version} + pom + import + + + + + + + com.lframework + web-starter + + + + org.dromara.warm + warm-flow-mybatis-plus-sb-starter + + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + + + + org.dromara.warm + warm-flow-plugin-ui-core + + + + com.lframework + mq-core + + + + org.dromara.warm + warm-flow-mybatis-plus-sb-starter + 1.7.4 + + + com.baomidou + mybatis-plus-boot-starter + + + + + \ No newline at end of file diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/DetailFlowCategoryBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/DetailFlowCategoryBo.java new file mode 100644 index 0000000..99c34b5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/DetailFlowCategoryBo.java @@ -0,0 +1,48 @@ +package com.lframework.starter.bpm.bo.flow.category; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class DetailFlowCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + /** + * 流程类型名称 + */ + @Schema(description = "流程类型名称") + private String name; + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; + + /** + * 父节点名称 + */ + @Schema(description = "父节点名称") + private String parentName; + + public DetailFlowCategoryBo(FlowCategory dto) { + super(dto); + } + + @Override + protected void afterInit(FlowCategory dto) { + if (StringUtil.isNotEmpty(dto.getParentId())) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory parent = flowCategoryService.findById(dto.getParentId()); + this.parentName = parent.getName(); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/QueryFlowCategoryTreeBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/QueryFlowCategoryTreeBo.java new file mode 100644 index 0000000..407f612 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/category/QueryFlowCategoryTreeBo.java @@ -0,0 +1,30 @@ +package com.lframework.starter.bpm.bo.flow.category; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.web.core.bo.BaseBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryFlowCategoryTreeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + /** + * 流程类型名称 + */ + @Schema(description = "流程类型名称") + private String name; + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; + + public QueryFlowCategoryTreeBo(FlowCategory dto) { + super(dto); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/DetailFlowDefinitionBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/DetailFlowDefinitionBo.java new file mode 100644 index 0000000..209ed00 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/DetailFlowDefinitionBo.java @@ -0,0 +1,66 @@ +package com.lframework.starter.bpm.bo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class DetailFlowDefinitionBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String code; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String name; + + /** + * 流程分类ID + */ + @Schema(description = "流程分类ID") + private String categoryId; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + @EnumConvert + private Integer isPublish; + + public DetailFlowDefinitionBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryId = flowCategory.getId(); + this.categoryName = flowCategory.getName(); + + this.code = dto.getFlowCode(); + this.name = dto.getFlowName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/FlowDefinitionSelectorBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/FlowDefinitionSelectorBo.java new file mode 100644 index 0000000..31e93b6 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/FlowDefinitionSelectorBo.java @@ -0,0 +1,63 @@ +package com.lframework.starter.bpm.bo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class FlowDefinitionSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 版本号 + */ + @Schema(description = "版本号") + private String version; + + /** + * 创建时间 + * @param dto + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + public FlowDefinitionSelectorBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryName = flowCategory.getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/QueryFlowDefinitionBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/QueryFlowDefinitionBo.java new file mode 100644 index 0000000..4f07066 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/definition/QueryFlowDefinitionBo.java @@ -0,0 +1,78 @@ +package com.lframework.starter.bpm.bo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryFlowDefinitionBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 版本号 + */ + @Schema(description = "版本号") + private String version; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + @EnumConvert + private Integer isPublish; + + /** + * 激活状态 + */ + @Schema(description = "激活状态") + @EnumConvert + private Integer activityStatus; + + /** + * 创建时间 + * @param dto + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + public QueryFlowDefinitionBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryName = flowCategory.getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/instance/QueryBusinessFlowInstanceBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/instance/QueryBusinessFlowInstanceBo.java new file mode 100644 index 0000000..8247cb5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/instance/QueryBusinessFlowInstanceBo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.bo.flow.instance; + +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.bpm.service.FlowCuInstanceService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryBusinessFlowInstanceBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + public QueryBusinessFlowInstanceBo(FlowInstanceWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowInstanceWrapper dto) { + FlowCuInstanceService flowCuInstanceService = ApplicationUtil.getBean( + FlowCuInstanceService.class); + + this.title = flowCuInstanceService.getById(dto.getId()).getTitle(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryInstanceListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryInstanceListBo.java new file mode 100644 index 0000000..b6abda5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryInstanceListBo.java @@ -0,0 +1,147 @@ +package com.lframework.starter.bpm.bo.flow.task; + +import cn.hutool.core.date.BetweenFormatter.Level; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryInstanceListBo extends BaseBo { + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + /** + * 流程结束时间 + */ + @Schema(description = "流程结束时间") + private LocalDateTime endTime; + + /** + * 流程执行时间 + */ + @Schema(description = "流程执行时间") + private String executeTime; + + public QueryInstanceListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + + if (dto.getEndTime() != null) { + this.executeTime = DateUtil.formatBetween( + LocalDateTimeUtil.between(dto.getStartTime(), dto.getEndTime()).getSeconds() * 1000L, + Level.SECOND); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryMyTaskListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryMyTaskListBo.java new file mode 100644 index 0000000..aa64a1c --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryMyTaskListBo.java @@ -0,0 +1,147 @@ +package com.lframework.starter.bpm.bo.flow.task; + +import cn.hutool.core.date.BetweenFormatter.Level; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryMyTaskListBo extends BaseBo { + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + /** + * 流程结束时间 + */ + @Schema(description = "流程结束时间") + private LocalDateTime endTime; + + /** + * 流程执行时间 + */ + @Schema(description = "流程执行时间") + private String executeTime; + + public QueryMyTaskListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + + if (dto.getEndTime() != null) { + this.executeTime = DateUtil.formatBetween( + LocalDateTimeUtil.between(dto.getStartTime(), dto.getEndTime()).getSeconds() * 1000L, + Level.SECOND); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryTodoTaskListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryTodoTaskListBo.java new file mode 100644 index 0000000..ee5dcab --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/bo/flow/task/QueryTodoTaskListBo.java @@ -0,0 +1,132 @@ +package com.lframework.starter.bpm.bo.flow.task; + +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryTodoTaskListBo extends BaseBo { + + /** + * 任务ID + */ + @Schema(description = "任务ID") + private String taskId; + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + public QueryTodoTaskListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmBeanAutoConfiguration.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmBeanAutoConfiguration.java new file mode 100644 index 0000000..f2b6fc4 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmBeanAutoConfiguration.java @@ -0,0 +1,57 @@ +package com.lframework.starter.bpm.config; + +import com.lframework.starter.bpm.controller.*; +import com.lframework.starter.bpm.handlers.BpmChartExtService; +import com.lframework.starter.bpm.handlers.BpmHandlerSelectService; +import com.lframework.starter.bpm.handlers.BpmPermissionHandler; +import com.lframework.starter.bpm.handlers.exception.FlowExceptionConverter; +import com.lframework.starter.bpm.impl.*; +import com.lframework.starter.bpm.listeners.BpmGlobalListener; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; + +@Slf4j +@Configuration +@Import({ + BpmSelectorController.class, + FlowCategoryController.class, + FlowDefinitionController.class, + FlowTaskController.class, + FlowInstanceController.class, + FlowCategoryServiceImpl.class, + FlowDefinitionWrapperServiceImpl.class, + FlowTaskWrapperServiceImpl.class, + FlowCuInstanceServiceImpl.class, + FlowInstanceWrapperServiceImpl.class, + FlowCuApproveHisServiceImpl.class, + BpmChartExtService.class, + BpmGlobalListener.class, +}) +@MapperScan("com.lframework.starter.bpm.**.mappers") +public class BpmBeanAutoConfiguration implements EnvironmentAware { + + @Bean + public BpmHandlerSelectService bpmHandlerSelectService() { + return new BpmHandlerSelectService(); + } + + @Bean + public BpmPermissionHandler bpmPermissionHandler() { + return new BpmPermissionHandler(); + } + + @Bean + public FlowExceptionConverter flowExceptionConverter() { + return new FlowExceptionConverter(); + } + + @Override + public void setEnvironment(Environment environment) { + log.info("bpm-starter加载完成"); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmSwaggerAutoConfiguration.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmSwaggerAutoConfiguration.java new file mode 100644 index 0000000..d9937e0 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/config/BpmSwaggerAutoConfiguration.java @@ -0,0 +1,18 @@ +package com.lframework.starter.bpm.config; + +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BpmSwaggerAutoConfiguration { + + @Bean("bpmApiDocket") + public GroupedOpenApi bpmApiDocket() { + return GroupedOpenApi.builder() + .group("审批流程模块") + .packagesToScan("com.lframework.starter.bpm") + .pathsToMatch("/**") + .build(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/BpmSelectorController.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/BpmSelectorController.java new file mode 100644 index 0000000..ab6da73 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/BpmSelectorController.java @@ -0,0 +1,75 @@ +package com.lframework.starter.bpm.controller; + +import com.lframework.starter.bpm.bo.flow.definition.FlowDefinitionSelectorBo; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowDefinitionWrapperService; +import com.lframework.starter.bpm.vo.flow.definition.FlowDefinitionSelectorVo; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * BPM选择器 + * + * @author zmj + */ +@Tag(name = "BPM选择器") +@Validated +@RestController +@RequestMapping("/selector/bpm") +public class BpmSelectorController extends DefaultBaseController { + + @Autowired + private FlowDefinitionWrapperService flowDefinitionWrapperService; + + /** + * 流程定义 + */ + @Operation(summary = "流程定义") + @GetMapping("/flow/definition") + public InvokeResult> selector( + @Valid FlowDefinitionSelectorVo vo) { + + PageResult pageResult = flowDefinitionWrapperService.selector( + getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(FlowDefinitionSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载流程定义 + */ + @Operation(summary = "加载流程定义") + @PostMapping("/flow/definition/load") + public InvokeResult> loadFlowDefinition( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = flowDefinitionWrapperService.listByIds(ids); + List results = datas.stream().map(FlowDefinitionSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowCategoryController.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowCategoryController.java new file mode 100644 index 0000000..afe9e9e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowCategoryController.java @@ -0,0 +1,128 @@ +package com.lframework.starter.bpm.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.bo.flow.category.DetailFlowCategoryBo; +import com.lframework.starter.bpm.bo.flow.category.QueryFlowCategoryTreeBo; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.bpm.service.FlowDefinitionWrapperService; +import com.lframework.starter.bpm.vo.flow.category.CreateFlowCategoryVo; +import com.lframework.starter.bpm.vo.flow.category.UpdateFlowCategoryVo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@Tag(name = "流程分类") +@Validated +@RestController +@RequestMapping("/flow/category") +public class FlowCategoryController extends DefaultBaseController { + + @Autowired + private FlowCategoryService flowCategoryService; + + @Autowired + private FlowDefinitionWrapperService flowDefinitionWrapperService; + + /** + * 根据ID查询 + * + * @param id + * @return + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "ID") + @GetMapping("/detail") + public InvokeResult detail( + @NotBlank(message = "ID不能为空!") String id) { + FlowCategory data = flowCategoryService.getById(id); + if (data == null) { + throw new DefaultClientException("分类不存在!"); + } + + return InvokeResultBuilder.success(new DetailFlowCategoryBo(data)); + } + + /** + * 查询列表 + * + * @return + */ + @Operation(summary = "查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List list = flowCategoryService.list(); + List results = list.stream().map(QueryFlowCategoryTreeBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 新增 + * + * @param vo + * @return + */ + @Operation(summary = "新增") + @PostMapping + public InvokeResult create(@RequestBody CreateFlowCategoryVo vo) { + return InvokeResultBuilder.success(flowCategoryService.create(vo)); + } + + /** + * 修改 + * + * @param vo + * @return + */ + @Operation(summary = "修改") + @PutMapping + public InvokeResult update(@RequestBody UpdateFlowCategoryVo vo) { + flowCategoryService.update(vo); + + flowCategoryService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + * + * @param id + * @return + */ + @Operation(summary = "根据ID删除") + @Parameter(name = "id", description = "ID") + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "ID不能为空!") String id) { + // 先查询有没有子节点,如果有子节点那么不允许删除 + Wrapper checkWrapper = Wrappers.lambdaQuery(FlowCategory.class) + .eq(FlowCategory::getParentId, id); + if (flowCategoryService.count(checkWrapper) > 0) { + throw new DefaultClientException("当前分类存在子分类,不允许删除!"); + } + + Wrapper queryDefinitionWrapper = Wrappers.lambdaQuery(FlowDefinitionWrapper.class) + .eq(FlowDefinitionWrapper::getCategory, id); + if (flowDefinitionWrapperService.count(queryDefinitionWrapper) > 0) { + throw new DefaultClientException("当前分类下存在流程定义,不允许删除!"); + } + flowCategoryService.removeById(id); + + flowCategoryService.cleanCacheByKey(id); + return InvokeResultBuilder.success(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowDefinitionController.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowDefinitionController.java new file mode 100644 index 0000000..d886116 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowDefinitionController.java @@ -0,0 +1,193 @@ +package com.lframework.starter.bpm.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.bpm.bo.flow.definition.DetailFlowDefinitionBo; +import com.lframework.starter.bpm.bo.flow.definition.QueryFlowDefinitionBo; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.enums.FlowDefinitionActivityStatus; +import com.lframework.starter.bpm.enums.FlowDefinitionIsPublish; +import com.lframework.starter.bpm.service.FlowDefinitionWrapperService; +import com.lframework.starter.bpm.vo.flow.definition.*; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Tag(name = "流程定义") +@Validated +@RestController +@RequestMapping("/flow/definition") +public class FlowDefinitionController extends DefaultBaseController { + + @Autowired + private DefService defService; + + @Autowired + private FlowDefinitionWrapperService flowDefinitionWrapperService; + + /** + * 查询列表 + * + * @return + */ + @Operation(summary = "查询列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryFlowDefinitionVo vo) { + PageHelperUtil.startPage(vo); + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowDefinitionWrapper.class) + .eq(!StringUtil.isBlank(vo.getCode()), FlowDefinitionWrapper::getFlowCode, vo.getCode()) + .like(!StringUtil.isBlank(vo.getName()), FlowDefinitionWrapper::getFlowName, vo.getName()) + .eq(!StringUtil.isBlank(vo.getVersion()), FlowDefinitionWrapper::getVersion, + vo.getVersion()) + .eq(!StringUtil.isBlank(vo.getCategoryId()), FlowDefinitionWrapper::getCategory, + vo.getCategoryId()) + .eq(vo.getIsPublish() != null, FlowDefinitionWrapper::getIsPublish, vo.getIsPublish()) + .eq(vo.getActivityStatus() != null, FlowDefinitionWrapper::getActivityStatus, + vo.getActivityStatus()) + .orderByDesc(FlowDefinitionWrapper::getCreateTime); + List datas = flowDefinitionWrapperService.list(queryWrapper); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + List results = datas.stream().map(QueryFlowDefinitionBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @Operation(summary = "查询详情") + @Parameter(name = "id", description = "ID") + @GetMapping("/detail") + public InvokeResult detail(@NotNull(message = "ID不能为空!") Long id) { + FlowDefinitionWrapper data = flowDefinitionWrapperService.getById(id); + if (data == null) { + throw new DefaultClientException("流程不存在!"); + } + + return InvokeResultBuilder.success(new DetailFlowDefinitionBo(data)); + } + + /** + * 新增 + * + * @param vo + * @return + */ + @Operation(summary = "新增") + @PostMapping + public InvokeResult create(@Valid CreateFlowDefinitionVo vo) { + + if (!CollectionUtil.isEmpty(defService.getByFlowCode(vo.getCode()))) { + throw new DefaultClientException("流程编号重复,请重新输入!"); + } + FlowDefinition definition = new FlowDefinition(); + definition.setFlowCode(vo.getCode()); + definition.setFlowName(vo.getName()); + definition.setCategory(vo.getCategoryId()); + definition.setVersion("1"); + definition.setIsPublish(FlowDefinitionIsPublish.N.getCode()); + definition.setFormCustom(StringPool.N); + definition.setActivityStatus(FlowDefinitionActivityStatus.ACTIVATE.getCode()); + + defService.saveAndInitNode(definition); + return InvokeResultBuilder.success(); + } + + /** + * 修改 + * + * @param vo + * @return + */ + @Operation(summary = "修改") + @PutMapping + public InvokeResult update(@Valid UpdateFlowDefinitionVo vo) { + flowDefinitionWrapperService.update(vo); + return InvokeResultBuilder.success(); + } + + /** + * 设置发布状态 + * + * @param vo + * @return + */ + @Operation(summary = "设置发布状态") + @PostMapping("/publish") + public InvokeResult setPublishStatus(@Valid SetFlowDefinitionPublishVo vo) { + if (vo.getIsPublish() == FlowDefinitionIsPublish.Y.getCode().intValue()) { + defService.publish(vo.getId()); + } else { + defService.unPublish(vo.getId()); + } + + return InvokeResultBuilder.success(); + } + + /** + * 设置激活状态 + * + * @param vo + * @return + */ + @Operation(summary = "设置激活状态") + @PostMapping("/activity") + public InvokeResult setActivityStatus(@Valid SetFlowDefinitionActivityStatusVo vo) { + if (vo.getActivityStatus() == FlowDefinitionActivityStatus.ACTIVATE.getCode().intValue()) { + defService.active(vo.getId()); + } else { + defService.unActive(vo.getId()); + } + + return InvokeResultBuilder.success(); + } + + /** + * 复制流程 + * + * @param vo + * @return + */ + @Operation(summary = "复制流程") + @PostMapping("/copy") + public InvokeResult copy(@Valid UpdateFlowDefinitionVo vo) { + flowDefinitionWrapperService.copy(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + * + * @param id + * @return + */ + @Operation(summary = "根据ID删除") + @Parameter(name = "id", description = "ID") + @DeleteMapping + public InvokeResult deleteById(@NotNull(message = "ID不能为空!") Long id) { + defService.removeDef(Collections.singletonList(id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowInstanceController.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowInstanceController.java new file mode 100644 index 0000000..5e6bbd6 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowInstanceController.java @@ -0,0 +1,68 @@ +package com.lframework.starter.bpm.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.bo.flow.instance.QueryBusinessFlowInstanceBo; +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.bpm.service.FlowInstanceWrapperService; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +@Tag(name = "流程实例") +@Validated +@RestController +@RequestMapping("/flow/instance") +public class FlowInstanceController extends DefaultBaseController { + + @Autowired + private FlowInstanceWrapperService flowInstanceWrapperService; + + /** + * 根据业务ID查询 + * + * @return + */ + @Operation(summary = "根据业务ID查询") + @Parameter(name = "businessId", description = "业务ID") + @GetMapping("/list/business") + public InvokeResult> listBusiness( + @NotNull(message = "业务ID不能为空!") String businessId) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowInstanceWrapper.class) + .eq(FlowInstanceWrapper::getBusinessId, businessId) + .orderByDesc(FlowInstanceWrapper::getCreateTime); + + List datas = flowInstanceWrapperService.list(queryWrapper); + + List results = datas.stream().map(QueryBusinessFlowInstanceBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "根据ID查询状态") + @Parameter(name = "id", description = "流程实例ID") + @GetMapping("/status") + public InvokeResult getStatus(@NotNull(message = "流程实例ID不能为空!") Long id) { + FlowInstanceWrapper instance = flowInstanceWrapperService.getById(id); + if(instance == null) { + throw new DefaultClientException("流程实例不存在!"); + } + return InvokeResultBuilder.success(instance.getFlowStatus().getCode()); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowTaskController.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowTaskController.java new file mode 100644 index 0000000..2cee829 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/controller/FlowTaskController.java @@ -0,0 +1,151 @@ +package com.lframework.starter.bpm.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.bo.flow.task.QueryInstanceListBo; +import com.lframework.starter.bpm.bo.flow.task.QueryMyTaskListBo; +import com.lframework.starter.bpm.bo.flow.task.QueryTodoTaskListBo; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.enums.FlowCooperateType; +import com.lframework.starter.bpm.service.FlowTaskWrapperService; +import com.lframework.starter.bpm.vo.flow.instance.QueryInstanceListVo; +import com.lframework.starter.bpm.vo.flow.task.*; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@Tag(name = "流程任务") +@Validated +@RestController +@RequestMapping("/flow/task") +public class FlowTaskController extends DefaultBaseController { + + @Autowired + private FlowTaskWrapperService flowTaskWrapperService; + + @Autowired + private TaskService taskService; + + @Autowired + private FlowNodeMapper flowNodeMapper; + + @Operation(summary = "查询待办任务列表") + @GetMapping("/list/todo") + public InvokeResult> queryTodoList( + @Valid QueryTodoTaskListVo vo) { + PageResult pageResult = flowTaskWrapperService.queryTodoList(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = datas.stream().map(QueryTodoTaskListBo::new).collect( + Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @Operation(summary = "查询我的发起列表") + @GetMapping("/list/my") + public InvokeResult> queryMyList( + @Valid QueryMyTaskListVo vo) { + PageResult pageResult = flowTaskWrapperService.queryMyList(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = datas.stream().map(QueryMyTaskListBo::new).collect( + Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @Operation(summary = "查询流程实例列表") + @GetMapping("/list/instance") + public InvokeResult> queryInstanceList( + @Valid QueryInstanceListVo vo) { + PageResult pageResult = flowTaskWrapperService.queryInstanceList(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = datas.stream().map(QueryInstanceListBo::new).collect( + Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @Operation(summary = "根据ID查询审核类型") + @Parameter(name = "id", description = "流程任务ID") + @GetMapping("/cooperate") + public InvokeResult getCooperateType(@NotNull(message = "流程任务ID不能为空!") Long id) { + Task task = taskService.getById(id); + if (task == null) { + throw new DefaultClientException("流程任务不存在!"); + } + Long definitionId = task.getDefinitionId(); + String nodeCode = task.getNodeCode(); + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowNode.class) + .eq(FlowNode::getDefinitionId, definitionId) + .eq(FlowNode::getNodeCode, nodeCode); + FlowNode flowNode = flowNodeMapper.selectOne(queryWrapper); + if (flowNode == null) { + throw new DefaultClientException("流程节点不存在!"); + } + + if (CooperateType.isCountersign(flowNode.getNodeRatio())) { + return InvokeResultBuilder.success(FlowCooperateType.ALL.getCode()); + } else if (CooperateType.isVoteSign(flowNode.getNodeRatio())) { + return InvokeResultBuilder.success(FlowCooperateType.VOTE.getCode()); + } else { + return InvokeResultBuilder.success(FlowCooperateType.NORMAL.getCode()); + } + } + + @Operation(summary = "审核通过") + @PostMapping("/approve/pass") + public InvokeResult approvePass(@Valid @RequestBody ApprovePassTaskVo vo) { + flowTaskWrapperService.approvePass(vo); + return InvokeResultBuilder.success(); + } + + @Operation(summary = "审核拒绝") + @PostMapping("/approve/refuse") + public InvokeResult approveRefuse(@Valid @RequestBody ApproveRefuseTaskVo vo) { + flowTaskWrapperService.approveRefuse(vo); + return InvokeResultBuilder.success(); + } + + @Operation(summary = "撤回") + @PostMapping("/undo") + public InvokeResult undo(@Valid @RequestBody UndoTaskVo vo) { + flowTaskWrapperService.undo(vo); + return InvokeResultBuilder.success(); + } + + @Operation(summary = "反对") + @PostMapping("/reject") + public InvokeResult reject(@Valid @RequestBody RejectTaskVo vo) { + flowTaskWrapperService.reject(vo); + return InvokeResultBuilder.success(); + } + + @Operation(summary = "终止") + @PostMapping("/termination") + public InvokeResult termination(@NotNull(message = "流程实例ID不能为空!") Long instanceId) { + flowTaskWrapperService.termination(instanceId); + return InvokeResultBuilder.success(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowInstanceExtDto.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowInstanceExtDto.java new file mode 100644 index 0000000..3a7f0bb --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowInstanceExtDto.java @@ -0,0 +1,22 @@ +package com.lframework.starter.bpm.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class FlowInstanceExtDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型 + */ + private String bizType; + + /** + * 业务标识 + */ + private String bizFlag; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowTaskDto.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowTaskDto.java new file mode 100644 index 0000000..214ed59 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/dto/FlowTaskDto.java @@ -0,0 +1,93 @@ +package com.lframework.starter.bpm.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class FlowTaskDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 任务ID + */ + private Long taskId; + + /** + * 任务标题 + */ + private String title; + + /** + * 业务ID + */ + private String businessId; + + /** + * 节点编号 + */ + private String nodeCode; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 节点类型 + */ + private Integer nodeType; + + /** + * 流程状态 + */ + private String flowStatus; + + /** + * 流程定义ID + */ + private Long flowId; + + /** + * 流程定义编号 + */ + private String flowCode; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义分类ID + */ + private String categoryId; + + /** + * 流程实例ID + */ + private Long instanceId; + + /** + * 流程实例扩展字段 + */ + private String ext; + + /** + * 流程发起人ID + */ + private String startById; + + /** + * 流程发起时间 + */ + private LocalDateTime startTime; + + /** + * 流程结束时间 + */ + private LocalDateTime endTime; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCategory.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCategory.java new file mode 100644 index 0000000..6aed810 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCategory.java @@ -0,0 +1,30 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("flow_cu_category") +public class FlowCategory extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "FlowCategory"; + + /** + * 主键 + */ + private String id; + /** + * 流程类型名称 + */ + private String name; + /** + * 父节点ID + */ + private String parentId; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuApproveHis.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuApproveHis.java new file mode 100644 index 0000000..c4f720b --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuApproveHis.java @@ -0,0 +1,77 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.bpm.enums.FlowSkipType; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("flow_cu_approve_his") +public class FlowCuApproveHis extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + + /** + * 流程定义ID + */ + private Long definitionId; + + /** + * 流程实例ID + */ + private Long instanceId; + + /** + * 节点编码 + */ + private String nodeCode; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 任务ID + */ + private Long taskId; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 说明 + */ + private String message; + + /** + * 审批类型 + */ + private FlowSkipType skipType; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuInstance.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuInstance.java new file mode 100644 index 0000000..c5bfa80 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowCuInstance.java @@ -0,0 +1,42 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("flow_cu_instance") +public class FlowCuInstance extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 标题 + */ + private String title; + /** + * 业务类型 + */ + private String bizType; + + /** + * 业务标识 + */ + private String bizFlag; + /** + * 发起时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowDefinitionWrapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowDefinitionWrapper.java new file mode 100644 index 0000000..76273d8 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowDefinitionWrapper.java @@ -0,0 +1,99 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.bpm.enums.FlowDefinitionActivityStatus; +import com.lframework.starter.bpm.enums.FlowDefinitionIsPublish; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("flow_definition") +public class FlowDefinitionWrapper extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId + private Long id; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @TableLogic(value = "0", delval = "1") + private String delFlag; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 流程编码 + */ + private String flowCode; + + /** + * 流程名称 + */ + private String flowName; + + /** + * 流程类别 + */ + private String category; + + /** + * 流程版本 + */ + private String version; + + /** + * 是否发布(0未开启 1开启) + */ + private FlowDefinitionIsPublish isPublish; + + /** + * 审批表单是否自定义(Y是 2否) + */ + private String formCustom; + + /** + * 审批表单是否自定义(Y是 2否) + */ + private String formPath; + + /** + * 流程激活状态(0挂起 1激活) + */ + private FlowDefinitionActivityStatus activityStatus; + + /** + * 监听器类型 + */ + private String listenerType; + + /** + * 监听器路径 + */ + private String listenerPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowInstanceWrapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowInstanceWrapper.java new file mode 100644 index 0000000..b5267aa --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowInstanceWrapper.java @@ -0,0 +1,102 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.bpm.enums.FlowDefinitionActivityStatus; +import com.lframework.starter.bpm.enums.FlowInstanceStatus; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("flow_instance") +public class FlowInstanceWrapper extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId + private Long id; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + @TableLogic(value = "0", delval = "1") + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程节点编码 每个流程的nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制 + */ + private String nodeCode; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 流程变量 + */ + private String variable; + + /** + * 流程状态(0待提交 1审批中 2审批通过 4终止 5作废 6撤销 8已完成 9已退回 10失效 11拿回) + */ + private FlowInstanceStatus flowStatus; + + /** + * 流程激活状态(0挂起 1激活) + */ + private FlowDefinitionActivityStatus activityStatus; + + /** + * 创建者 + */ + private String createBy; + + /** + * 流程定义json + */ + private String defJson; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowTaskWrapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowTaskWrapper.java new file mode 100644 index 0000000..776fe25 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/entity/FlowTaskWrapper.java @@ -0,0 +1,85 @@ +package com.lframework.starter.bpm.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("flow_task") +public class FlowTaskWrapper extends BaseEntity implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId + private Long id; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + @TableLogic(value = "0", delval = "1") + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程实例表id + */ + private Long instanceId; + + /** + * 节点编码 + */ + private String nodeCode; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程状态(0待提交 1审批中 2审批通过 4终止 5作废 6撤销 8已完成 9已退回 10失效 11拿回) + */ + private String flowStatus; + + /** + * 审批表单是否自定义(Y是 2否) + */ + private String formCustom; + + /** + * 审批表单 + */ + private String formPath; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowCooperateType.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowCooperateType.java new file mode 100644 index 0000000..ba7b5de --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowCooperateType.java @@ -0,0 +1,34 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowCooperateType implements BaseEnum { + NORMAL(0, "或签"), + ALL(1, "会签"), + VOTE(2, "票签") + ; + + @EnumValue + private final Integer code; + + private final String desc; + + FlowCooperateType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionActivityStatus.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionActivityStatus.java new file mode 100644 index 0000000..06e3b41 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionActivityStatus.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowDefinitionActivityStatus implements BaseEnum { + ACTIVATE(1, "已激活"), DEACTIVATE(0, "已挂起"); + + @EnumValue + private final Integer code; + + private final String desc; + + FlowDefinitionActivityStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionExtBizType.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionExtBizType.java new file mode 100644 index 0000000..7f3710e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionExtBizType.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowDefinitionExtBizType implements BaseEnum { + SYSTEM("system", "系统内部功能"); + + @EnumValue + private final String code; + + private final String desc; + + FlowDefinitionExtBizType(String code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionIsPublish.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionIsPublish.java new file mode 100644 index 0000000..2b1bc65 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowDefinitionIsPublish.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowDefinitionIsPublish implements BaseEnum { + Y(1, "已发布"), N(0, "未发布"), UNABLE(9, "失效"); + + @EnumValue + private final Integer code; + + private final String desc; + + FlowDefinitionIsPublish(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowInstanceStatus.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowInstanceStatus.java new file mode 100644 index 0000000..c9c3724 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowInstanceStatus.java @@ -0,0 +1,40 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowInstanceStatus implements BaseEnum { + CREATE("0", "待提交"), + APPROVING("1", "审核中"), + APPROVE_PASS("2", "审核通过"), + TERMINATION("4", "已终止"), + CANCEL("5", "已作废"), + UNDO("6", "已撤回"), + FINISH("8", "已完成"), + REFUSE("9", "已退回"), + INVALID("10", "已失效"), + REVOKE("11", "已驳回"); + + @EnumValue + private final String code; + + private final String desc; + + FlowInstanceStatus(String code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowNodeType.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowNodeType.java new file mode 100644 index 0000000..e19daa6 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowNodeType.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowNodeType implements BaseEnum { + START(0, "开始节点"), + TASK(1, "中间节点"), + END(2, "结束节点"), + EXCLUSIVE_GATEWAY(3, "互斥网关"), + PARALLEL_GATEWAY(4, "并行网关"); + + + @EnumValue + private final Integer code; + + private final String desc; + + FlowNodeType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowSkipType.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowSkipType.java new file mode 100644 index 0000000..c74aca3 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/enums/FlowSkipType.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum FlowSkipType implements BaseEnum { + START(0, "发起"), + APPROVE_PASS(1, "通过"), + APPROVE_REFUSE(2, "退回"), + UNDO(3, "撤回"), + REJECT(4, "反对"), + TERMINATION(5, "终止"); + + @EnumValue + private final Integer code; + + private final String desc; + + FlowSkipType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmChartExtService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmChartExtService.java new file mode 100644 index 0000000..f28775f --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmChartExtService.java @@ -0,0 +1,63 @@ +package com.lframework.starter.bpm.handlers; + +import com.lframework.starter.bpm.entity.FlowCuInstance; +import com.lframework.starter.bpm.service.FlowCuInstanceService; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.utils.RequestUtil; +import org.dromara.warm.flow.core.dto.DefJson; +import org.dromara.warm.flow.core.dto.PromptContent; +import org.dromara.warm.flow.ui.service.ChartExtService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Component +public class BpmChartExtService implements ChartExtService { + + @Autowired + private FlowCuInstanceService flowCuInstanceService; + + @Override + public void execute(DefJson defJson) { + String uri = RequestUtil.getRequest().getRequestURI(); + String instanceId = uri.substring(uri.lastIndexOf("/") + 1); + FlowCuInstance cuInstance = flowCuInstanceService.getById(instanceId); + defJson.setTopText(cuInstance.getTitle()); + + defJson.getNodeList().forEach(nodeJson -> { + Map extMap = nodeJson.getExtMap(); + if (CollectionUtil.isNotEmpty(extMap) && extMap.containsKey("handleInfos")) { + List> handleInfos = (List>) extMap.get( + "handleInfos"); + + for (int i = 0; i < handleInfos.size(); i++) { + Map handleInfo = handleInfos.get(i); + + PromptContent.InfoItem item = new PromptContent.InfoItem(); + item.setPrefix("处理人" + (handleInfos.size() > 1 ? (i + 1) : "") + ": "); + item.setContent((String) handleInfo.get("createBy")); + nodeJson.getPromptContent().getInfo().add(item); + + item = new PromptContent.InfoItem(); + item.setPrefix("处理方式: "); + item.setContent((String) handleInfo.get("skipType")); + nodeJson.getPromptContent().getInfo().add(item); + + item = new PromptContent.InfoItem(); + item.setPrefix("处理时间: "); + item.setContent((String) handleInfo.get("createTime")); + nodeJson.getPromptContent().getInfo().add(item); + + if (handleInfo.containsKey("message")) { + item = new PromptContent.InfoItem(); + item.setPrefix("说明: "); + item.setContent((String) handleInfo.get("message")); + nodeJson.getPromptContent().getInfo().add(item); + } + } + } + }); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmDataFillHandler.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmDataFillHandler.java new file mode 100644 index 0000000..2a0b300 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmDataFillHandler.java @@ -0,0 +1,21 @@ +package com.lframework.starter.bpm.handlers; + +import com.lframework.starter.web.core.utils.IdUtil; +import org.dromara.warm.flow.core.entity.RootEntity; +import org.dromara.warm.flow.core.handler.DataFillHandler; +import org.dromara.warm.flow.core.utils.ObjectUtil; + +import java.util.Objects; + +public class BpmDataFillHandler implements DataFillHandler { + + @Override + public void idFill(Object object) { + RootEntity entity = (RootEntity) object; + if (ObjectUtil.isNotNull(entity)) { + if (Objects.isNull(entity.getId())) { + entity.setId(IdUtil.getIdLong()); + } + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmHandlerSelectService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmHandlerSelectService.java new file mode 100644 index 0000000..a0af9a6 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmHandlerSelectService.java @@ -0,0 +1,230 @@ +package com.lframework.starter.bpm.handlers; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysDept; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.entity.SysUserDept; +import com.lframework.starter.web.inner.service.system.SysDeptService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import org.dromara.warm.flow.core.utils.CollUtil; +import org.dromara.warm.flow.ui.dto.HandlerFunDto; +import org.dromara.warm.flow.ui.dto.HandlerQuery; +import org.dromara.warm.flow.ui.dto.TreeFunDto; +import org.dromara.warm.flow.ui.service.HandlerSelectService; +import org.dromara.warm.flow.ui.vo.HandlerFeedBackVo; +import org.dromara.warm.flow.ui.vo.HandlerSelectVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class BpmHandlerSelectService implements HandlerSelectService { + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private SysDeptService sysDeptService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Override + public List getHandlerType() { + return Arrays.asList("用户", "角色", "部门"); + } + + @Override + public HandlerSelectVo getHandlerSelect(HandlerQuery handlerQuery) { + if ("角色".equals(handlerQuery.getHandlerType())) { + return getRole(handlerQuery); + } + + if ("部门".equals(handlerQuery.getHandlerType())) { + return getDept(handlerQuery); + } + + if ("用户".equals(handlerQuery.getHandlerType())) { + return getUser(handlerQuery); + } + + return new HandlerSelectVo(); + } + + @Override + public List handlerFeedback(List storageIds) { + List handlerFeedBackVos = new ArrayList<>(); + if (CollUtil.isEmpty(storageIds)) { + return handlerFeedBackVos; + } + + for (String storageId : storageIds) { + if (storageId.startsWith("role:")) { + String tmpId = storageId.substring(5); + SysRole role = sysRoleService.findById(tmpId); + + handlerFeedBackVos.add(new HandlerFeedBackVo(storageId, role.getName())); + } else if (storageId.startsWith("dept:")) { + String tmpId = storageId.substring(5); + SysDept dept = sysDeptService.findById(tmpId); + handlerFeedBackVos.add(new HandlerFeedBackVo(storageId, dept.getName())); + } else { + String tmpId = storageId; + SysUser user = sysUserService.findById(tmpId); + handlerFeedBackVos.add(new HandlerFeedBackVo(storageId, user.getName())); + } + } + return handlerFeedBackVos; + } + + /** + * 获取角色列表 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getRole(HandlerQuery query) { + // 查询角色列表 + LocalDateTime begTime = StringUtil.isBlank(query.getBeginTime()) ? null + : DateUtil.toLocalDateTime(DateUtil.parseDate(query.getBeginTime())); + LocalDateTime endTime = StringUtil.isBlank(query.getEndTime()) ? null + : DateUtil.toLocalDateTimeMax(DateUtil.parseDate(query.getEndTime())); + Wrapper queryWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(StringUtil.isNotBlank(query.getHandlerCode()), SysRole::getCode, query.getHandlerCode()) + .eq(SysRole::getAvailable, Boolean.TRUE) + .like(StringUtil.isNotBlank(query.getHandlerName()), SysRole::getName, + query.getHandlerName()) + .ge(begTime != null, SysRole::getCreateTime, begTime) + .le(endTime != null, SysRole::getCreateTime, endTime) + .orderByAsc(SysRole::getCode); + PageHelperUtil.startPage(query.getPageNum(), query.getPageSize()); + List roleList = sysRoleService.list(queryWrapper); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(roleList)); + long total = pageResult.getTotalCount(); + + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(roleList, total) + // 以下设置获取内置变量的Function + .setStorageId(role -> "role:" + role.getId()) // 前面拼接role: 是为了防止用户、角色的主键重复 + .setHandlerCode(SysRole::getCode) // 权限编码 + .setHandlerName(SysRole::getName) // 权限名称 + .setCreateTime(role -> DateUtil.formatDateTime(role.getCreateTime())); + + return getHandlerSelectVo(handlerFunDto); + } + + /** + * 获取部门列表 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getDept(HandlerQuery query) { + // 查询部门列表 + LocalDateTime begTime = StringUtil.isBlank(query.getBeginTime()) ? null + : DateUtil.toLocalDateTime(DateUtil.parseDate(query.getBeginTime())); + LocalDateTime endTime = StringUtil.isBlank(query.getEndTime()) ? null + : DateUtil.toLocalDateTimeMax(DateUtil.parseDate(query.getEndTime())); + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(StringUtil.isNotBlank(query.getHandlerCode()), SysDept::getCode, query.getHandlerCode()) + .eq(SysDept::getAvailable, Boolean.TRUE) + .like(StringUtil.isNotBlank(query.getHandlerName()), SysDept::getName, + query.getHandlerName()) + .ge(begTime != null, SysDept::getCreateTime, begTime) + .le(endTime != null, SysDept::getCreateTime, endTime) + .orderByAsc(SysDept::getCode); + PageHelperUtil.startPage(query.getPageNum(), query.getPageSize()); + List deptList = sysDeptService.list(queryWrapper); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(deptList)); + long total = pageResult.getTotalCount(); + + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(deptList, total) + .setStorageId(dept -> "dept:" + dept.getId()) // 前面拼接dept: 是为了防止用户、部门的主键重复 + .setHandlerCode(SysDept::getCode) + .setHandlerName(SysDept::getName) // 权限名称 + .setCreateTime(dept -> DateUtil.formatDateTime(dept.getCreateTime())); + + return getHandlerSelectVo(handlerFunDto); + } + + /** + * 获取用户列表, 同时构建左侧部门树状结构 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getUser(HandlerQuery query) { + // 查询用户列表 + LocalDateTime begTime = StringUtil.isBlank(query.getBeginTime()) ? null + : DateUtil.toLocalDateTime(DateUtil.parseDate(query.getBeginTime())); + LocalDateTime endTime = StringUtil.isBlank(query.getEndTime()) ? null + : DateUtil.toLocalDateTimeMax(DateUtil.parseDate(query.getEndTime())); + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(StringUtil.isNotBlank(query.getHandlerCode()), SysUser::getCode, query.getHandlerCode()) + .eq(SysUser::getAvailable, Boolean.TRUE) + .like(StringUtil.isNotBlank(query.getHandlerName()), SysUser::getName, + query.getHandlerName()) + .ge(begTime != null, SysUser::getCreateTime, begTime) + .le(endTime != null, SysUser::getCreateTime, endTime) + .inSql(StringUtil.isNotBlank(query.getGroupId()), SysUser::getId, + "SELECT user_id FROM sys_user_dept WHERE dept_id = " + query.getGroupId()) + .orderByAsc(SysUser::getCode); + PageHelperUtil.startPage(query.getPageNum(), query.getPageSize()); + List userList = sysUserService.list(queryWrapper); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(userList)); + long total = pageResult.getTotalCount(); + + // 查询部门列表,构建树状结构 + Wrapper queryDeptWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getAvailable, Boolean.TRUE) + .orderByAsc(SysDept::getCode); + List deptList = sysDeptService.list(queryDeptWrapper); + + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(userList, total) + .setStorageId(SysUser::getId) + .setHandlerCode(SysUser::getUsername) // 权限编码 + .setHandlerName(SysUser::getName) // 权限名称 + .setCreateTime(user -> DateUtil.formatDateTime(user.getCreateTime())) + .setGroupName(user -> { + + List userDeptList = sysUserDeptService.getByUserId(user.getId()); + Set deptNameList = userDeptList.stream().map(userDept -> { + SysDept dept = sysDeptService.findById(userDept.getDeptId()); + + return dept.getName(); + }).collect(Collectors.toSet()); + + return StringUtil.join(StringPool.STR_SPLIT_CN, deptNameList); + }); + + // 业务系统机构,转成组件内部左侧树列表能够显示的数据 + TreeFunDto treeFunDto = new TreeFunDto<>(deptList) + .setId(SysDept::getId) // 左侧树ID + .setName(SysDept::getName) // 左侧树名称 + .setParentId(SysDept::getParentId); // 左侧树父级ID + + return getHandlerSelectVo(handlerFunDto, treeFunDto); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmPermissionHandler.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmPermissionHandler.java new file mode 100644 index 0000000..8e3af22 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/BpmPermissionHandler.java @@ -0,0 +1,70 @@ +package com.lframework.starter.bpm.handlers; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.inner.entity.SysUserDept; +import com.lframework.starter.web.inner.entity.SysUserRole; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import org.dromara.warm.flow.core.handler.PermissionHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class BpmPermissionHandler implements PermissionHandler { + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Override + public List permissions() { + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + List userRoleList = sysUserRoleService.getByUserId(currentUser.getId()); + + List userDeptList = sysUserDeptService.getByUserId(currentUser.getId()); + + List permissions = new ArrayList<>(); + permissions.add(currentUser.getId()); + permissions.addAll( + userRoleList.stream().map(t -> "role:" + t.getRoleId()).collect(Collectors.toSet())); + permissions.addAll( + userDeptList.stream().map(t -> "dept:" + t.getDeptId()).collect(Collectors.toSet())); + + return permissions; + } + + @Override + public String getHandler() { + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + return currentUser == null ? null : currentUser.getId(); + } + + @Override + public List convertPermissions(List permissions) { + + List results = new ArrayList<>(); + for (String permission : permissions) { + if (permission.startsWith("role:")) { + String tmpId = permission.substring(5); + List userRoleList = sysUserRoleService.getByRoleId(tmpId); + results.addAll( + userRoleList.stream().map(SysUserRole::getUserId).collect(Collectors.toSet())); + } else if (permission.startsWith("dept:")) { + String tmpId = permission.substring(5); + List userDeptList = sysUserDeptService.getByDeptId(tmpId); + results.addAll( + userDeptList.stream().map(SysUserDept::getUserId).collect(Collectors.toSet())); + } else { + results.add(permission); + } + } + return results; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/exception/FlowExceptionConverter.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/exception/FlowExceptionConverter.java new file mode 100644 index 0000000..ede424e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/handlers/exception/FlowExceptionConverter.java @@ -0,0 +1,19 @@ +package com.lframework.starter.bpm.handlers.exception; + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.dromara.warm.flow.core.exception.FlowException; + +public class FlowExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof FlowException; + } + + @Override + public BaseException convert(Throwable e) { + return new DefaultClientException(e.getMessage()); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCategoryServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCategoryServiceImpl.java new file mode 100644 index 0000000..5bac189 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCategoryServiceImpl.java @@ -0,0 +1,59 @@ +package com.lframework.starter.bpm.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.mappers.FlowCategoryMapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.bpm.vo.flow.category.CreateFlowCategoryVo; +import com.lframework.starter.bpm.vo.flow.category.UpdateFlowCategoryVo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; + +@Service +public class FlowCategoryServiceImpl extends + BaseMpServiceImpl implements + FlowCategoryService { + + @Cacheable(value = FlowCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public FlowCategory findById(String id) { + return getById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateFlowCategoryVo vo) { + FlowCategory record = new FlowCategory(); + record.setName(vo.getName()); + if (!StringUtil.isEmpty(vo.getParentId())) { + record.setParentId(vo.getParentId()); + } else { + record.setParentId(StringPool.EMPTY_STR); + } + this.save(record); + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateFlowCategoryVo vo) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(FlowCategory.class) + .set(FlowCategory::getName, vo.getName()) + .eq(FlowCategory::getId, vo.getId()); + this.update(updateWrapper); + } + + @CacheEvict(value = FlowCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuApproveHisServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuApproveHisServiceImpl.java new file mode 100644 index 0000000..58ecfc8 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuApproveHisServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.starter.bpm.impl; + +import com.lframework.starter.bpm.entity.FlowCuApproveHis; +import com.lframework.starter.bpm.mappers.FlowCuApproveHisMapper; +import com.lframework.starter.bpm.service.FlowCuApproveHisService; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class FlowCuApproveHisServiceImpl extends + BaseMpServiceImpl implements + FlowCuApproveHisService { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuInstanceServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuInstanceServiceImpl.java new file mode 100644 index 0000000..75ac082 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowCuInstanceServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.starter.bpm.impl; + +import com.lframework.starter.bpm.entity.FlowCuInstance; +import com.lframework.starter.bpm.mappers.FlowCuInstanceMapper; +import com.lframework.starter.bpm.service.FlowCuInstanceService; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class FlowCuInstanceServiceImpl extends + BaseMpServiceImpl implements + FlowCuInstanceService { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowDefinitionWrapperServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowDefinitionWrapperServiceImpl.java new file mode 100644 index 0000000..e787506 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowDefinitionWrapperServiceImpl.java @@ -0,0 +1,75 @@ +package com.lframework.starter.bpm.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.mappers.FlowDefinitionWrapperMapper; +import com.lframework.starter.bpm.service.FlowDefinitionWrapperService; +import com.lframework.starter.bpm.vo.flow.definition.FlowDefinitionSelectorVo; +import com.lframework.starter.bpm.vo.flow.definition.UpdateFlowDefinitionVo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.service.DefService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class FlowDefinitionWrapperServiceImpl extends + BaseMpServiceImpl implements + FlowDefinitionWrapperService { + + @Autowired + private DefService defService; + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + FlowDefinitionSelectorVo vo) { + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateFlowDefinitionVo vo) { + Wrapper updateWrapper = Wrappers.lambdaUpdate( + FlowDefinitionWrapper.class) + .eq(FlowDefinitionWrapper::getId, vo.getId()) + .set(FlowDefinitionWrapper::getFlowName, vo.getName()) + .set(FlowDefinitionWrapper::getCategory, vo.getCategoryId()); + + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void copy(UpdateFlowDefinitionVo vo) { + Definition definition = defService.getById(vo.getId()); + if (definition == null) { + throw new DefaultClientException("流程不存在!"); + } + + defService.copyDef(vo.getId()); + + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowDefinitionWrapper.class) + .eq(FlowDefinitionWrapper::getFlowCode, definition.getFlowCode()) + .orderByDesc(FlowDefinitionWrapper::getCreateTime) + .last("LIMIT 1"); + FlowDefinitionWrapper flowDefinitionWrapper = this.getOne(queryWrapper); + + vo.setId(flowDefinitionWrapper.getId()); + this.update(vo); + + defService.unActive(flowDefinitionWrapper.getId()); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowInstanceWrapperServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowInstanceWrapperServiceImpl.java new file mode 100644 index 0000000..b41e221 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowInstanceWrapperServiceImpl.java @@ -0,0 +1,26 @@ +package com.lframework.starter.bpm.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.bpm.enums.FlowInstanceStatus; +import com.lframework.starter.bpm.mappers.FlowInstanceWrapperMapper; +import com.lframework.starter.bpm.service.FlowInstanceWrapperService; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class FlowInstanceWrapperServiceImpl extends + BaseMpServiceImpl implements + FlowInstanceWrapperService { + + @Override + public Boolean canRestart(String businessId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowInstanceWrapper.class) + .eq(FlowInstanceWrapper::getBusinessId, businessId) + .in(FlowInstanceWrapper::getFlowStatus, FlowInstanceStatus.CREATE, + FlowInstanceStatus.APPROVING).last("LIMIT 1"); + + return this.getOne(queryWrapper) == null; + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowTaskWrapperServiceImpl.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowTaskWrapperServiceImpl.java new file mode 100644 index 0000000..8f8a321 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/impl/FlowTaskWrapperServiceImpl.java @@ -0,0 +1,186 @@ +package com.lframework.starter.bpm.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowTaskWrapper; +import com.lframework.starter.bpm.enums.FlowInstanceStatus; +import com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper; +import com.lframework.starter.bpm.service.FlowTaskWrapperService; +import com.lframework.starter.bpm.vo.flow.instance.QueryInstanceListVo; +import com.lframework.starter.bpm.vo.flow.task.*; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.entity.User; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.enums.UserType; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.utils.CollUtil; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; + +@Service +public class FlowTaskWrapperServiceImpl extends + BaseMpServiceImpl implements + FlowTaskWrapperService { + + @Autowired + private TaskService taskService; + + @Autowired + private FlowNodeMapper flowNodeMapper; + + @Override + public PageResult queryTodoList(Integer pageIndex, Integer pageSize, + QueryTodoTaskListVo vo) { + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryTodoList(vo, + SecurityUtil.getCurrentUser().getId()); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult queryMyList(Integer pageIndex, Integer pageSize, + QueryMyTaskListVo vo) { + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryMyList(vo, + SecurityUtil.getCurrentUser().getId()); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult queryInstanceList(Integer pageIndex, Integer pageSize, + QueryInstanceListVo vo) { + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryInstanceList(vo); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassTaskVo vo) { + taskService.pass(vo.getTaskId(), vo.getMessage(), vo.getVariables()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseTaskVo vo) { + FlowParams flowParams = new FlowParams(); + flowParams.message(vo.getMessage()); + flowParams.skipType("REJECT"); + flowParams.flowStatus(FlowInstanceStatus.REFUSE.getCode()); + flowParams.variable(vo.getVariables()); + taskService.termination(vo.getTaskId(), flowParams); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void undo(UndoTaskVo vo) { + FlowParams flowParams = new FlowParams(); + flowParams.message(vo.getMessage()); + flowParams.skipType("REJECT"); + flowParams.flowStatus(FlowInstanceStatus.UNDO.getCode()); + flowParams.variable(vo.getVariables()); + flowParams.ignore(true); + taskService.terminationByInsId(vo.getInstanceId(), flowParams); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void reject(RejectTaskVo vo) { + + Task task = taskService.getById(vo.getTaskId()); + Long definitionId = task.getDefinitionId(); + String nodeCode = task.getNodeCode(); + Wrapper queryWrapper = Wrappers.lambdaQuery(FlowNode.class) + .eq(FlowNode::getDefinitionId, definitionId) + .eq(FlowNode::getNodeCode, nodeCode); + FlowNode flowNode = flowNodeMapper.selectOne(queryWrapper); + if (flowNode == null) { + throw new DefaultClientException("流程节点不存在!"); + } + + BigDecimal nodeRatio = flowNode.getNodeRatio(); + + // 办理人和转办人列表 + List todoList = FlowEngine.userService().listByAssociatedAndTypes(vo.getTaskId() + , UserType.APPROVAL.getKey(), UserType.TRANSFER.getKey(), UserType.DEPUTE.getKey()); + + String currentUserId = SecurityUtil.getCurrentUser().getId(); + // 判断办理人是否有办理权限 + User todoUser = CollUtil.getOne( + StreamUtils.filter(todoList, u -> Objects.equals(u.getProcessedBy(), currentUserId))); + if (ObjectUtil.isNull(todoUser)) { + throw new DefaultClientException(ExceptionCons.NOT_AUTHORITY); + } + + FlowParams terminationParams = new FlowParams(); + terminationParams.message(vo.getMessage()); + terminationParams.skipType("REJECT"); + terminationParams.flowStatus(FlowInstanceStatus.REVOKE.getCode()); + terminationParams.variable(vo.getVariables()); + + // 当只剩一位待办用户时,由当前用户决定走向 + if (todoList.size() == 1) { + taskService.termination(vo.getTaskId(), terminationParams); + return; + } + + // 查询会签票签已办列表 + List doneList = FlowEngine.hisTaskService().listByTaskIdAndCooperateTypes(task.getId() + , CooperateType.isCountersign(nodeRatio) ? CooperateType.COUNTERSIGN.getKey() + : CooperateType.VOTE.getKey()); + doneList = CollUtil.emptyDefault(doneList); + + // 所有人 + BigDecimal all = BigDecimal.ZERO.add(BigDecimal.valueOf(todoList.size())) + .add(BigDecimal.valueOf(doneList.size())); + + List doneRejectList = StreamUtils.filter(doneList + , hisTask -> Objects.equals(hisTask.getSkipType(), SkipType.REJECT.getKey())); + + // 计算驳回率 + BigDecimal rejectRatio = (BigDecimal.ONE) + .add(BigDecimal.valueOf(doneRejectList.size())) + .divide(all, 4, RoundingMode.HALF_UP).multiply(CooperateType.ONE_HUNDRED); + + if (rejectRatio.compareTo(CooperateType.ONE_HUNDRED.subtract(nodeRatio)) > 0) { + taskService.termination(vo.getTaskId(), terminationParams); + return; + } + + taskService.reject(vo.getTaskId(), vo.getMessage(), vo.getVariables()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void termination(Long instanceId) { + FlowParams flowParams = new FlowParams(); + flowParams.skipType("REJECT"); + flowParams.flowStatus(FlowInstanceStatus.TERMINATION.getCode()); + flowParams.ignore(true); + taskService.terminationByInsId(instanceId, flowParams); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmBizListener.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmBizListener.java new file mode 100644 index 0000000..fb59536 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmBizListener.java @@ -0,0 +1,65 @@ +package com.lframework.starter.bpm.listeners; + +import com.lframework.starter.bpm.dto.FlowInstanceExtDto; +import org.dromara.warm.flow.core.listener.ListenerVariable; + +public interface BpmBizListener { + + /** + * 是否匹配 + * + * @param ext + * @return + */ + boolean isMatch(FlowInstanceExtDto ext); + + + /** + * 开始监听器,任务开始办理时执行 + * + * @param ext 业务扩展信息 + * @param listenerVariable 监听器变量 + */ + default void start(FlowInstanceExtDto ext, ListenerVariable listenerVariable) { + } + + /** + * 分派监听器,动态修改代办任务信息 + * + * @param ext 业务扩展信息 + * @param listenerVariable 监听器变量 + */ + default void assignment(FlowInstanceExtDto ext, ListenerVariable listenerVariable) { + } + + /** + * 完成监听器,当前任务完成后执行 + * + * @param ext 业务扩展信息 + * @param listenerVariable 监听器变量 + * @param beforeListenerVariable 任务开始时的监听器变量 + */ + default void finish(FlowInstanceExtDto ext, ListenerVariable listenerVariable, + ListenerVariable beforeListenerVariable) { + } + + /** + * 业务完成监听器,流程完成时执行 + * + * @param businessId + * @param startById + */ + default void businessComplete(ListenerVariable listenerVariable, String businessId, + String startById) { + + } + + /** + * 创建监听器,任务创建时执行 + * + * @param ext 业务扩展信息 + * @param listenerVariable 监听器变量 + */ + default void create(FlowInstanceExtDto ext, ListenerVariable listenerVariable) { + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmGlobalListener.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmGlobalListener.java new file mode 100644 index 0000000..d11e328 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/listeners/BpmGlobalListener.java @@ -0,0 +1,368 @@ +package com.lframework.starter.bpm.listeners; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.bpm.dto.FlowInstanceExtDto; +import com.lframework.starter.bpm.entity.FlowCuApproveHis; +import com.lframework.starter.bpm.entity.FlowCuInstance; +import com.lframework.starter.bpm.enums.FlowInstanceStatus; +import com.lframework.starter.bpm.enums.FlowSkipType; +import com.lframework.starter.bpm.service.FlowCuApproveHisService; +import com.lframework.starter.bpm.service.FlowCuInstanceService; +import com.lframework.starter.bpm.transfers.FlowCuInstanceTransfer; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.core.service.MqProducerService; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.service.system.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.dto.*; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.handler.PermissionHandler; +import org.dromara.warm.flow.core.listener.GlobalListener; +import org.dromara.warm.flow.core.listener.ListenerVariable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class BpmGlobalListener implements GlobalListener { + + private static final ThreadLocal LISTENER_VARIABLE = new ThreadLocal<>(); + + @Autowired + private FlowCuInstanceService flowCuInstanceService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private FlowCuApproveHisService flowCuApproveHisService; + + @Autowired + private PermissionHandler permissionHandler; + + @Autowired + private MqProducerService mqProducerService; + + /** + * 开始监听器,任务开始办理时执行 + * + * @param listenerVariable 监听器变量 + */ + public void start(ListenerVariable listenerVariable) { + log.debug("全局开始监听器开始执行......"); + log.debug(JsonUtil.toJsonPrettyStr(listenerVariable)); + + LISTENER_VARIABLE.set(listenerVariable); + + if (FlowInstanceStatus.REFUSE.getCode() + .equals(listenerVariable.getFlowParams().getFlowStatus())) { + this.addHandleInfo(listenerVariable, FlowSkipType.APPROVE_REFUSE); + } else if (FlowInstanceStatus.UNDO.getCode() + .equals(listenerVariable.getFlowParams().getFlowStatus())) { + this.addHandleInfo(listenerVariable, FlowSkipType.UNDO); + } else if (FlowInstanceStatus.REVOKE.getCode() + .equals(listenerVariable.getFlowParams().getFlowStatus())) { + this.addHandleInfo(listenerVariable, FlowSkipType.REJECT); + } else if (FlowInstanceStatus.TERMINATION.getCode() + .equals(listenerVariable.getFlowParams().getFlowStatus())) { + this.addHandleInfo(listenerVariable, FlowSkipType.TERMINATION); + } else if ("PASS" + .equals(listenerVariable.getFlowParams().getSkipType())) { + if (!NodeType.START.getKey().equals(listenerVariable.getNode().getNodeType())) { + this.addHandleInfo(listenerVariable, FlowSkipType.APPROVE_PASS); + } + } else if (CooperateType.isVoteSign(listenerVariable.getNode().getNodeRatio()) + && "REJECT".equals(listenerVariable.getFlowParams().getSkipType())) { + this.addHandleInfo(listenerVariable, FlowSkipType.REJECT); + } + + FlowInstanceExtDto ext = parseExt(listenerVariable); + if (ext == null) { + log.info("扩展字段为空,不监听"); + return; + } + List bizListeners = parseBizListeners(ext); + + for (BpmBizListener bizListener : bizListeners) { + bizListener.start(ext, listenerVariable); + } + + log.debug("全局开始监听器执行结束......"); + } + + /** + * 分派监听器,动态修改代办任务信息 + * + * @param listenerVariable 监听器变量 + */ + public void assignment(ListenerVariable listenerVariable) { + log.debug("全局分派监听器开始执行......"); + log.debug(JsonUtil.toJsonPrettyStr(listenerVariable)); + + if (NodeType.START.getKey().equals(listenerVariable.getNode().getNodeType())) { + this.addHandleInfo(listenerVariable, FlowSkipType.START); + } + + FlowInstanceExtDto ext = parseExt(listenerVariable); + if (ext == null) { + log.info("扩展字段为空,不监听"); + return; + } + List bizListeners = parseBizListeners(ext); + + for (BpmBizListener bizListener : bizListeners) { + bizListener.assignment(ext, listenerVariable); + } + + log.debug("全局分派监听器执行结束......"); + } + + /** + * 完成监听器,当前任务完成后执行 + * + * @param listenerVariable 监听器变量 + */ + public void finish(ListenerVariable listenerVariable) { + log.debug("全局完成监听器开始执行......"); + log.debug(JsonUtil.toJsonPrettyStr(listenerVariable)); + + ListenerVariable beforeListenerVariable = LISTENER_VARIABLE.get(); + LISTENER_VARIABLE.remove(); + + LocalDateTime now = LocalDateTime.now(); + if (beforeListenerVariable.getInstance() == null) { + // 这里表示流程实例刚创建完成 + String title = FlowCuInstanceTransfer.getTitle(); + FlowCuInstanceTransfer.clearTitle(); + if (StringUtil.isBlank(title)) { + // 设置默认标题 + SysUser createBy = sysUserService.findById(listenerVariable.getInstance().getCreateBy()); + title = StringUtil.format("{}在{}发起的{}", createBy.getName(), + DateUtil.formatDateTime(now, "yyyy年MM月dd日HH时mm分ss秒"), + listenerVariable.getDefinition().getFlowName()); + } + FlowCuInstance flowCuInstance = new FlowCuInstance(); + flowCuInstance.setId(listenerVariable.getInstance().getId()); + flowCuInstance.setTitle(title); + flowCuInstance.setStartTime( + DateUtil.toLocalDateTime(listenerVariable.getInstance().getCreateTime())); + + FlowInstanceExtDto ext = parseExt(listenerVariable); + if (ext != null) { + flowCuInstance.setBizType(ext.getBizType()); + flowCuInstance.setBizFlag(ext.getBizFlag()); + } + flowCuInstanceService.save(flowCuInstance); + } + + FlowParams flowParams = beforeListenerVariable.getFlowParams(); + if ("PASS".equals(flowParams.getSkipType()) && FlowInstanceStatus.APPROVING.getCode() + .equals(listenerVariable.getInstance().getFlowStatus())) { + FlowCombine flowCombine = FlowEngine.defService() + .getFlowCombineNoDef(listenerVariable.getDefinition().getId()); + // 获取后续任务节点结合 + PathWayData pathWayData = new PathWayData().setInsId(listenerVariable.getInstance().getId()) + .setSkipType(flowParams.getSkipType()); + Node nextNode = FlowEngine.nodeService() + .getNextNode(listenerVariable.getNode(), flowParams.getNodeCode() + , flowParams.getSkipType(), pathWayData, flowCombine); + List nextNodes = FlowEngine.nodeService().getNextByCheckGateway(flowParams.getVariable() + , nextNode, pathWayData, flowCombine); + + if (CollectionUtil.isNotEmpty(nextNodes)) { + for (Node node : nextNodes) { + if (StringUtil.isBlank(node.getPermissionFlag())) { + continue; + } + List permissionFlagList = new ArrayList<>( + Arrays.asList(node.getPermissionFlag().split("@@"))); + + FlowCuInstance cuInstance = flowCuInstanceService.getById( + listenerVariable.getInstance().getId()); + SysUser startBy = sysUserService.findById(listenerVariable.getInstance().getCreateBy()); + List notifyUserIds = permissionHandler.convertPermissions(permissionFlagList); + SysSiteMessageDto siteMessageDto = new SysSiteMessageDto(); + siteMessageDto.setUserIdList( + notifyUserIds.stream().distinct().collect(Collectors.toList())); + siteMessageDto.setTitle("【" + node.getNodeName() + "】新的待审核流程"); + siteMessageDto.setContent( + StringUtil.format( + "您有待审核流程需要处理,请及时处理。流程标题:{},发起人:{},发起时间:{}。", + cuInstance.getTitle(), startBy.getName(), DateUtil.formatDateTime( + DateUtil.toLocalDateTime(listenerVariable.getInstance().getCreateTime()), + "yyyy年MM月dd日HH时mm分ss秒"))); + siteMessageDto.setBizKey(String.valueOf(listenerVariable.getInstance().getId())); + siteMessageDto.setCreateUserId(SecurityUtil.getCurrentUser().getId()); + + mqProducerService.createSysSiteMessage(siteMessageDto); + } + } + } + + if ("end".equals(listenerVariable.getInstance().getNodeCode())) { + this.endInstance(listenerVariable.getInstance().getId(), now); + } + + FlowInstanceExtDto ext = parseExt(listenerVariable); + if (ext == null) { + log.info("扩展字段为空,不监听"); + return; + } + List bizListeners = parseBizListeners(ext); + + for (BpmBizListener bizListener : bizListeners) { + bizListener.finish(ext, listenerVariable, beforeListenerVariable); + } + + // 这里单独把完成流程通知一下 + if ("end".equals(listenerVariable.getInstance().getNodeCode())) { + if (FlowInstanceStatus.FINISH.getCode() + .equals(listenerVariable.getInstance().getFlowStatus())) { + // 这里是完成了流程 + for (BpmBizListener bizListener : bizListeners) { + // 这里不用获取当前审核人,因为当前登录人就是审核人 + bizListener.businessComplete(listenerVariable, + listenerVariable.getInstance().getBusinessId(), + listenerVariable.getInstance().getCreateBy()); + } + } + } + + log.debug("全局完成监听器执行结束......"); + } + + /** + * 创建监听器,任务创建时执行 + * + * @param listenerVariable 监听器变量 + */ + public void create(ListenerVariable listenerVariable) { + log.debug("全局创建监听器开始执行......"); + log.debug(JsonUtil.toJsonPrettyStr(listenerVariable)); + + FlowInstanceExtDto ext = parseExt(listenerVariable); + if (ext == null) { + log.info("扩展字段为空,不监听"); + return; + } + List bizListeners = parseBizListeners(ext); + + for (BpmBizListener bizListener : bizListeners) { + bizListener.create(ext, listenerVariable); + } + + log.debug("全局创建监听器执行结束......"); + } + + private FlowInstanceExtDto parseExt(ListenerVariable listenerVariable) { + if (listenerVariable == null) { + return null; + } + if (listenerVariable.getInstance() == null) { + return null; + } + if (StringUtil.isBlank(listenerVariable.getInstance().getExt())) { + return null; + } + return JsonUtil.parseObject(listenerVariable.getInstance().getExt(), FlowInstanceExtDto.class); + } + + private List parseBizListeners(FlowInstanceExtDto ext) { + + Map bizListeners = ApplicationUtil.getBeansOfType(BpmBizListener.class); + + return bizListeners.values().stream().filter(bizListener -> bizListener.isMatch(ext)).collect( + Collectors.toList()); + } + + private void addHandleInfo(ListenerVariable listenerVariable, FlowSkipType skipType) { + + LocalDateTime now = LocalDateTime.now(); + String defJsonStr = listenerVariable.getInstance().getDefJson(); + + if (StringUtil.isNotBlank(defJsonStr)) { + DefJson defJson = FlowEngine.jsonConvert.strToBean(defJsonStr, DefJson.class); + for (NodeJson nodeJson : defJson.getNodeList()) { + if (nodeJson.getNodeCode().equals(listenerVariable.getNode().getNodeCode())) { + List> handleInfos = (List>) nodeJson.getExtMap() + .get("handleInfos"); + if (handleInfos == null) { + handleInfos = new ArrayList<>(); + nodeJson.getExtMap().put("handleInfos", new ArrayList<>()); + } + String userId = listenerVariable.getFlowParams().getHandler(); + SysUser sysUser = sysUserService.findById(userId); + + FlowCuApproveHis approveHis = new FlowCuApproveHis(); + approveHis.setId(IdUtil.getIdLong()); + approveHis.setDefinitionId(listenerVariable.getDefinition().getId()); + approveHis.setInstanceId(listenerVariable.getInstance().getId()); + approveHis.setNodeCode(nodeJson.getNodeCode()); + approveHis.setNodeName(nodeJson.getNodeName()); + approveHis.setTaskId( + listenerVariable.getTask() == null ? null : listenerVariable.getTask().getId()); + + Map handleInfo = new LinkedHashMap<>(); + if (sysUser != null && StringUtil.isNotEmpty(sysUser.getName())) { + approveHis.setCreateById(sysUser.getId()); + approveHis.setCreateBy(sysUser.getName()); + + handleInfo.put("createById", sysUser.getId()); + handleInfo.put("createBy", sysUser.getName()); + + if (listenerVariable.getFlowParams() != null && StringUtil.isNotBlank( + listenerVariable.getFlowParams().getMessage())) { + approveHis.setMessage(listenerVariable.getFlowParams().getMessage()); + + handleInfo.put("message", approveHis.getMessage()); + } + } + approveHis.setSkipType(skipType); + + handleInfo.put("skipType", skipType.getDesc()); + + approveHis.setCreateTime(now); + handleInfo.put("createTime", + DateUtil.formatDateTime(approveHis.getCreateTime(), "yyyy年MM月dd日HH时mm分ss秒")); + + flowCuApproveHisService.save(approveHis); + + handleInfos.add(handleInfo); + + nodeJson.getExtMap().put("handleInfos", handleInfos); + } + } + listenerVariable.getInstance().setDefJson(FlowEngine.jsonConvert.objToStr(defJson)); + + FlowEngine.insService().updateById(listenerVariable.getInstance()); + } + + if (skipType == FlowSkipType.APPROVE_REFUSE || skipType == FlowSkipType.UNDO + || skipType == FlowSkipType.TERMINATION) { + this.endInstance(listenerVariable.getInstance().getId(), now); + } + } + + private void endInstance(Long instanceId, LocalDateTime endTime) { + // 流程结束,记录结束时间 + Wrapper updateWrapper = Wrappers.lambdaUpdate(FlowCuInstance.class) + .set(FlowCuInstance::getEndTime, endTime) + .eq(FlowCuInstance::getId, instanceId); + flowCuInstanceService.update(updateWrapper); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCategoryMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCategoryMapper.java new file mode 100644 index 0000000..6d33064 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCategoryMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.web.core.mapper.BaseMapper; + +public interface FlowCategoryMapper extends BaseMapper { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuApproveHisMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuApproveHisMapper.java new file mode 100644 index 0000000..b4315af --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuApproveHisMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.entity.FlowCuApproveHis; +import com.lframework.starter.web.core.mapper.BaseMapper; + +public interface FlowCuApproveHisMapper extends BaseMapper { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuInstanceMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuInstanceMapper.java new file mode 100644 index 0000000..3d0468a --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowCuInstanceMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.entity.FlowCuInstance; +import com.lframework.starter.web.core.mapper.BaseMapper; + +public interface FlowCuInstanceMapper extends BaseMapper { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowDefinitionWrapperMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowDefinitionWrapperMapper.java new file mode 100644 index 0000000..fd91c53 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowDefinitionWrapperMapper.java @@ -0,0 +1,19 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.vo.flow.definition.FlowDefinitionSelectorVo; +import com.lframework.starter.web.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface FlowDefinitionWrapperMapper extends BaseMapper { + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") FlowDefinitionSelectorVo vo); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowInstanceWrapperMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowInstanceWrapperMapper.java new file mode 100644 index 0000000..c265ee1 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowInstanceWrapperMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.web.core.mapper.BaseMapper; + +public interface FlowInstanceWrapperMapper extends BaseMapper { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowTaskWrapperMapper.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowTaskWrapperMapper.java new file mode 100644 index 0000000..a8b7d78 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/mappers/FlowTaskWrapperMapper.java @@ -0,0 +1,39 @@ +package com.lframework.starter.bpm.mappers; + +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowTaskWrapper; +import com.lframework.starter.bpm.vo.flow.instance.QueryInstanceListVo; +import com.lframework.starter.bpm.vo.flow.task.QueryMyTaskListVo; +import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo; +import com.lframework.starter.web.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface FlowTaskWrapperMapper extends BaseMapper { + + /** + * 查询待办任务列表 + * + * @param vo + * @return + */ + List queryTodoList(@Param("vo") QueryTodoTaskListVo vo, + @Param("userId") String userId); + + /** + * 查询我的发起列表 + * + * @param vo + * @return + */ + List queryMyList(@Param("vo") QueryMyTaskListVo vo, @Param("userId") String userId); + + /** + * 查询流程实例列表 + * + * @param vo + * @return + */ + List queryInstanceList(@Param("vo") QueryInstanceListVo vo); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCategoryService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCategoryService.java new file mode 100644 index 0000000..5779d11 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCategoryService.java @@ -0,0 +1,33 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.vo.flow.category.CreateFlowCategoryVo; +import com.lframework.starter.bpm.vo.flow.category.UpdateFlowCategoryVo; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowCategoryService extends BaseMpService { + + /** + * 根据ID查询 + * + * @param id + * @return + */ + FlowCategory findById(String id); + + /** + * 新增 + * + * @param vo + * @return + */ + String create(CreateFlowCategoryVo vo); + + /** + * 修改 + * + * @param vo + * @return + */ + void update(UpdateFlowCategoryVo vo); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuApproveHisService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuApproveHisService.java new file mode 100644 index 0000000..80bf0ad --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuApproveHisService.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.entity.FlowCuApproveHis; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowCuApproveHisService extends BaseMpService { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuInstanceService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuInstanceService.java new file mode 100644 index 0000000..91fcbc6 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowCuInstanceService.java @@ -0,0 +1,8 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.entity.FlowCuInstance; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowCuInstanceService extends BaseMpService { + +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowDefinitionWrapperService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowDefinitionWrapperService.java new file mode 100644 index 0000000..ad13681 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowDefinitionWrapperService.java @@ -0,0 +1,35 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.vo.flow.definition.FlowDefinitionSelectorVo; +import com.lframework.starter.bpm.vo.flow.definition.UpdateFlowDefinitionVo; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowDefinitionWrapperService extends BaseMpService { + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + FlowDefinitionSelectorVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateFlowDefinitionVo vo); + + /** + * 复制 + * + * @param vo + */ + void copy(UpdateFlowDefinitionVo vo); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowInstanceWrapperService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowInstanceWrapperService.java new file mode 100644 index 0000000..4ad9b69 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowInstanceWrapperService.java @@ -0,0 +1,15 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowInstanceWrapperService extends BaseMpService { + + /** + * 是否可以重新发起 + * + * @param businessId + * @return + */ + Boolean canRestart(String businessId); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowTaskWrapperService.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowTaskWrapperService.java new file mode 100644 index 0000000..23fc653 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/service/FlowTaskWrapperService.java @@ -0,0 +1,79 @@ +package com.lframework.starter.bpm.service; + +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowTaskWrapper; +import com.lframework.starter.bpm.vo.flow.instance.QueryInstanceListVo; +import com.lframework.starter.bpm.vo.flow.task.*; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; + +public interface FlowTaskWrapperService extends BaseMpService { + + /** + * 查询待办任务列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryTodoList(Integer pageIndex, Integer pageSize, + QueryTodoTaskListVo vo); + + /** + * 查询我的发起列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryMyList(Integer pageIndex, Integer pageSize, + QueryMyTaskListVo vo); + + /** + * 查询流程实例列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryInstanceList(Integer pageIndex, Integer pageSize, + QueryInstanceListVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassTaskVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseTaskVo vo); + + /** + * 撤回 + * + * @param vo + */ + void undo(UndoTaskVo vo); + + /** + * 反对 + * + * @param vo + */ + void reject(RejectTaskVo vo); + + /** + * 终止 + * + * @param instanceId + */ + void termination(Long instanceId); +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/transfers/FlowCuInstanceTransfer.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/transfers/FlowCuInstanceTransfer.java new file mode 100644 index 0000000..b1a198f --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/transfers/FlowCuInstanceTransfer.java @@ -0,0 +1,18 @@ +package com.lframework.starter.bpm.transfers; + +public class FlowCuInstanceTransfer { + + private static final ThreadLocal TITLE_TRANS = new ThreadLocal<>(); + + public static void setTitle(String title) { + TITLE_TRANS.set(title); + } + + public static String getTitle() { + return TITLE_TRANS.get(); + } + + public static void clearTitle() { + TITLE_TRANS.remove(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/CreateFlowCategoryVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/CreateFlowCategoryVo.java new file mode 100644 index 0000000..173bde1 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/CreateFlowCategoryVo.java @@ -0,0 +1,23 @@ +package com.lframework.starter.bpm.vo.flow.category; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class CreateFlowCategoryVo implements BaseVo { + + public static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; + + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/DetailFlowCategoryBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/DetailFlowCategoryBo.java new file mode 100644 index 0000000..b8230b5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/DetailFlowCategoryBo.java @@ -0,0 +1,48 @@ +package com.lframework.starter.bpm.vo.flow.category; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class DetailFlowCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + /** + * 流程类型名称 + */ + @Schema(description = "流程类型名称") + private String name; + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; + + /** + * 父节点名称 + */ + @Schema(description = "父节点名称") + private String parentName; + + public DetailFlowCategoryBo(FlowCategory dto) { + super(dto); + } + + @Override + protected void afterInit(FlowCategory dto) { + if (StringUtil.isNotEmpty(dto.getParentId())) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory parent = flowCategoryService.findById(dto.getParentId()); + this.parentName = parent.getName(); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/GetFlowCategoryListVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/GetFlowCategoryListVo.java new file mode 100644 index 0000000..73ccd58 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/GetFlowCategoryListVo.java @@ -0,0 +1,10 @@ +package com.lframework.starter.bpm.vo.flow.category; + +import com.lframework.starter.web.core.vo.PageVo; + +import java.io.Serializable; + +public class GetFlowCategoryListVo extends PageVo implements Serializable { + + public static final long serialVersionUID = 1L; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/QueryFlowCategoryTreeBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/QueryFlowCategoryTreeBo.java new file mode 100644 index 0000000..66a1412 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/QueryFlowCategoryTreeBo.java @@ -0,0 +1,30 @@ +package com.lframework.starter.bpm.vo.flow.category; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.web.core.bo.BaseBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryFlowCategoryTreeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + /** + * 流程类型名称 + */ + @Schema(description = "流程类型名称") + private String name; + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; + + public QueryFlowCategoryTreeBo(FlowCategory dto) { + super(dto); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/UpdateFlowCategoryVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/UpdateFlowCategoryVo.java new file mode 100644 index 0000000..0436985 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/category/UpdateFlowCategoryVo.java @@ -0,0 +1,24 @@ +package com.lframework.starter.bpm.vo.flow.category; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateFlowCategoryVo implements BaseVo, Serializable { + + public static final long serialVersionUID = 1L; + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + private String id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/CreateFlowDefinitionVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/CreateFlowDefinitionVo.java new file mode 100644 index 0000000..fa60c5e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/CreateFlowDefinitionVo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateFlowDefinitionVo implements BaseVo, Serializable { + + public static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "编号不能为空!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "分类ID不能为空!") + private String categoryId; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/DetailFlowDefinitionBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/DetailFlowDefinitionBo.java new file mode 100644 index 0000000..ac889c1 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/DetailFlowDefinitionBo.java @@ -0,0 +1,66 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class DetailFlowDefinitionBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String code; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String name; + + /** + * 流程分类ID + */ + @Schema(description = "流程分类ID") + private String categoryId; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + @EnumConvert + private Integer isPublish; + + public DetailFlowDefinitionBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryId = flowCategory.getId(); + this.categoryName = flowCategory.getName(); + + this.code = dto.getFlowCode(); + this.name = dto.getFlowName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorBo.java new file mode 100644 index 0000000..1e0a5c5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorBo.java @@ -0,0 +1,63 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class FlowDefinitionSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 版本号 + */ + @Schema(description = "版本号") + private String version; + + /** + * 创建时间 + * @param dto + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + public FlowDefinitionSelectorBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryName = flowCategory.getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorVo.java new file mode 100644 index 0000000..13fbc38 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/FlowDefinitionSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class FlowDefinitionSelectorVo extends PageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String code; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String name; + + /** + * 流程分类ID + */ + @Schema(description = "流程分类ID") + private String categoryId; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionBo.java new file mode 100644 index 0000000..ae4952f --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionBo.java @@ -0,0 +1,78 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.entity.FlowDefinitionWrapper; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryFlowDefinitionBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 流程分类 + */ + @Schema(description = "流程分类") + private String categoryName; + + /** + * 版本号 + */ + @Schema(description = "版本号") + private String version; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + @EnumConvert + private Integer isPublish; + + /** + * 激活状态 + */ + @Schema(description = "激活状态") + @EnumConvert + private Integer activityStatus; + + /** + * 创建时间 + * @param dto + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + public QueryFlowDefinitionBo(FlowDefinitionWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowDefinitionWrapper dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategory()); + this.categoryName = flowCategory.getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionVo.java new file mode 100644 index 0000000..e3f907d --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/QueryFlowDefinitionVo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryFlowDefinitionVo extends PageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String code; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String name; + + /** + * 流程分类ID + */ + @Schema(description = "流程分类ID") + private String categoryId; + + /** + * 版本号 + */ + @Schema(description = "版本号") + private String version; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + private Integer isPublish; + + /** + * 激活状态 + */ + @Schema(description = "激活状态") + private Integer activityStatus; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionActivityStatusVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionActivityStatusVo.java new file mode 100644 index 0000000..8475a8c --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionActivityStatusVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.bpm.enums.FlowDefinitionActivityStatus; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SetFlowDefinitionActivityStatusVo implements BaseVo, Serializable { + + public static final long serialVersionUID = 1L; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "流程定义ID不能为空!") + private Long id; + + /** + * 激活状态 + */ + @Schema(description = "激活状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "激活状态不能为空!") + @IsEnum(enumClass = FlowDefinitionActivityStatus.class, message = "激活状态格式不正确!") + private Integer activityStatus; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionPublishVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionPublishVo.java new file mode 100644 index 0000000..5dc41e0 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/SetFlowDefinitionPublishVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.bpm.enums.FlowDefinitionIsPublish; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SetFlowDefinitionPublishVo implements BaseVo, Serializable { + + public static final long serialVersionUID = 1L; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "流程定义ID不能为空!") + private Long id; + + /** + * 发布状态 + */ + @Schema(description = "发布状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "发布状态不能为空!") + @IsEnum(enumClass = FlowDefinitionIsPublish.class, message = "发布状态格式不正确!") + private Integer isPublish; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/UpdateFlowDefinitionVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/UpdateFlowDefinitionVo.java new file mode 100644 index 0000000..51b5a09 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/definition/UpdateFlowDefinitionVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.definition; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateFlowDefinitionVo implements BaseVo, Serializable { + + public static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "ID不能为空!") + private Long id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "分类ID不能为空!") + private String categoryId; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryBusinessFlowInstanceBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryBusinessFlowInstanceBo.java new file mode 100644 index 0000000..adaac3a --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryBusinessFlowInstanceBo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.instance; + +import com.lframework.starter.bpm.entity.FlowInstanceWrapper; +import com.lframework.starter.bpm.service.FlowCuInstanceService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryBusinessFlowInstanceBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + public QueryBusinessFlowInstanceBo(FlowInstanceWrapper dto) { + super(dto); + } + + @Override + protected void afterInit(FlowInstanceWrapper dto) { + FlowCuInstanceService flowCuInstanceService = ApplicationUtil.getBean( + FlowCuInstanceService.class); + + this.title = flowCuInstanceService.getById(dto.getId()).getTitle(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryInstanceListVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryInstanceListVo.java new file mode 100644 index 0000000..5b85d6c --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/instance/QueryInstanceListVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.instance; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryInstanceListVo extends PageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApprovePassTaskVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApprovePassTaskVo.java new file mode 100644 index 0000000..09e2a37 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApprovePassTaskVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +@Data +public class ApprovePassTaskVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 任务ID + */ + @Schema(description = "任务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "任务ID不能为空!") + private Long taskId; + + /** + * 说明 + */ + @Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "说明不能为空!") + private String message; + + /** + * 表单变量 + */ + @Schema(description = "表单变量") + private Map variables; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApproveRefuseTaskVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApproveRefuseTaskVo.java new file mode 100644 index 0000000..0e34792 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/ApproveRefuseTaskVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +@Data +public class ApproveRefuseTaskVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 任务ID + */ + @Schema(description = "任务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "任务ID不能为空!") + private Long taskId; + + /** + * 说明 + */ + @Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "说明不能为空!") + private String message; + + /** + * 表单变量 + */ + @Schema(description = "表单变量") + private Map variables; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryInstanceListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryInstanceListBo.java new file mode 100644 index 0000000..cf03b24 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryInstanceListBo.java @@ -0,0 +1,147 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import cn.hutool.core.date.BetweenFormatter.Level; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryInstanceListBo extends BaseBo { + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + /** + * 流程结束时间 + */ + @Schema(description = "流程结束时间") + private LocalDateTime endTime; + + /** + * 流程执行时间 + */ + @Schema(description = "流程执行时间") + private String executeTime; + + public QueryInstanceListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + + if (dto.getEndTime() != null) { + this.executeTime = DateUtil.formatBetween( + LocalDateTimeUtil.between(dto.getStartTime(), dto.getEndTime()).getSeconds() * 1000L, + Level.SECOND); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListBo.java new file mode 100644 index 0000000..3768d10 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListBo.java @@ -0,0 +1,147 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import cn.hutool.core.date.BetweenFormatter.Level; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryMyTaskListBo extends BaseBo { + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + /** + * 流程结束时间 + */ + @Schema(description = "流程结束时间") + private LocalDateTime endTime; + + /** + * 流程执行时间 + */ + @Schema(description = "流程执行时间") + private String executeTime; + + public QueryMyTaskListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + + if (dto.getEndTime() != null) { + this.executeTime = DateUtil.formatBetween( + LocalDateTimeUtil.between(dto.getStartTime(), dto.getEndTime()).getSeconds() * 1000L, + Level.SECOND); + } + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListVo.java new file mode 100644 index 0000000..6e3ac3e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryMyTaskListVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryMyTaskListVo extends PageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListBo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListBo.java new file mode 100644 index 0000000..417df0e --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListBo.java @@ -0,0 +1,132 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.bpm.dto.FlowTaskDto; +import com.lframework.starter.bpm.entity.FlowCategory; +import com.lframework.starter.bpm.service.FlowCategoryService; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryTodoTaskListBo extends BaseBo { + + /** + * 任务ID + */ + @Schema(description = "任务ID") + private String taskId; + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; + + /** + * 业务ID + */ + @Schema(description = "业务ID") + private String businessId; + + /** + * 节点编号 + */ + @Schema(description = "节点编号") + private String nodeCode; + + /** + * 节点名称 + */ + @Schema(description = "节点名称") + private String nodeName; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + /** + * 流程定义ID + */ + @Schema(description = "流程定义ID") + private String flowId; + + /** + * 流程定义编号 + */ + @Schema(description = "流程定义编号") + private String flowCode; + + /** + * 流程定义名称 + */ + @Schema(description = "流程定义名称") + private String flowName; + + /** + * 流程定义分类ID + */ + @Schema(description = "流程定义分类ID") + private String categoryId; + + /** + * 流程定义分类名称 + */ + @Schema(description = "流程定义分类名称") + private String categoryName; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID") + private String instanceId; + + /** + * 流程实例扩展字段 + */ + @Schema(description = "流程实例扩展字段") + private String ext; + + /** + * 流程发起人ID + */ + @Schema(description = "流程发起人ID") + private String startById; + + /** + * 流程发起人 + */ + @Schema(description = "流程发起人") + private String startBy; + + /** + * 流程发起时间 + */ + @Schema(description = "流程发起时间") + private LocalDateTime startTime; + + public QueryTodoTaskListBo(FlowTaskDto dto) { + super(dto); + } + + @Override + protected void afterInit(FlowTaskDto dto) { + FlowCategoryService flowCategoryService = ApplicationUtil.getBean(FlowCategoryService.class); + FlowCategory flowCategory = flowCategoryService.findById(dto.getCategoryId()); + this.categoryName = flowCategory.getName(); + + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + this.startBy = sysUserService.findById(dto.getStartById()).getName(); + } +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListVo.java new file mode 100644 index 0000000..4ff0fd5 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/QueryTodoTaskListVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryTodoTaskListVo extends PageVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程编号 + */ + @Schema(description = "流程编号") + private String flowCode; + + /** + * 流程名称 + */ + @Schema(description = "流程名称") + private String flowName; + + /** + * 任务标题 + */ + @Schema(description = "任务标题") + private String title; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/RejectTaskVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/RejectTaskVo.java new file mode 100644 index 0000000..a5fbbd0 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/RejectTaskVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +@Data +public class RejectTaskVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 任务ID + */ + @Schema(description = "任务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "任务ID不能为空!") + private Long taskId; + + /** + * 说明 + */ + @Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "说明不能为空!") + private String message; + + /** + * 表单变量 + */ + @Schema(description = "表单变量") + private Map variables; +} diff --git a/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/UndoTaskVo.java b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/UndoTaskVo.java new file mode 100644 index 0000000..a30ea33 --- /dev/null +++ b/bpm-starter/src/main/java/com/lframework/starter/bpm/vo/flow/task/UndoTaskVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.bpm.vo.flow.task; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +@Data +public class UndoTaskVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流程实例ID + */ + @Schema(description = "流程实例ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "流程实例ID不能为空!") + private Long instanceId; + + /** + * 说明 + */ + @Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "说明不能为空!") + private String message; + + /** + * 表单变量 + */ + @Schema(description = "表单变量") + private Map variables; +} diff --git a/bpm-starter/src/main/java/lombok.config b/bpm-starter/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/bpm-starter/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/bpm-starter/src/main/resources/META-INF/spring.factories b/bpm-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..8076069 --- /dev/null +++ b/bpm-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.lframework.starter.bpm.config.BpmBeanAutoConfiguration,\ + com.lframework.starter.bpm.config.BpmSwaggerAutoConfiguration \ No newline at end of file diff --git a/bpm-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/bpm-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..fee09c6 --- /dev/null +++ b/bpm-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.lframework.starter.bpm.config.BpmBeanAutoConfiguration +com.lframework.starter.bpm.config.BpmSwaggerAutoConfiguration diff --git a/bpm-starter/src/main/resources/mappers/FlowDefinitionWrapperMapper.xml b/bpm-starter/src/main/resources/mappers/FlowDefinitionWrapperMapper.xml new file mode 100644 index 0000000..d96a099 --- /dev/null +++ b/bpm-starter/src/main/resources/mappers/FlowDefinitionWrapperMapper.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/bpm-starter/src/main/resources/mappers/FlowTaskWrapperMapper.xml b/bpm-starter/src/main/resources/mappers/FlowTaskWrapperMapper.xml new file mode 100644 index 0000000..673950f --- /dev/null +++ b/bpm-starter/src/main/resources/mappers/FlowTaskWrapperMapper.xml @@ -0,0 +1,114 @@ + + + + + + + \ No newline at end of file diff --git a/common/README.md b/common/README.md new file mode 100644 index 0000000..7afc43b --- /dev/null +++ b/common/README.md @@ -0,0 +1,40 @@ +# common —— 公共工具库 + +## 概述 + +common 是 framework 的公共模块,提供无第三方框架依赖的核心工具类和常量定义,被所有其他模块依赖。 + +## 核心能力 + +### 工具类 +- **IdWorker** —— 分布式 ID 生成器(雪花算法) +- **Assert** —— 断言工具(参数校验、业务异常抛出) +- **BeanUtil / CollectionUtil / StringUtil / NumberUtil / ArrayUtil / ObjectUtil / DateUtil / FileUtil** —— 常用操作工具 +- **RegUtil** —— 正则匹配工具(预置常用正则 PatternPool) +- **XmlUtil / ZipUtil** —— XML 解析与 ZIP 压缩 +- **MailUtil** —— 邮件发送 +- **ReflectUtil** —— 反射操作 +- **ThreadUtil** —— 线程工具 +- **Locker** — 分布式锁接口定义 + +### 异常体系 +- **BaseException** —— 异常基类 +- **ClientException / SysException** —— 客户端异常 / 系统异常 +- **AccessDeniedException / AuthExpiredException / InputErrorException / UserLoginException / RepeatRequestException** 等具体异常 + +### 常量 +- **StringPool** —— 字符串常量池 +- **PatternPool** —— 正则表达式常量 +- **ResponseConstants** —— 响应状态码常量 + +### 函数式接口 +- **SFunction** —— 支持 Lambda 方法引用的函数接口(用于 MyBatis-Plus Lambda 查询) + +## 依赖 + +- Hutool 5.7.17 +- SLF4J + Logback +- Lombok +- HttpClient +- JavaMail +- dom4j diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..83fc94e --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.lframework + framework + 1.0.0 + + + common + + + 17 + 17 + UTF-8 + + + + + org.slf4j + slf4j-api + + + + ch.qos.logback + logback-classic + + + + org.projectlombok + lombok + + + + cn.hutool + hutool-core + + + + cn.hutool + hutool-extra + + + + cn.hutool + hutool-crypto + + + + cn.hutool + hutool-json + + + + cn.hutool + hutool-http + + + + com.sun.mail + javax.mail + + + + org.apache.httpcomponents + httpclient + + + + dom4j + dom4j + + + + \ No newline at end of file diff --git a/common/src/main/java/com/lframework/starter/common/constants/PatternPool.java b/common/src/main/java/com/lframework/starter/common/constants/PatternPool.java new file mode 100644 index 0000000..48f6fc3 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/constants/PatternPool.java @@ -0,0 +1,145 @@ +package com.lframework.starter.common.constants; + +import java.util.regex.Pattern; + +/** + * 正则表达式工具类 + * + * @author zmj + */ +public class PatternPool extends cn.hutool.core.lang.PatternPool { + + /** + * 不包含+86的手机号码 + */ + public static final String PATTERN_STR_CN_TEL = "^1[3-9]\\d{9}$"; + + public static final Pattern PATTERN_CN_TEL = Pattern.compile(PATTERN_STR_CN_TEL); + + /** + * 电子邮箱 + */ + public static final String PATTERN_STR_EMAIL = "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; + + public static final Pattern PATTERN_EMAIL = Pattern.compile(PATTERN_STR_EMAIL); + + /** + * 5-16位密码 只允许包含大写字母、小写字母、数字、下划线 + */ + public static final String PATTERN_STR_PASSWORD = "^[a-zA-Z0-9_]{5,16}$"; + + public static final Pattern PATTERN_PASSWORD = Pattern.compile(PATTERN_STR_PASSWORD); + + /** + * 是否 整数 + */ + public static final String PATTERN_STR_IS_INTEGER = "^(-?[1-9]\\d*|[0])$"; + + public static final Pattern PATTERN_IS_INTEGER = Pattern.compile(PATTERN_STR_IS_INTEGER); + + /** + * 是否 正整数 + */ + public static final String PATTERN_STR_IS_INTEGER_GT_ZERO = "^[1-9]\\d*$"; + + public static final Pattern PATTERN_IS_INTEGER_GT_ZERO = Pattern.compile( + PATTERN_STR_IS_INTEGER_GT_ZERO); + + /** + * 是否 负整数 + */ + public static final String PATTERN_STR_IS_INTEGER_LT_ZERO = "^-[1-9]\\d*$"; + + public static final Pattern PATTERN_IS_INTEGER_LT_ZERO = Pattern.compile( + PATTERN_STR_IS_INTEGER_LT_ZERO); + + /** + * 是否 非正整数 <=0 + */ + public static final String PATTERN_STR_IS_INTEGER_LE_ZERO = "^(-[1-9]\\d*|[0]{1})$"; + + public static final Pattern PATTERN_IS_INTEGER_LE_ZERO = Pattern.compile( + PATTERN_STR_IS_INTEGER_LE_ZERO); + + /** + * 是否 非负整数 >=0 + */ + public static final String PATTERN_STR_IS_INTEGER_GE_ZERO = "^([1-9]\\d*|[0]{1})$"; + + public static final Pattern PATTERN_IS_INTEGER_GE_ZERO = Pattern.compile( + PATTERN_STR_IS_INTEGER_GE_ZERO); + + /** + * 是否 浮点数 + */ + public static final String PATTERN_STR_IS_FLOAT = "^((-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0))|((-?[1-9]\\d*|[0])))$"; + + public static final Pattern PATTERN_IS_FLOAT = Pattern.compile(PATTERN_STR_IS_FLOAT); + + /** + * 是否 正浮点数 + */ + public static final String PATTERN_STR_IS_FLOAT_GT_ZERO = "^(([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*)|([1-9]\\d*))$"; + + public static final Pattern PATTERN_IS_FLOAT_GT_ZERO = Pattern.compile( + PATTERN_STR_IS_FLOAT_GT_ZERO); + + /** + * 是否 负浮点数 + */ + public static final String PATTERN_STR_IS_FLOAT_LT_ZERO = "^((-([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*))|(-[1-9]\\d*))$"; + + public static final Pattern PATTERN_IS_FLOAT_LT_ZERO = Pattern.compile( + PATTERN_STR_IS_FLOAT_LT_ZERO); + + /** + * 是否 非正浮点数 <= 0 + */ + public static final String PATTERN_STR_IS_FLOAT_LE_ZERO = "^(((-([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*))|0?\\.0+|0)|(-[1-9]\\d*))$"; + + public static final Pattern PATTERN_IS_FLOAT_LE_ZERO = Pattern.compile( + PATTERN_STR_IS_FLOAT_LE_ZERO); + + /** + * 是否 非负浮点数 >= 0 + */ + public static final String PATTERN_STR_IS_FLOAT_GE_ZERO = "^(([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)|([1-9]\\d*))$"; + + public static final Pattern PATTERN_IS_FLOAT_GE_ZERO = Pattern.compile( + PATTERN_STR_IS_FLOAT_GE_ZERO); + + /** + * 是否 数字组成 + */ + public static final String PATTERN_STR_IS_NUMBERIC = "^[0-9]*$"; + + public static final Pattern PATTERN_IS_NUMBERIC = Pattern.compile(PATTERN_STR_IS_NUMBERIC); + + /** + * 是否 价格 大于或等于0的两位小数 + */ + public static final String PATTERN_STR_IS_PRICE = "(^[1-9]([0-9]+)?(\\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\\.[0-9]([0-9])?$)"; + + public static final Pattern PATTERN_IS_PRICE = Pattern.compile(PATTERN_STR_IS_PRICE); + + /** + * ip地址 + */ + public static final String PATTERN_STR_IP_ADDRESS = "^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$"; + + public static final Pattern PATTERN_IP_ADDRESS = Pattern.compile(PATTERN_STR_IP_ADDRESS); + + /** + * Http Url链接 + */ + public static final String PATTERN_STR_HTTP_URL = "^(https?|http)://((?!(\\?)).)*$"; + + public static final Pattern PATTERN_HTTP_URL = Pattern.compile(PATTERN_STR_HTTP_URL); + + /** + * 编号 + */ + public static final String PATTERN_STR_CODE = "^[-_.A-Za-z0-9]{1,20}$"; + + public static final Pattern PATTERN_CODE = Pattern.compile(PATTERN_STR_CODE); +} diff --git a/common/src/main/java/com/lframework/starter/common/constants/ResponseConstants.java b/common/src/main/java/com/lframework/starter/common/constants/ResponseConstants.java new file mode 100644 index 0000000..1091191 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/constants/ResponseConstants.java @@ -0,0 +1,79 @@ +package com.lframework.starter.common.constants; + +/** + * 响应常量 + * + * @author zmj + */ +public class ResponseConstants { + + /** + * 响应成功状态码 + */ + public static final Integer INVOKE_RESULT_SUCCESS_CODE = 200; + + /** + * 响应失败状态码-传入参数错误 + */ + public static final Integer INVOKE_RESULT_FAIL_CODE_INPUT_ERROR = 400; + + /** + * 响应失败状态码-无登录状态 + */ + public static final Integer INVOKE_RESULT_FAIL_CODE_AUTH_EXPIRED = 401; + + /** + * 响应失败状态码-无权限 + */ + public static final Integer INVOKE_RESULT_FAIL_CODE_ACCESS_DENIED = 403; + + /** + * 响应失败状态码-重复请求 + */ + public static final Integer INVOKE_RESULT_FAIL_CODE_REPEAT_REQUEST = 410; + + /** + * 响应失败状态码-登录失败 + */ + public static final Integer INVOKE_RESULT_FAIL_USER_LOGIN_FAIL = 419; + + /** + * 响应失败状态码 + */ + public static final Integer INVOKE_RESULT_FAIL_CODE = 500; + + /** + * 响应成功信息 + */ + public static final String INVOKE_RESULT_SUCCESS_MSG = "success"; + + /** + * 默认响应失败信息 + */ + public static final String INVOKE_RESULT_FAIL_MSG = "fail"; + + /** + * 响应成功信息 + */ + public static final String INVOKE_RESULT_ERROR_MSG = "系统出现内部错误,请联系系统管理员!"; + + /** + * 响应失败信息-传入参数错误 + */ + public static final String INVOKE_RESULT_ERROR_MSG_INPUT_ERROR = "传入参数有误!"; + + /** + * 响应失败信息-无登录状态 + */ + public static final String INVOKE_RESULT_ERROR_MSG_AUTH_EXPIRED = "请重新登录!"; + + /** + * 响应失败信息-无权限 + */ + public static final String INVOKE_RESULT_ERROR_MSG_ACCESS_DENIED = "无系统权限!"; + + /** + * 响应失败信息-重复请求 + */ + public static final String INVOKE_RESULT_ERROR_MSG_REPEAT_REQUEST = "请求过于频繁,请稍后再试!"; +} diff --git a/common/src/main/java/com/lframework/starter/common/constants/StringPool.java b/common/src/main/java/com/lframework/starter/common/constants/StringPool.java new file mode 100644 index 0000000..d696000 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/constants/StringPool.java @@ -0,0 +1,108 @@ +package com.lframework.starter.common.constants; + +/** + * 常量池 + * + * @author zmj + */ +public interface StringPool { + + /** + * 空格 + */ + String SPACE = " "; + + /** + * 单元格占位符 + */ + String CELL_PLACEHOLDER = "-"; + + /** + * 空字符串 + */ + String EMPTY_STR = ""; + + /** + * 字符串分隔符 + */ + String STR_SPLIT = ","; + + /** + * 中文字符串分隔符 + */ + String STR_SPLIT_CN = ","; + + /** + * 城市名称分隔符 + */ + String CITY_SPLIT = "/"; + + /** + * utf-8字符集 + */ + String CHARACTER_ENCODING_UTF_8 = "utf-8"; + + /** + * Excel中的日期格式 + */ + String EXCEL_DATE_PATTERN = "yyyy/MM/dd"; + + /** + * 日期格式 + */ + String DATE_PATTERN = "yyyy-MM-dd"; + + /** + * 时间格式 + */ + String TIME_PATTERN = "HH:mm:ss"; + + /** + * 日期时间格式 + */ + String DATE_TIME_PATTERN = DATE_PATTERN + SPACE + TIME_PATTERN; + + /** + * 年月日时 + */ + String DATE_TIME_HOUR_PATTER = DATE_PATTERN + SPACE + "HH"; + + /** + * 小数点 + */ + String DECIMAL_POINT = "."; + + /** + * 零 + */ + String ZERO = "0"; + + /** + * 登录验证码在redis中的key值 + */ + String LOGIN_CAPTCHA_KEY = "login_captcha_key_{}"; + + /** + * 请求ID再Header中的key值 + */ + String HEADER_NAME_REQUEST_ID = "Request-Id"; + + /** + * 数据字典分隔符 + */ + String DATA_DIC_SPLIT = "@"; + + /** + * 加密字符 + */ + String ENCRYPT_STR = "*"; + + /** + * 租户ID在Qrtz中的Key + */ + String TENANT_ID_QRTZ = "__tenantId"; + + String Y = "Y"; + + String N = "N"; +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/BaseException.java b/common/src/main/java/com/lframework/starter/common/exceptions/BaseException.java new file mode 100644 index 0000000..fc0c163 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/BaseException.java @@ -0,0 +1,37 @@ +package com.lframework.starter.common.exceptions; + +/** + * 系统内异常基类 + * + * @author zmj + */ +public abstract class BaseException extends RuntimeException { + + /** + * 响应码 + */ + private Integer code; + + /** + * 响应信息 + */ + private String msg; + + public BaseException(Integer code, String msg) { + + super(msg); + + this.code = code; + this.msg = msg; + } + + public Integer getCode() { + + return code; + } + + public String getMsg() { + + return msg; + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/ClientException.java b/common/src/main/java/com/lframework/starter/common/exceptions/ClientException.java new file mode 100644 index 0000000..88b4cdb --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/ClientException.java @@ -0,0 +1,14 @@ +package com.lframework.starter.common.exceptions; + +/** + * 由于客户端请求错误导致的异常 用于表示需要返回信息至前端的异常 + * + * @author zmj + */ +public abstract class ClientException extends BaseException { + + public ClientException(Integer code, String msg) { + + super(code, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/SysException.java b/common/src/main/java/com/lframework/starter/common/exceptions/SysException.java new file mode 100644 index 0000000..5f566c4 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/SysException.java @@ -0,0 +1,14 @@ +package com.lframework.starter.common.exceptions; + +/** + * 由于系统内部错误导致的异常 用于表示程序运行错误或其他情况导致的不能将错误信息返回前端的异常 + * + * @author zmj + */ +public abstract class SysException extends BaseException { + + public SysException(Integer code, String msg) { + + super(code, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/AccessDeniedException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/AccessDeniedException.java new file mode 100644 index 0000000..396711e --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/AccessDeniedException.java @@ -0,0 +1,23 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +/** + * 由于无权限导致的异常 + * + * @author zmj + */ +public class AccessDeniedException extends ClientException { + + public AccessDeniedException() { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_ACCESS_DENIED, + ResponseConstants.INVOKE_RESULT_ERROR_MSG_ACCESS_DENIED); + } + + public AccessDeniedException(String msg) { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_ACCESS_DENIED, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/AuthExpiredException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/AuthExpiredException.java new file mode 100644 index 0000000..64b30cf --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/AuthExpiredException.java @@ -0,0 +1,18 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +/** + * 登录状态过期导致的异常 + * + * @author zmj + */ +public class AuthExpiredException extends ClientException { + + public AuthExpiredException() { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_AUTH_EXPIRED, + ResponseConstants.INVOKE_RESULT_ERROR_MSG_AUTH_EXPIRED); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultClientException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultClientException.java new file mode 100644 index 0000000..391e637 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultClientException.java @@ -0,0 +1,17 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +/** + * 自定义消息的异常 + * + * @author zmj + */ +public class DefaultClientException extends ClientException { + + public DefaultClientException(String msg) { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultSysException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultSysException.java new file mode 100644 index 0000000..8ff7214 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/DefaultSysException.java @@ -0,0 +1,22 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.SysException; + +/** + * 自定义消息的系统异常 + * + * @author zmj + */ +public class DefaultSysException extends SysException { + + public DefaultSysException() { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE, ResponseConstants.INVOKE_RESULT_ERROR_MSG); + } + + public DefaultSysException(String msg) { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/InputErrorException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/InputErrorException.java new file mode 100644 index 0000000..4db5b44 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/InputErrorException.java @@ -0,0 +1,23 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +/** + * 由于客户端传入参数错误导致的异常 + * + * @author zmj + */ +public class InputErrorException extends ClientException { + + public InputErrorException() { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_INPUT_ERROR, + ResponseConstants.INVOKE_RESULT_ERROR_MSG_INPUT_ERROR); + } + + public InputErrorException(String msg) { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_INPUT_ERROR, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/ParameterNotFoundException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/ParameterNotFoundException.java new file mode 100644 index 0000000..27eb634 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/ParameterNotFoundException.java @@ -0,0 +1,11 @@ +package com.lframework.starter.common.exceptions.impl; + +public class ParameterNotFoundException extends DefaultSysException { + + public ParameterNotFoundException() { + } + + public ParameterNotFoundException(String msg) { + super(msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/RepeatRequestException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/RepeatRequestException.java new file mode 100644 index 0000000..4301fdd --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/RepeatRequestException.java @@ -0,0 +1,18 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +/** + * 重复请求异常 + * + * @author zmj + */ +public class RepeatRequestException extends ClientException { + + public RepeatRequestException() { + + super(ResponseConstants.INVOKE_RESULT_FAIL_CODE_REPEAT_REQUEST, + ResponseConstants.INVOKE_RESULT_ERROR_MSG_REPEAT_REQUEST); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/exceptions/impl/UserLoginException.java b/common/src/main/java/com/lframework/starter/common/exceptions/impl/UserLoginException.java new file mode 100644 index 0000000..7ee2f6b --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/exceptions/impl/UserLoginException.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.exceptions.impl; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.ClientException; + +public class UserLoginException extends ClientException { + + public UserLoginException(String msg) { + + super(ResponseConstants.INVOKE_RESULT_FAIL_USER_LOGIN_FAIL, msg); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/functions/SFunction.java b/common/src/main/java/com/lframework/starter/common/functions/SFunction.java new file mode 100644 index 0000000..a80c5ab --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/functions/SFunction.java @@ -0,0 +1,17 @@ +package com.lframework.starter.common.functions; + +import com.lframework.starter.common.utils.ReflectUtil; + +import java.io.Serializable; +import java.util.function.Function; + +/** + * 主要用于根据方法名获取对应的属性名 + * + * @author zmj + * @see ReflectUtil + */ +@FunctionalInterface +public interface SFunction extends Function, Serializable { + +} diff --git a/common/src/main/java/com/lframework/starter/common/locker/LockBuilder.java b/common/src/main/java/com/lframework/starter/common/locker/LockBuilder.java new file mode 100644 index 0000000..6aae705 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/locker/LockBuilder.java @@ -0,0 +1,14 @@ +package com.lframework.starter.common.locker; + +public interface LockBuilder { + + /** + * 构建锁 + * + * @param lockName 锁名称 + * @param expireTime 过期时间(毫秒)只有Redis锁会生效 + * @param waitTime 等待时间(毫秒)只有Redis锁会生效 + * @return + */ + Locker buildLocker(String lockName, long expireTime, long waitTime); +} diff --git a/common/src/main/java/com/lframework/starter/common/locker/Locker.java b/common/src/main/java/com/lframework/starter/common/locker/Locker.java new file mode 100644 index 0000000..794b1af --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/locker/Locker.java @@ -0,0 +1,8 @@ +package com.lframework.starter.common.locker; + +public interface Locker extends AutoCloseable { + + boolean lock(); + + boolean unLock(); +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/ArrayUtil.java b/common/src/main/java/com/lframework/starter/common/utils/ArrayUtil.java new file mode 100644 index 0000000..e7876c7 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/ArrayUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * 数组工具类 + * 基于HuTool的ArrayUtil进行扩展,提供数组操作相关的工具方法 + * 包括数组判空、转换、查找、排序等功能 + * + * @author lframework@163.com + */ +public class ArrayUtil extends cn.hutool.core.util.ArrayUtil { + +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/Assert.java b/common/src/main/java/com/lframework/starter/common/utils/Assert.java new file mode 100644 index 0000000..01240e0 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/Assert.java @@ -0,0 +1,39 @@ +package com.lframework.starter.common.utils; + +/** + * 断言工具类 + * 基于HuTool的Assert进行扩展,提供参数验证和断言相关的工具方法 + * 包括参数非空验证、数值范围验证、条件断言等功能 + * + * @author lframework@163.com + */ +public class Assert extends cn.hutool.core.lang.Assert { + + /** + * 断言数字大于0 + * 验证数字必须大于0,否则抛出异常 + * + * @param number 要验证的数字,不能为null + * @throws IllegalArgumentException 当数字为null或小于等于0时抛出 + */ + public static void greaterThanZero(Number number) { + + notNull(number); + + isTrue(number.doubleValue() > 0D); + } + + /** + * 断言数字大于或等于0 + * 验证数字必须大于或等于0,否则抛出异常 + * + * @param number 要验证的数字,不能为null + * @throws IllegalArgumentException 当数字为null或小于0时抛出 + */ + public static void greaterThanOrEqualToZero(Number number) { + + notNull(number); + + isTrue(number.doubleValue() >= 0D); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/BeanUtil.java b/common/src/main/java/com/lframework/starter/common/utils/BeanUtil.java new file mode 100644 index 0000000..b4ab3a2 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/BeanUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * JavaBean工具类 + * 基于HuTool的BeanUtil进行扩展,提供JavaBean操作相关的工具方法 + * 包括对象属性复制、类型转换、反射操作等功能 + * + * @author lframework@163.com + */ +public class BeanUtil extends cn.hutool.core.bean.BeanUtil { + +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/CollectionUtil.java b/common/src/main/java/com/lframework/starter/common/utils/CollectionUtil.java new file mode 100644 index 0000000..e30e241 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/CollectionUtil.java @@ -0,0 +1,39 @@ +package com.lframework.starter.common.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 集合工具类 + * 基于HuTool的CollectionUtil进行扩展,提供集合操作相关的工具方法 + * 包括集合判空、创建空集合、集合转换等功能 + * + * @author lframework@163.com + */ +public class CollectionUtil extends cn.hutool.core.collection.CollectionUtil { + + /** + * 创建空的List集合 + * 返回一个容量为0的ArrayList实例 + * + * @param 集合元素类型 + * @return 空的List集合 + */ + public static List emptyList() { + return new ArrayList<>(0); + } + + /** + * 创建空的Map集合 + * 返回一个容量为0的HashMap实例 + * + * @param Map键类型 + * @param Map值类型 + * @return 空的Map集合 + */ + public static Map emptyMap() { + return new HashMap<>(0); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/DateUtil.java b/common/src/main/java/com/lframework/starter/common/utils/DateUtil.java new file mode 100644 index 0000000..c302b9f --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/DateUtil.java @@ -0,0 +1,385 @@ +package com.lframework.starter.common.utils; + +import cn.hutool.core.date.LocalDateTimeUtil; +import com.lframework.starter.common.constants.StringPool; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.temporal.WeekFields; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 时间工具类 + * 基于HuTool的LocalDateTimeUtil进行扩展,提供时间操作相关的工具方法 + * 包括时间格式化、类型转换、时间范围计算等功能 + * + * @author lframework@163.com + */ +public class DateUtil extends LocalDateTimeUtil { + + /** + * 格式化日期为标准格式 + * 使用默认的日期格式(yyyy-MM-dd)格式化LocalDate + * + * @param localDate 要格式化的日期,不能为null + * @return 格式化后的日期字符串 + */ + public static String formatDate(LocalDate localDate) { + + return LocalDateTimeUtil.formatNormal(localDate); + } + + /** + * 格式化日期为指定格式 + * 使用指定的日期格式格式化LocalDate + * + * @param localDate 要格式化的日期,不能为null + * @param format 日期格式,不能为null或空 + * @return 格式化后的日期字符串 + */ + public static String formatDate(LocalDate localDate, String format) { + + return LocalDateTimeUtil.format(localDate, format); + } + + /** + * 将Date转换为LocalTime + * 提取Date中的时间部分转换为LocalTime + * + * @param date 要转换的Date对象,可以为null + * @return 转换后的LocalTime对象,如果输入为null则返回null + */ + public static LocalTime toLocalTime(Date date) { + if (date == null) { + return null; + } + return LocalDateTimeUtil.of(date).toLocalTime(); + } + + /** + * 将Date转换为LocalDate + * 提取Date中的日期部分转换为LocalDate + * + * @param date 要转换的Date对象,可以为null + * @return 转换后的LocalDate对象,如果输入为null则返回null + */ + public static LocalDate toLocalDate(Date date) { + if (date == null) { + return null; + } + return LocalDateTimeUtil.of(date).toLocalDate(); + } + + /** + * 将Date转换为LocalDateTime + * 将Date对象转换为LocalDateTime对象 + * + * @param date 要转换的Date对象,不能为null + * @return 转换后的LocalDateTime对象 + */ + public static LocalDateTime toLocalDateTime(Date date) { + return LocalDateTimeUtil.of(date); + } + + /** + * 将LocalDateTime转换为Date + * 将LocalDateTime对象转换为Date对象 + * + * @param dateTime 要转换的LocalDateTime对象,可以为null + * @return 转换后的Date对象,如果输入为null则返回null + */ + public static Date toDate(LocalDateTime dateTime) { + + if (dateTime == null) { + return null; + } + + return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant()); + } + + /** + * 将LocalDate转换为Date + * 将LocalDate对象转换为Date对象,时间部分为00:00:00 + * + * @param date 要转换的LocalDate对象,可以为null + * @return 转换后的Date对象,如果输入为null则返回null + */ + public static Date toDate(LocalDate date) { + + if (date == null) { + return null; + } + + return Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()); + } + + /** + * 将LocalDate转换为LocalDateTime(最小时间) + * 将LocalDate转换为当天的00:00:00时间 + * + * @param localDate 要转换的LocalDate对象,不能为null + * @return 转换后的LocalDateTime对象 + */ + public static LocalDateTime toLocalDateTime(LocalDate localDate) { + + return LocalDateTime.of(localDate, LocalTime.MIN); + } + + /** + * 将LocalDate转换为LocalDateTime(最大时间) + * 将LocalDate转换为当天的23:59:59.999999999时间 + * + * @param localDate 要转换的LocalDate对象,不能为null + * @return 转换后的LocalDateTime对象 + */ + public static LocalDateTime toLocalDateTimeMax(LocalDate localDate) { + + return LocalDateTime.of(localDate, LocalTime.MAX.withNano(0)); + } + + /** + * 格式化日期时间为标准格式 + * 使用默认的日期时间格式(yyyy-MM-dd HH:mm:ss)格式化LocalDateTime + * + * @param localDateTime 要格式化的日期时间,不能为null + * @return 格式化后的日期时间字符串 + */ + public static String formatDateTime(LocalDateTime localDateTime) { + + return formatDateTime(localDateTime, StringPool.DATE_TIME_PATTERN); + } + + /** + * 格式化日期时间为指定格式 + * 使用指定的日期时间格式格式化LocalDateTime + * + * @param localDateTime 要格式化的日期时间,不能为null + * @param pattern 日期时间格式,不能为null或空 + * @return 格式化后的日期时间字符串 + */ + public static String formatDateTime(LocalDateTime localDateTime, String pattern) { + + return format(localDateTime, pattern); + } + + /** + * 获取LocalDateTime的时间戳 + * 将LocalDateTime转换为毫秒时间戳 + * + * @param localDateTime 要转换的LocalDateTime对象,不能为null + * @return 毫秒时间戳 + */ + public static long getTime(LocalDateTime localDateTime) { + + return Timestamp.valueOf(localDateTime).getTime(); + } + + /** + * 获取LocalDate的时间戳 + * 将LocalDate转换为毫秒时间戳(当天00:00:00) + * + * @param localDate 要转换的LocalDate对象,不能为null + * @return 毫秒时间戳 + */ + public static long getTime(LocalDate localDate) { + + return Timestamp.valueOf(toLocalDateTime(localDate)).getTime(); + } + + /** + * 获取Date的时间戳 + * 获取Date对象的毫秒时间戳 + * + * @param date 要获取时间戳的Date对象,不能为null + * @return 毫秒时间戳 + */ + public static long getTime(Date date) { + + return date.getTime(); + } + + /** + * 获取本周的所有日期 + * 返回当前周从周一到周日的所有日期 + * + * @return 本周的日期列表,包含7个日期 + */ + public static List getCurrentWeekDates() { + + return getWeekDates(LocalDate.now()); + } + + /** + * 获取指定日期所在周的所有日期 + * 返回指定日期所在周从周一到周日的所有日期 + * + * @param date 指定日期,不能为null + * @return 该周的日期列表,包含7个日期 + */ + public static List getWeekDates(LocalDate date) { + LocalDate firstDate = date.with(WeekFields.ISO.dayOfWeek(), 1L); + + List results = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + results.add(firstDate.plusDays(i)); + } + + return results; + } + + + /** + * 获取本月的所有日期 + * 返回当前月份的所有日期 + * + * @return 本月的日期列表 + */ + public static List getCurrentMonthDates() { + LocalDate now = LocalDate.now(); + + return getMonthDates(LocalDate.now()); + } + + /** + * 获取指定日期所在月份的所有日期 + * 返回指定日期所在月份的所有日期 + * + * @param date 指定日期,不能为null + * @return 该月的日期列表 + */ + public static List getMonthDates(LocalDate date) { + LocalDate firstDate = date.withDayOfMonth(1); + List results = new ArrayList<>(); + for (int i = 0; i < 31; i++) { + LocalDate tmp = firstDate.plusDays(i); + if (tmp.getMonthValue() != firstDate.getMonthValue()) { + break; + } + results.add(tmp); + } + + return results; + } + + /** + * 获取本季度的所有日期 + * 返回当前季度的所有日期 + * + * @return 本季度的日期列表 + */ + public static List getCurrentQuarterDates() { + + return getQuarterDates(LocalDate.now()); + } + + /** + * 获取指定日期所在季度的所有日期 + * 返回指定日期所在季度的所有日期 + * + * @param date 指定日期,不能为null + * @return 该季度的日期列表 + */ + public static List getQuarterDates(LocalDate date) { + int quarter = getQuarter(date); + + LocalDate firstDate = date.withMonth((quarter - 1) * 3 + 1).withDayOfMonth(1); + + List results = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + results.addAll(getMonthDates(firstDate.plusMonths(i))); + } + + return results; + } + + /** + * 获取当前半年的所有日期 + * 返回当前半年的所有日期 + * + * @param date 指定日期,不能为null + * @return 当前半年的日期列表 + */ + public static List getCurrentHalfYearDates(LocalDate date) { + return getHalfYearDates(LocalDate.now()); + } + + /** + * 获取指定日期所在半年的所有日期 + * 返回指定日期所在半年的所有日期 + * + * @param date 指定日期,不能为null + * @return 该半年的日期列表 + */ + public static List getHalfYearDates(LocalDate date) { + LocalDate firstDate = date.getMonthValue() > 6 ? date.withMonth(7).withDayOfMonth(1) + : date.withMonth(1).withDayOfMonth(1); + LocalDate lastDate = date.getMonthValue() > 6 ? date.withMonth(12).withDayOfMonth(31) + : date.withMonth(6).withDayOfMonth(30); + + List results = new ArrayList<>(); + int i = 0; + while (true) { + + LocalDate tmp = firstDate.plusDays(i); + if (tmp.isAfter(lastDate)) { + break; + } + results.add(tmp); + i++; + } + + return results; + } + + /** + * 获取当前年的所有日期 + * 返回当前年份的所有日期 + * + * @return 当前年的日期列表 + */ + public static List getCurrentYearDates() { + return getYearDates(LocalDate.now()); + } + + /** + * 获取指定日期所在年份的所有日期 + * 返回指定日期所在年份的所有日期 + * + * @param date 指定日期,不能为null + * @return 该年的日期列表 + */ + public static List getYearDates(LocalDate date) { + LocalDate firstDate = date.withMonth(1).withDayOfMonth(1); + LocalDate lastDate = date.withMonth(12).withDayOfMonth(31); + + List results = new ArrayList<>(); + int i = 0; + while (true) { + + LocalDate tmp = firstDate.plusDays(i); + if (tmp.isAfter(lastDate)) { + break; + } + results.add(tmp); + i++; + } + + return results; + } + + /** + * 获取指定日期属于第几季度 + * 根据月份计算季度:1-3月为第1季度,4-6月为第2季度,7-9月为第3季度,10-12月为第4季度 + * + * @param date 指定日期,不能为null + * @return 季度数(1-4) + */ + public static int getQuarter(LocalDate date) { + return (date.getMonthValue() - 1) / 3 + 1; + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/FileUtil.java b/common/src/main/java/com/lframework/starter/common/utils/FileUtil.java new file mode 100644 index 0000000..1b94290 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/FileUtil.java @@ -0,0 +1,33 @@ +package com.lframework.starter.common.utils; + +import java.util.Arrays; +import java.util.List; + +/** + * 文件工具类 + * 基于HuTool的FileUtil进行扩展,提供文件操作相关的工具方法 + * 包括文件类型判断、文件操作、路径处理等功能 + * + * @author lframework@163.com + */ +public class FileUtil extends cn.hutool.core.io.FileUtil { + + /** + * 图片文件后缀名列表 + * 支持常见的图片格式:jpg、jpeg、bmp、png、gif + */ + public static final List IMG_SUFFIX = Arrays.asList("jpg", "jpeg", "bmp", "png", "gif"); + + /** + * Excel文件后缀名列表 + * 支持Excel格式:xls、xlsx + */ + public static final List EXCEL_SUFFIX = Arrays.asList("xls", "xlsx"); + + /** + * 视频文件后缀名列表 + * 支持常见的视频格式:avi、wmv、mpeg、mp4、m4v、mov、asf、flv、f4v、rmvb、rm、3gp、vob + */ + public static final List VIDEO_SUFFIX = Arrays.asList("avi", "wmv", "mpeg", "mp4", "m4v", + "mov", "asf", "flv", "f4v", "rmvb", "rm", "3gp", "vob"); +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/IdWorker.java b/common/src/main/java/com/lframework/starter/common/utils/IdWorker.java new file mode 100644 index 0000000..70918cd --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/IdWorker.java @@ -0,0 +1,82 @@ +package com.lframework.starter.common.utils; + +import cn.hutool.core.lang.Snowflake; +import lombok.extern.slf4j.Slf4j; + +import java.util.Date; + +/** + * 分布式ID生成器 + * 基于HuTool的Snowflake雪花算法实现,生成全局唯一的分布式ID + * 支持高并发场景下的ID生成,保证ID的唯一性和有序性 + * + * @author lframework@163.com + */ +@Slf4j +public class IdWorker extends Snowflake { + + /** + * 默认构造函数 + * 使用默认的workerId和dataCenterId创建ID生成器 + */ + public IdWorker() { + super(); + } + + /** + * 指定workerId的构造函数 + * + * @param workerId 工作机器ID,范围0-31 + */ + public IdWorker(long workerId) { + super(workerId); + } + + /** + * 指定workerId和dataCenterId的构造函数 + * + * @param workerId 工作机器ID,范围0-31 + * @param dataCenterId 数据中心ID,范围0-31 + */ + public IdWorker(long workerId, long dataCenterId) { + super(workerId, dataCenterId); + } + + /** + * 指定workerId、dataCenterId和时钟使用方式的构造函数 + * + * @param workerId 工作机器ID,范围0-31 + * @param dataCenterId 数据中心ID,范围0-31 + * @param isUseSystemClock 是否使用系统时钟 + */ + public IdWorker(long workerId, long dataCenterId, boolean isUseSystemClock) { + super(workerId, dataCenterId, isUseSystemClock); + } + + /** + * 指定纪元时间、workerId、dataCenterId和时钟使用方式的构造函数 + * + * @param epochDate 纪元时间,不能为null + * @param workerId 工作机器ID,范围0-31 + * @param dataCenterId 数据中心ID,范围0-31 + * @param isUseSystemClock 是否使用系统时钟 + */ + public IdWorker(Date epochDate, long workerId, long dataCenterId, + boolean isUseSystemClock) { + super(epochDate, workerId, dataCenterId, isUseSystemClock); + } + + /** + * 完整参数的构造函数 + * + * @param epochDate 纪元时间,不能为null + * @param workerId 工作机器ID,范围0-31 + * @param dataCenterId 数据中心ID,范围0-31 + * @param isUseSystemClock 是否使用系统时钟 + * @param timeOffset 时间偏移量 + */ + public IdWorker(Date epochDate, long workerId, long dataCenterId, + boolean isUseSystemClock, long timeOffset) { + super(epochDate, workerId, dataCenterId, isUseSystemClock, timeOffset); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/MailUtil.java b/common/src/main/java/com/lframework/starter/common/utils/MailUtil.java new file mode 100644 index 0000000..ceddaf7 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/MailUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * 邮件工具类 + * 基于HuTool的MailUtil进行扩展,提供邮件发送相关的工具方法 + * 包括邮件发送、附件处理、模板邮件等功能 + * + * @author lframework@163.com + */ +public class MailUtil extends cn.hutool.extra.mail.MailUtil { + +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/NumberUtil.java b/common/src/main/java/com/lframework/starter/common/utils/NumberUtil.java new file mode 100644 index 0000000..15a22be --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/NumberUtil.java @@ -0,0 +1,381 @@ +package com.lframework.starter.common.utils; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 数字工具类 + * 提供精确的数字计算、比较、精度控制等功能,避免浮点数计算精度问题 + * 支持加减乘除运算、大小比较、税率计算、精度验证等常用数字操作 + * + * @author lframework@163.com + */ +public class NumberUtil { + + /** + * 判断数字的小数位数是否符合指定精度要求 + * 用于验证数字的小数位数是否在允许范围内 + * + * @param value 待验证的数字,不能为null + * @param precision 允许的最大小数位数,必须大于等于0 + * @return true-符合精度要求,false-不符合精度要求或参数无效 + */ + public static boolean isNumberPrecision(Number value, int precision) { + + if (value == null) { + return false; + } + + if (precision < 0) { + return false; + } + + String str = BigDecimal.valueOf(value.doubleValue()).toPlainString(); + + if (str.contains(StringPool.DECIMAL_POINT)) { + while (StringPool.ZERO.equals(str.substring(str.length() - 1))) { + // 将数字末尾为0的字符去除 + str = str.substring(0, str.length() - 1); + } + + if (StringPool.DECIMAL_POINT.equals(str.substring(str.length() - 1))) { + return true; + } + + return str.substring(str.indexOf(StringPool.DECIMAL_POINT)).length() - 1 <= precision; + } + + return true; + } + + /** + * 判断数字是否为整数 + * 检查Number对象是否表示一个整数值(没有小数部分) + * + * @param number 待检查的数字,不能为null + * @return true-是整数,false-不是整数或参数为null + */ + public static boolean isInteger(Number number) { + if (number == null) { + return false; + } + + if (number instanceof Integer || number instanceof Long || number instanceof Short + || number instanceof Byte) { + return true; + } + + BigDecimal bigDecimal = getNumber(number); + return bigDecimal.compareTo(new BigDecimal(bigDecimal.toBigInteger())) == 0; + } + + /** + * 精确加法运算 + * 对多个数字进行精确的加法计算,避免浮点数精度问题 + * + * @param numbers 参与加法运算的数字,支持可变参数 + * @return 所有数字相加的结果,使用BigDecimal保证精度 + */ + public static BigDecimal add(Number... numbers) { + + BigDecimal result = new BigDecimal(0); + + for (Number number : numbers) { + result = result.add(getNumber(number)); + } + + return result; + } + + /** + * 精确减法运算 + * 从被减数中依次减去所有减数,进行精确的减法计算 + * + * @param n1 被减数,不能为null + * @param numbers 减数数组,不能为空 + * @return 减法运算的结果,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当被减数为null或减数数组为空时抛出 + */ + public static BigDecimal sub(Number n1, Number... numbers) { + + Assert.notNull(n1); + Assert.notEmpty(numbers); + + BigDecimal result = getNumber(n1); + + for (Number number : numbers) { + BigDecimal tmp = getNumber(number); + + result = result.subtract(tmp); + } + + return result; + } + + /** + * 精确乘法运算 + * 对多个数字进行精确的乘法计算,避免浮点数精度问题 + * + * @param numbers 参与乘法运算的数字,支持可变参数 + * @return 所有数字相乘的结果,使用BigDecimal保证精度 + */ + public static BigDecimal mul(Number... numbers) { + + BigDecimal result = new BigDecimal(1); + for (Number number : numbers) { + result = result.multiply(getNumber(number)); + } + + return result; + } + + /** + * 精确除法运算(四舍五入) + * 使用四舍五入模式进行精确的除法计算 + * + * @param n1 被除数,不能为null + * @param numbers 除数数组,不能为空且不能包含0 + * @return 除法运算的结果,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当被除数为null或除数数组为空时抛出 + * @throws DefaultSysException 当除数为0时抛出 + */ + public static BigDecimal div(Number n1, Number... numbers) { + + return div(RoundingMode.HALF_UP, n1, numbers); + } + + /** + * 精确除法运算(指定舍入模式) + * 使用指定的舍入模式进行精确的除法计算 + * + * @param mode 小数位处理方式,不能为null + * @param n1 被除数,不能为null + * @param numbers 除数数组,不能为空且不能包含0 + * @return 除法运算的结果,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当被除数为null或除数数组为空时抛出 + * @throws DefaultSysException 当除数为0时抛出 + */ + public static BigDecimal div(RoundingMode mode, Number n1, Number... numbers) { + + Assert.notNull(n1); + Assert.notEmpty(numbers); + + BigDecimal result = getNumber(n1); + + for (Number number : numbers) { + BigDecimal tmp = getNumber(number); + if (equal(tmp, 0)) { + throw new DefaultSysException("除数不能等于0"); + } + + result = new BigDecimal(result.divide(tmp, 16, mode).stripTrailingZeros().toPlainString()); + } + + return result; + } + + /** + * 判断第一个数字是否大于第二个数字 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param n1 第一个数字,不能为null + * @param n2 第二个数字,不能为null + * @return true-第一个数字大于第二个数字,false-否则 + */ + public static boolean gt(Number n1, Number n2) { + + return getNumber(n1).compareTo(getNumber(n2)) > 0; + } + + /** + * 判断第一个数字是否小于第二个数字 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param n1 第一个数字,不能为null + * @param n2 第二个数字,不能为null + * @return true-第一个数字小于第二个数字,false-否则 + */ + public static boolean lt(Number n1, Number n2) { + + return getNumber(n1).compareTo(getNumber(n2)) < 0; + } + + /** + * 判断第一个数字是否大于或等于第二个数字 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param n1 第一个数字,不能为null + * @param n2 第二个数字,不能为null + * @return true-第一个数字大于或等于第二个数字,false-否则 + */ + public static boolean ge(Number n1, Number n2) { + + return getNumber(n1).compareTo(getNumber(n2)) >= 0; + } + + /** + * 判断第一个数字是否小于或等于第二个数字 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param n1 第一个数字,不能为null + * @param n2 第二个数字,不能为null + * @return true-第一个数字小于或等于第二个数字,false-否则 + */ + public static boolean le(Number n1, Number n2) { + + return getNumber(n1).compareTo(getNumber(n2)) <= 0; + } + + /** + * 判断两个数字是否相等 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param n1 第一个数字,不能为null + * @param n2 第二个数字,不能为null + * @return true-两个数字相等,false-否则 + */ + public static boolean equal(Number n1, Number n2) { + + return getNumber(n1).compareTo(getNumber(n2)) == 0; + } + + /** + * 根据无税价格计算含税价格 + * 计算公式:含税价格 = 无税价格 × (1 + 税率/100) + * + * @param unTaxPrice 无税价格,不能为null + * @param taxRate 税率(百分比),不能为null,如13表示13% + * @return 计算后的含税价格,使用BigDecimal保证精度 + */ + public static BigDecimal calcTaxPrice(Number unTaxPrice, Number taxRate) { + + return mul(unTaxPrice, add(div(taxRate, 100), BigDecimal.ONE)); + } + + /** + * 根据含税价格计算无税价格 + * 计算公式:无税价格 = 含税价格 ÷ (1 + 税率/100) + * + * @param taxPrice 含税价格,不能为null + * @param taxRate 税率(百分比),不能为null,如13表示13% + * @return 计算后的无税价格,使用BigDecimal保证精度 + */ + public static BigDecimal calcUnTaxPrice(Number taxPrice, Number taxRate) { + + return div(taxPrice, add(div(taxRate, 100), BigDecimal.ONE)); + } + + /** + * 根据含税价格和无税价格计算税率 + * 计算公式:税率 = (含税价格 ÷ 无税价格 - 1) × 100 + * + * @param tax 含税价格或含税金额,不能为null + * @param unTax 无税价格或无税金额,不能为null且不能为0 + * @return 计算后的税率(百分比),使用BigDecimal保证精度 + * @throws DefaultSysException 当无税价格为0时抛出 + */ + public static BigDecimal calcTaxRate(Number tax, Number unTax) { + return mul(sub(div(tax, unTax), BigDecimal.ONE), 100); + } + + /** + * 获取多个数字中的最小值 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param numbers 参与比较的数字,不能为null且至少包含一个元素 + * @return 所有数字中的最小值,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当数字数组为null或为空时抛出 + */ + public static BigDecimal min(Number... numbers) { + Assert.notEmpty(numbers); + + BigDecimal min = getNumber(numbers[0]); + for (int i = 1; i < numbers.length; i++) { + BigDecimal current = getNumber(numbers[i]); + if (current.compareTo(min) < 0) { + min = current; + } + } + + return min; + } + + /** + * 获取多个数字中的最大值 + * 使用BigDecimal进行精确比较,避免浮点数比较问题 + * + * @param numbers 参与比较的数字,不能为null且至少包含一个元素 + * @return 所有数字中的最大值,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当数字数组为null或为空时抛出 + */ + public static BigDecimal max(Number... numbers) { + Assert.notEmpty(numbers); + + BigDecimal max = getNumber(numbers[0]); + for (int i = 1; i < numbers.length; i++) { + BigDecimal current = getNumber(numbers[i]); + if (current.compareTo(max) > 0) { + max = current; + } + } + + return max; + } + + /** + * 获取数字的绝对值 + * 使用BigDecimal进行精确计算,避免浮点数精度问题 + * + * @param number 待计算绝对值的数字,不能为null + * @return 数字的绝对值,使用BigDecimal保证精度 + * @throws IllegalArgumentException 当数字为null时抛出 + */ + public static BigDecimal abs(Number number) { + Assert.notNull(number); + + if (number instanceof BigDecimal) { + return ((BigDecimal) number).abs(); + } else { + return BigDecimal.valueOf(number.doubleValue()).abs(); + } + } + + /** + * 将数字格式化为指定精度的小数 + * 使用四舍五入模式保留指定的小数位数 + * + * @param number 待格式化的数字,不能为null + * @param precision 保留的小数位数,必须大于等于0 + * @return 格式化后的数字,使用BigDecimal保证精度 + */ + public static BigDecimal getNumber(Number number, int precision) { + + precision = Math.max(0, precision); + + BigDecimal result = getNumber(number).setScale(precision, BigDecimal.ROUND_HALF_UP); + + return result.stripTrailingZeros(); + } + + /** + * 将Number类型转换为BigDecimal类型 + * 内部工具方法,用于统一数字类型转换 + * + * @param number 待转换的数字,不能为null + * @return 转换后的BigDecimal对象 + * @throws IllegalArgumentException 当数字为null时抛出 + */ + private static BigDecimal getNumber(Number number) { + + Assert.notNull(number); + + if (number instanceof BigDecimal) { + return (BigDecimal) number; + } else { + return BigDecimal.valueOf(number.doubleValue()); + } + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/ObjectUtil.java b/common/src/main/java/com/lframework/starter/common/utils/ObjectUtil.java new file mode 100644 index 0000000..0a112a8 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/ObjectUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * 对象工具类 + * 基于HuTool的ObjectUtil进行扩展,提供对象操作相关的工具方法 + * 包括对象判空、类型转换、克隆、序列化等功能 + * + * @author lframework@163.com + */ +public class ObjectUtil extends cn.hutool.core.util.ObjectUtil { + +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/ReflectUtil.java b/common/src/main/java/com/lframework/starter/common/utils/ReflectUtil.java new file mode 100644 index 0000000..088b591 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/ReflectUtil.java @@ -0,0 +1,70 @@ +package com.lframework.starter.common.utils; + +import com.lframework.starter.common.functions.SFunction; + +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * 反射工具类 + * 基于HuTool的ReflectUtil进行扩展,提供反射操作相关的工具方法 + * 包括字段获取、方法调用、Lambda表达式字段名提取等功能 + * + * @author lframework@163.com + */ +public class ReflectUtil extends cn.hutool.core.util.ReflectUtil { + + /** + * 获取实体类的字段名称(实体声明的字段名称) + * 通过Lambda表达式获取对应的字段名称,支持getter方法 + * + * @param fn Lambda表达式,如 User::getName + * @param 实体类型 + * @return 字段名称,如 "name" + * @throws RuntimeException 当获取字段名失败时抛出 + */ + public static String getFieldName(SFunction fn) { + + SerializedLambda serializedLambda = getSerializedLambda(fn); + + // 从lambda信息取出method、field、class等 + String fieldName = serializedLambda.getImplMethodName().substring("get".length()); + fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", + (fieldName.charAt(0) + "").toLowerCase()); + + // 从field取出字段名,可以根据实际情况调整 + return fieldName.replaceAll("[A-Z]", "$0"); + } + + /** + * 获取Lambda表达式的序列化信息 + * 通过反射获取Lambda表达式的序列化Lambda对象 + * + * @param fn Lambda表达式,不能为null + * @param 实体类型 + * @return 序列化Lambda对象 + * @throws RuntimeException 当获取序列化Lambda失败时抛出 + */ + private static SerializedLambda getSerializedLambda(SFunction fn) { + // 从function取出序列化方法 + Method writeReplaceMethod; + try { + writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace"); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + + // 从序列化方法取出序列化的lambda信息 + boolean isAccessible = writeReplaceMethod.isAccessible(); + writeReplaceMethod.setAccessible(true); + SerializedLambda serializedLambda; + try { + serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + writeReplaceMethod.setAccessible(isAccessible); + return serializedLambda; + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/RegUtil.java b/common/src/main/java/com/lframework/starter/common/utils/RegUtil.java new file mode 100644 index 0000000..3fb36b9 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/RegUtil.java @@ -0,0 +1,28 @@ +package com.lframework.starter.common.utils; + +import cn.hutool.core.util.ReUtil; + +import java.util.regex.Pattern; + +/** + * 正则表达式工具类 + * 基于HuTool的ReUtil进行扩展,提供正则表达式相关的工具方法 + * 包括模式匹配、字符串替换、提取等功能 + * + * @author lframework@163.com + */ +public class RegUtil { + + /** + * 判断字符串是否匹配指定的正则表达式模式 + * 使用预编译的Pattern对象进行匹配,提高性能 + * + * @param pattern 预编译的正则表达式模式,不能为null + * @param str 要匹配的字符串,不能为null + * @return true-匹配成功,false-匹配失败 + */ + public static boolean isMatch(Pattern pattern, String str) { + + return ReUtil.isMatch(pattern, str); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/StringUtil.java b/common/src/main/java/com/lframework/starter/common/utils/StringUtil.java new file mode 100644 index 0000000..4ddbc7f --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/StringUtil.java @@ -0,0 +1,76 @@ +package com.lframework.starter.common.utils; + +import cn.hutool.core.util.StrUtil; +import com.lframework.starter.common.constants.PatternPool; + +/** + * 字符串工具类 + * 基于HuTool的StrUtil进行扩展,提供字符串操作相关的工具方法 + * 包括字符串验证、脱敏处理、模式匹配等功能 + * + * @author lframework@163.com + */ +public class StringUtil extends StrUtil { + + /** + * 邮箱地址脱敏处理 + * 将邮箱地址进行脱敏,保留首字符和域名部分 + * + * @param email 邮箱地址,不能为null + * @return 脱敏后的邮箱地址,如果格式不正确则返回null + */ + public static String encodeEmail(String email) { + + if (!RegUtil.isMatch(PatternPool.PATTERN_EMAIL, email)) { + return null; + } + + return email.charAt(0) + "******" + "@" + email.split("@")[1]; + } + + /** + * 手机号码脱敏处理 + * 将手机号码进行脱敏,保留前3位和后4位 + * + * @param telephone 手机号码,不能为null + * @return 脱敏后的手机号码,如果格式不正确则返回null + */ + public static String encodeTelephone(String telephone) { + + if (!RegUtil.isMatch(PatternPool.PATTERN_CN_TEL, telephone)) { + return null; + } + + return telephone.substring(0, 3) + "****" + telephone.substring(7); + } + + /** + * 字符串模式匹配,支持*和?通配符 + * 支持*匹配任意字符,?匹配单个字符的通配符匹配 + * + * @param str 要匹配的字符串,不能为null + * @param pattern 匹配模式,支持*和?通配符,不能为null + * @return true-匹配成功,false-匹配失败 + */ + public static boolean strMatch(String str, String pattern) { + if (StringUtil.isEmpty(str) && StringUtil.isEmpty(pattern)) { + return true; + } + if ("*".equals(str)) { + return true; + } + if (StringUtil.isEmpty(str) || StringUtil.isEmpty(pattern)) { + return false; + } + if ("?".equals(str.substring(0, 1))) { + return strMatch(str.substring(1), pattern.substring(1)); + } else if ("*".equals(str.substring(0, 1))) { + return strMatch(str.substring(1), pattern) || strMatch(str.substring(1), pattern.substring(1)) + || strMatch(str, pattern.substring(1)); + } else if (pattern.substring(0, 1).equals(str.substring(0, 1))) { + return strMatch(str.substring(1), pattern.substring(1)); + } else { + return false; + } + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/ThreadUtil.java b/common/src/main/java/com/lframework/starter/common/utils/ThreadUtil.java new file mode 100644 index 0000000..ba03b18 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/ThreadUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * 线程工具类 + * 基于HuTool的ThreadUtil进行扩展,提供线程相关的工具方法 + * 包括线程池创建、线程管理、异步任务执行等功能 + * + * @author lframework@163.com + */ +public class ThreadUtil extends cn.hutool.core.thread.ThreadUtil { + +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/XmlUtil.java b/common/src/main/java/com/lframework/starter/common/utils/XmlUtil.java new file mode 100644 index 0000000..e111f12 --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/XmlUtil.java @@ -0,0 +1,361 @@ +package com.lframework.starter.common.utils; + +import org.dom4j.*; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; + +/** + * XML工具类 + * 提供XML与Map之间的相互转换、XML格式化等功能 + * 支持带属性和不带属性的XML解析,以及XML文档的格式化输出 + * + * @author lframework@163.com + */ +public class XmlUtil { + + /** + * 将XML字符串转换为Map(不包含根节点键) + * 默认不包含根节点键,直接返回子节点内容 + * + * @param xmlStr XML字符串,不能为null或空 + * @return 转换后的Map对象 + * @throws DocumentException 当XML格式错误时抛出 + */ + public static Map xml2map(String xmlStr) throws DocumentException { + + return xml2map(xmlStr, false); + } + + /** + * 将XML字符串转换为Map(不带属性) + * 解析XML字符串并转换为Map结构,不包含XML属性信息 + * + * @param xmlStr XML字符串,不能为null或空 + * @param needRootKey 是否需要在返回的Map中包含根节点键 + * @return 转换后的Map对象,包含XML的层次结构 + * @throws DocumentException 当XML格式错误时抛出 + */ + public static Map xml2map(String xmlStr, boolean needRootKey) + throws DocumentException { + + Document doc = DocumentHelper.parseText(xmlStr); + Element root = doc.getRootElement(); + Map map = (Map) xml2map(root); + if (root.elements().size() == 0 && root.attributes().size() == 0) { + return map; + } + if (needRootKey) { + //在返回的map里加根节点键(如果需要) + Map rootMap = new HashMap(); + rootMap.put(root.getName(), map); + return rootMap; + } + return map; + } + + /** + * 将XML字符串转换为Map(带属性) + * 解析XML字符串并转换为Map结构,包含XML属性信息 + * 属性以"@"前缀标识,文本内容以"#text"标识 + * + * @param xmlStr XML字符串,不能为null或空 + * @param needRootKey 是否需要在返回的Map中包含根节点键 + * @return 转换后的Map对象,包含XML的层次结构和属性信息 + * @throws DocumentException 当XML格式错误时抛出 + */ + public static Map xml2mapWithAttr(String xmlStr, boolean needRootKey) throws DocumentException { + + Document doc = DocumentHelper.parseText(xmlStr); + Element root = doc.getRootElement(); + Map map = (Map) xml2mapWithAttr(root); + if (root.elements().size() == 0 && root.attributes().size() == 0) { + return map; //根节点只有一个文本内容 + } + if (needRootKey) { + //在返回的map里加根节点键(如果需要) + Map rootMap = new HashMap(); + rootMap.put(root.getName(), map); + return rootMap; + } + return map; + } + + /** + * 将XML元素转换为Map(不带属性) + * 递归处理XML元素,将子元素转换为Map结构 + * + * @param e XML元素,不能为null + * @return 转换后的Map对象 + */ + private static Map xml2map(Element e) { + + Map map = new LinkedHashMap(); + List list = e.elements(); + if (list.size() > 0) { + for (int i = 0; i < list.size(); i++) { + Element iter = (Element) list.get(i); + List mapList = new ArrayList(); + + if (iter.elements().size() > 0) { + Map m = xml2map(iter); + if (map.get(iter.getName()) != null) { + Object obj = map.get(iter.getName()); + if (!(obj instanceof List)) { + mapList = new ArrayList(); + mapList.add(obj); + mapList.add(m); + } + if (obj instanceof List) { + mapList = (List) obj; + mapList.add(m); + } + map.put(iter.getName(), mapList); + } else { + map.put(iter.getName(), m); + } + } else { + if (map.get(iter.getName()) != null) { + Object obj = map.get(iter.getName()); + if (!(obj instanceof List)) { + mapList = new ArrayList(); + mapList.add(obj); + mapList.add(iter.getText()); + } + if (obj instanceof List) { + mapList = (List) obj; + mapList.add(iter.getText()); + } + map.put(iter.getName(), mapList); + } else { + map.put(iter.getName(), iter.getText()); + } + } + } + } else { + map.put(e.getName(), e.getText()); + } + return map; + } + + /** + * 将XML元素转换为Map(带属性) + * 递归处理XML元素,将子元素和属性转换为Map结构 + * 属性以"@"前缀标识,文本内容以"#text"标识 + * + * @param element XML元素,不能为null + * @return 转换后的Map对象,包含属性和文本内容 + */ + private static Map xml2mapWithAttr(Element element) { + + Map map = new LinkedHashMap(); + + List list = element.elements(); + List listAttr0 = element.attributes(); // 当前节点的所有属性的list + for (Attribute attr : listAttr0) { + map.put("@" + attr.getName(), attr.getValue()); + } + if (list.size() > 0) { + + for (int i = 0; i < list.size(); i++) { + Element iter = list.get(i); + List mapList = new ArrayList(); + + if (iter.elements().size() > 0) { + Map m = xml2mapWithAttr(iter); + if (map.get(iter.getName()) != null) { + Object obj = map.get(iter.getName()); + if (!(obj instanceof List)) { + mapList = new ArrayList(); + mapList.add(obj); + mapList.add(m); + } + if (obj instanceof List) { + mapList = (List) obj; + mapList.add(m); + } + map.put(iter.getName(), mapList); + } else { + map.put(iter.getName(), m); + } + } else { + + List listAttr = iter.attributes(); // 当前节点的所有属性的list + Map attrMap = null; + boolean hasAttributes = false; + if (listAttr.size() > 0) { + hasAttributes = true; + attrMap = new LinkedHashMap(); + for (Attribute attr : listAttr) { + attrMap.put("@" + attr.getName(), attr.getValue()); + } + } + + if (map.get(iter.getName()) != null) { + Object obj = map.get(iter.getName()); + if (!(obj instanceof List)) { + mapList = new ArrayList(); + mapList.add(obj); + // mapList.add(iter.getText()); + if (hasAttributes) { + attrMap.put("#text", iter.getText()); + mapList.add(attrMap); + } else { + mapList.add(iter.getText()); + } + } + if (obj instanceof List) { + mapList = (List) obj; + // mapList.add(iter.getText()); + if (hasAttributes) { + attrMap.put("#text", iter.getText()); + mapList.add(attrMap); + } else { + mapList.add(iter.getText()); + } + } + map.put(iter.getName(), mapList); + } else { + // map.put(iter.getName(), iter.getText()); + if (hasAttributes) { + attrMap.put("#text", iter.getText()); + map.put(iter.getName(), attrMap); + } else { + map.put(iter.getName(), iter.getText()); + } + } + } + } + } else { + // 根节点的 + if (listAttr0.size() > 0) { + map.put("#text", element.getText()); + } else { + map.put(element.getName(), element.getText()); + } + } + return map; + } + + /** + * 将Map转换为XML文档(指定根节点名称) + * 当Map中没有根节点键时,使用指定的根节点名称创建XML文档 + * + * @param map 要转换的Map对象,不能为null + * @param rootName 根节点名称,不能为null或空 + * @return 转换后的XML文档对象 + */ + public static Document map2xml(Map map, String rootName) { + + Document doc = DocumentHelper.createDocument(); + Element root = DocumentHelper.createElement(rootName); + doc.add(root); + map2xml(map, root); + return doc; + } + + /** + * 将Map转换为XML文档(包含根节点键) + * 当Map中包含根节点键时,使用第一个键作为根节点名称创建XML文档 + * + * @param map 要转换的Map对象,不能为null且不能为空 + * @return 转换后的XML文档对象,如果Map为空则返回null + */ + public static Document map2xml(Map map) { + + Iterator> entries = map.entrySet().iterator(); + if (entries.hasNext()) { //获取第一个键创建根节点 + Map.Entry entry = entries.next(); + Document doc = DocumentHelper.createDocument(); + Element root = DocumentHelper.createElement(entry.getKey()); + doc.add(root); + map2xml((Map) entry.getValue(), root); + return doc; + } + return null; + } + + /** + * 将Map转换为XML元素 + * 递归处理Map,将键值对转换为XML元素和属性 + * 支持List、Map等复杂数据结构的转换 + * + * @param map 要转换的Map对象,不能为null + * @param body 父级XML元素,不能为null + * @return 转换后的XML元素 + */ + private static Element map2xml(Map map, Element body) { + + Iterator> entries = map.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry entry = entries.next(); + String key = entry.getKey(); + Object value = entry.getValue(); + if (key.startsWith("@")) { //属性 + body.addAttribute(key.substring(1, key.length()), value.toString()); + } else if (key.equals("#text")) { //有属性时的文本 + body.setText(value.toString()); + } else { + if (value instanceof List) { + List list = (List) value; + Object obj; + for (int i = 0; i < list.size(); i++) { + obj = list.get(i); + //list里是map或String,不会存在list里直接是list的, + if (obj instanceof Map) { + Element subElement = body.addElement(key); + map2xml((Map) list.get(i), subElement); + } else { + body.addElement(key).setText((String) list.get(i)); + } + } + } else if (value instanceof Map) { + Element subElement = body.addElement(key); + map2xml((Map) value, subElement); + } else { + body.addElement(key).setText(value.toString()); + } + } + } + return body; + } + + /** + * 格式化输出XML字符串 + * 将XML字符串格式化为易读的格式,包含缩进和换行 + * + * @param xmlStr 要格式化的XML字符串,不能为null或空 + * @return 格式化后的XML字符串 + * @throws DocumentException 当XML格式错误时抛出 + * @throws IOException 当IO操作失败时抛出 + */ + public static String formatXml(String xmlStr) throws DocumentException, IOException { + + Document document = DocumentHelper.parseText(xmlStr); + return formatXml(document); + } + + /** + * 格式化输出XML文档 + * 将XML文档格式化为易读的格式,包含缩进和换行 + * + * @param document 要格式化的XML文档,不能为null + * @return 格式化后的XML字符串 + * @throws IOException 当IO操作失败时抛出 + */ + public static String formatXml(Document document) throws IOException { + // 格式化输出格式 + OutputFormat format = OutputFormat.createPrettyPrint(); + //format.setEncoding("UTF-8"); + StringWriter writer = new StringWriter(); + // 格式化输出流 + XMLWriter xmlWriter = new XMLWriter(writer, format); + // 将document写入到输出流 + xmlWriter.write(document); + xmlWriter.close(); + return writer.toString(); + } +} diff --git a/common/src/main/java/com/lframework/starter/common/utils/ZipUtil.java b/common/src/main/java/com/lframework/starter/common/utils/ZipUtil.java new file mode 100644 index 0000000..06061ba --- /dev/null +++ b/common/src/main/java/com/lframework/starter/common/utils/ZipUtil.java @@ -0,0 +1,12 @@ +package com.lframework.starter.common.utils; + +/** + * 压缩工具类 + * 基于HuTool的ZipUtil进行扩展,提供ZIP文件压缩和解压缩功能 + * 支持文件和目录的压缩、解压缩、流式处理等操作 + * + * @author lframework@163.com + */ +public class ZipUtil extends cn.hutool.core.util.ZipUtil { + +} diff --git a/common/src/main/java/lombok.config b/common/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/common/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/mq-starter/README.md b/mq-starter/README.md new file mode 100644 index 0000000..ea8aeab --- /dev/null +++ b/mq-starter/README.md @@ -0,0 +1,13 @@ +# mq-starter —— 消息队列集成 + +## 概述 + +mq-starter 提供消息队列的抽象封装和具体实现,支持 ActiveMQ 和 RabbitMQ 两种消息中间件,业务模块通过统一接口发送和消费消息。 + +## 模块构成 + +| 模块 | 说明 | +|------|------| +| [mq-core](./mq-core) | MQ 抽象层,定义消息队列的统一接口、事件模型和导出任务处理 | +| [activemq-starter](./activemq-starter) | ActiveMQ 实现 | +| [rabbitmq-starter](./rabbitmq-starter) | RabbitMQ 实现 | diff --git a/mq-starter/activemq-starter/README.md b/mq-starter/activemq-starter/README.md new file mode 100644 index 0000000..185fc80 --- /dev/null +++ b/mq-starter/activemq-starter/README.md @@ -0,0 +1,12 @@ +# activemq-starter —— ActiveMQ 消息队列实现 + +## 概述 + +ActiveMQ 消息队列的 Spring Boot Starter 实现。基于 ActiveMQ Classic,提供消息的生产与消费能力。 + +## 核心能力 + +- ActiveMQ 连接工厂自动配置 +- 消息生产者(实现 MqProducer 接口) +- 消息监听器容器 +- 自定义拦截器 diff --git a/mq-starter/activemq-starter/pom.xml b/mq-starter/activemq-starter/pom.xml new file mode 100644 index 0000000..68e2958 --- /dev/null +++ b/mq-starter/activemq-starter/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + mq-starter + com.lframework + 1.0.0 + + + activemq-starter + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + mq-core + com.lframework + + + + spring-boot-starter-activemq + org.springframework.boot + + + org.apache.activemq + activemq-broker + + + pooled-jms + org.messaginghub + + + + \ No newline at end of file diff --git a/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/config/ActiveMqAutoConfiguration.java b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/config/ActiveMqAutoConfiguration.java new file mode 100644 index 0000000..aaad290 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/config/ActiveMqAutoConfiguration.java @@ -0,0 +1,17 @@ +package com.lframework.starter.mq.activemq.config; + +import com.lframework.starter.mq.activemq.producer.ActiveMqProducer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.annotation.EnableJms; +import org.springframework.jms.core.JmsTemplate; + +@EnableJms +@Configuration +public class ActiveMqAutoConfiguration { + + @Bean + public ActiveMqProducer activeMqProducer(JmsTemplate jmsTemplate) { + return new ActiveMqProducer(jmsTemplate); + } +} diff --git a/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/interceptors/ActiveMqTenantInterceptor.java b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/interceptors/ActiveMqTenantInterceptor.java new file mode 100644 index 0000000..5071168 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/interceptors/ActiveMqTenantInterceptor.java @@ -0,0 +1,29 @@ +package com.lframework.starter.mq.activemq.interceptors; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.activemq.broker.ProducerBrokerExchange; +import org.apache.activemq.broker.inteceptor.MessageInterceptor; +import org.apache.activemq.command.Message; + +@Slf4j +public class ActiveMqTenantInterceptor implements MessageInterceptor { + + @Override + public void intercept(ProducerBrokerExchange producerBrokerExchange, Message message) { + try { + if (TenantUtil.enableTenant()) { + Object obj = message.getProperty("tenantId"); + if (obj != null) { + Integer tenantId = Integer.valueOf(obj.toString()); + TenantContextHolder.setTenantId(tenantId); + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } +} diff --git a/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/producer/ActiveMqProducer.java b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/producer/ActiveMqProducer.java new file mode 100644 index 0000000..5d96eed --- /dev/null +++ b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/producer/ActiveMqProducer.java @@ -0,0 +1,126 @@ +package com.lframework.starter.mq.activemq.producer; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.mq.activemq.queue.ActiveMqQueueDefinition; +import com.lframework.starter.mq.core.producer.MqProducer; +import com.lframework.starter.mq.core.queue.QueueDefinition; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import jakarta.jms.Message; +import org.apache.activemq.ScheduledMessage; +import org.springframework.jms.core.JmsTemplate; + +import java.io.Serializable; + +/** + * ActiveMQ生产者 + * + * @author zmj + * @since 2022/8/25 + */ +public class ActiveMqProducer implements MqProducer { + + private final JmsTemplate jmsTemplate; + + public ActiveMqProducer(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } + + @Override + public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis) { + sendDelayMessage(definition, data, millis, TenantContextHolder.getTenantId()); + } + + @Override + public void sendMessage(QueueDefinition definition, Serializable data) { + sendMessage(definition, data, TenantContextHolder.getTenantId()); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, long millis) { + sendDelayMessage(definition, millis, TenantContextHolder.getTenantId()); + } + + @Override + public void sendMessage(QueueDefinition definition) { + sendMessage(definition, TenantContextHolder.getTenantId()); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis, + Integer tenantId) { + Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0); + + jmsTemplate.send(convertDefinition(definition), session -> { + + Message msg = session.createObjectMessage(data); + if (TenantUtil.enableTenant()) { + Assert.notNull(tenantId); + msg.setIntProperty("tenantId", tenantId); + } + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, millis); + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1000); + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1); + return msg; + }); + } + + @Override + public void sendMessage(QueueDefinition definition, Serializable data, Integer tenantId) { + + jmsTemplate.send(convertDefinition(definition), session -> { + + Message msg = session.createObjectMessage(data); + if (TenantUtil.enableTenant()) { + Assert.notNull(tenantId); + msg.setIntProperty("tenantId", tenantId); + } + return msg; + }); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, long millis, Integer tenantId) { + Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0); + + jmsTemplate.send(convertDefinition(definition), session -> { + + Message msg = session.createTextMessage(); + if (TenantUtil.enableTenant()) { + Assert.notNull(tenantId); + msg.setIntProperty("tenantId", tenantId); + } + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, millis); + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1000); + msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1); + return msg; + }); + } + + @Override + public void sendMessage(QueueDefinition definition, Integer tenantId) { + jmsTemplate.send(convertDefinition(definition), session -> { + + Message msg = session.createTextMessage(); + if (TenantUtil.enableTenant()) { + Assert.notNull(tenantId); + msg.setIntProperty("tenantId", tenantId); + } + return msg; + }); + } + + private String convertDefinition(QueueDefinition definition) { + if (definition == null) { + throw new DefaultSysException("definition不能为空!"); + } + + if (definition instanceof ActiveMqQueueDefinition) { + return ((ActiveMqQueueDefinition) definition).getQueue(); + } else { + throw new DefaultSysException( + "没有找到" + definition.getClass().getName() + "对应的QueueDefinition"); + } + } +} diff --git a/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/queue/ActiveMqQueueDefinition.java b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/queue/ActiveMqQueueDefinition.java new file mode 100644 index 0000000..48cc6b6 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/java/com/lframework/starter/mq/activemq/queue/ActiveMqQueueDefinition.java @@ -0,0 +1,17 @@ +package com.lframework.starter.mq.activemq.queue; + +import com.lframework.starter.mq.core.queue.QueueDefinition; +import lombok.Getter; + +@Getter +public class ActiveMqQueueDefinition implements QueueDefinition { + + /** + * 队列名 + */ + private String queue; + + public ActiveMqQueueDefinition(String queue) { + this.queue = queue; + } +} diff --git a/mq-starter/activemq-starter/src/main/java/lombok.config b/mq-starter/activemq-starter/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/mq-starter/activemq-starter/src/main/resources/META-INF/spring.factories b/mq-starter/activemq-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..b0d9603 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.mq.activemq.config.ActiveMqAutoConfiguration \ No newline at end of file diff --git a/mq-starter/activemq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/mq-starter/activemq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..b35f961 --- /dev/null +++ b/mq-starter/activemq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.lframework.starter.mq.activemq.config.ActiveMqAutoConfiguration diff --git a/mq-starter/mq-core/README.md b/mq-starter/mq-core/README.md new file mode 100644 index 0000000..f27fe5f --- /dev/null +++ b/mq-starter/mq-core/README.md @@ -0,0 +1,13 @@ +# mq-core —— 消息队列核心抽象 + +## 概述 + +mq-core 是 MQ 模块的核心抽象层,定义消息队列的统一接口、事件模型和导出任务(异步导出 Excel)处理能力。 + +## 核心能力 + +- **MqProducer** —— 消息发送者接口 +- **MqQueue** —— 消息队列定义接口 +- **消息事件模型** —— 基于 Spring ApplicationEvent 的消息事件机制 +- **异步导出** —— 通过 MQ 异步处理 Excel 导出任务,支持进度查询 +- **消息处理异常处理器** diff --git a/mq-starter/mq-core/pom.xml b/mq-starter/mq-core/pom.xml new file mode 100644 index 0000000..d1602ba --- /dev/null +++ b/mq-starter/mq-core/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + + mq-starter + com.lframework + 1.0.0 + + + mq-core + + + + web-starter + com.lframework + + + org.projectlombok + lombok + provided + + + + \ No newline at end of file diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/ExportingExportTaskBo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/ExportingExportTaskBo.java new file mode 100644 index 0000000..ec7af25 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/ExportingExportTaskBo.java @@ -0,0 +1,54 @@ +package com.lframework.starter.mq.core.bo; + +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.web.core.bo.BaseBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class ExportingExportTaskBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 总数据条数 + */ + @Schema(description = "总数据条数") + private Long totalCount; + + /** + * 当前完成数据条数 + */ + @Schema(description = "当前完成数据条数") + private Long curCount; + + /** + * 状态 + */ + @Schema(description = "状态") + private Integer status; + + public ExportingExportTaskBo(ExportTask dto) { + super(dto); + } + + @Override + public BaseBo convert(ExportTask dto) { + return super.convert(dto, ExportingExportTaskBo::getStatus); + } + + @Override + protected void afterInit(ExportTask dto) { + this.status = dto.getStatus().getCode(); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/FailExportTaskBo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/FailExportTaskBo.java new file mode 100644 index 0000000..9624b7a --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/FailExportTaskBo.java @@ -0,0 +1,40 @@ +package com.lframework.starter.mq.core.bo; + +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.web.core.bo.BaseBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class FailExportTaskBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 错误信息 + */ + @Schema(description = "错误信息") + private String errorMsg; + + public FailExportTaskBo(ExportTask dto) { + super(dto); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/SuccessExportTaskBo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/SuccessExportTaskBo.java new file mode 100644 index 0000000..607b19a --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/bo/SuccessExportTaskBo.java @@ -0,0 +1,58 @@ +package com.lframework.starter.mq.core.bo; + +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.web.core.bo.BaseBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class SuccessExportTaskBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 文件大小 + */ + @Schema(description = "文件大小") + private String fileSize; + + /** + * 上传记录ID + */ + @Schema(description = "上传记录ID") + private String recordId; + + /** + * 总数据条数 + */ + @Schema(description = "总数据条数") + private Long totalCount; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 完成时间 + */ + @Schema(description = "完成时间") + private LocalDateTime finishTime; + + public SuccessExportTaskBo(ExportTask dto) { + super(dto); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java new file mode 100644 index 0000000..4abf075 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java @@ -0,0 +1,47 @@ +package com.lframework.starter.mq.core.components.export; + +import com.lframework.starter.web.core.components.excel.ExcelModel; +import com.lframework.starter.web.core.components.resp.PageResult; + +public interface ExportTaskWorker { + + /** + * 解析传入参数 + * + * @param json + * @return + */ + P parseParams(String json); + + /** + * 查询数据 + * + * @param pageIndex + * @param pageSize + * @param params + * @return + */ + PageResult getDataList(int pageIndex, int pageSize, P params); + + /** + * 导出数据 + * + * @param data + */ + M exportData(D data); + + /** + * 处理异常 + * + * @param e + */ + default void handleError(Exception e) { + } + + /** + * 获取导出模型类 + * + * @return + */ + Class getModelClass(); +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java new file mode 100644 index 0000000..a039b13 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java @@ -0,0 +1,25 @@ +package com.lframework.starter.mq.core.config; + +import com.lframework.starter.mq.core.controller.ExportTaskController; +import com.lframework.starter.mq.core.impl.ExportTaskServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; + +@Slf4j +@Configuration +@Import({ + ExportTaskServiceImpl.class, + ExportTaskController.class, +}) +@MapperScan("com.lframework.starter.mq.core.**.mappers") +public class MqBeanAutoConfiguration implements EnvironmentAware { + + @Override + public void setEnvironment(Environment environment) { + log.info("mq-core加载完成"); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java new file mode 100644 index 0000000..9416c3e --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java @@ -0,0 +1,18 @@ +package com.lframework.starter.mq.core.config; + +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MqSwaggerAutoConfiguration { + + @Bean("mqApiDocket") + public GroupedOpenApi mqApiDocket() { + return GroupedOpenApi.builder() + .group("消息队列模块") + .packagesToScan("com.lframework.starter.mq.core") + .pathsToMatch("/**") + .build(); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java new file mode 100644 index 0000000..9ae3e9e --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java @@ -0,0 +1,107 @@ +package com.lframework.starter.mq.core.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.core.bo.ExportingExportTaskBo; +import com.lframework.starter.mq.core.bo.FailExportTaskBo; +import com.lframework.starter.mq.core.bo.SuccessExportTaskBo; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.mq.core.enums.ExportTaskStatus; +import com.lframework.starter.mq.core.service.ExportTaskService; +import com.lframework.starter.mq.core.vo.QueryFailExportTaskVo; +import com.lframework.starter.mq.core.vo.QuerySuccessExportTaskVo; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 导出任务 + * + * @author zmj + */ +@Tag(name = "导出任务") +@Validated +@RestController +@RequestMapping("/export/task") +public class ExportTaskController extends DefaultBaseController { + + @Autowired + private ExportTaskService exportTaskService; + + /** + * 正在导出列表 + */ + @Operation(summary = "正在导出列表") + @GetMapping("/exporting") + public InvokeResult> queryExporting() { + + Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class) + .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId()) + .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING) + .orderByDesc(ExportTask::getCreateTime); + List datas = exportTaskService.list(queryWrapper); + + List results = datas.stream().map(ExportingExportTaskBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "导出成功列表") + @GetMapping("/success") + public InvokeResult> querySuccess( + @Valid QuerySuccessExportTaskVo vo) { + Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class) + .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId()) + .eq(ExportTask::getStatus, ExportTaskStatus.SUCCESS) + .like(StringUtil.isNotBlank(vo.getName()), ExportTask::getName, vo.getName()) + .orderByDesc(ExportTask::getCreateTime); + + Page page = new Page<>(getPageIndex(vo), getPageSize(vo)); + + Page pageList = exportTaskService.page(page, queryWrapper); + PageResult pageResult = PageResultUtil.convert(pageList); + List datas = pageResult.getDatas(); + List results = datas.stream().map(SuccessExportTaskBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @Operation(summary = "导出失败列表") + @GetMapping("/fail") + public InvokeResult> queryFail( + @Valid QueryFailExportTaskVo vo) { + Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class) + .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId()) + .eq(ExportTask::getStatus, ExportTaskStatus.FAIL) + .like(StringUtil.isNotBlank(vo.getName()), ExportTask::getName, vo.getName()) + .orderByDesc(ExportTask::getCreateTime); + + Page page = new Page<>(getPageIndex(vo), getPageSize(vo)); + + Page pageList = exportTaskService.page(page, queryWrapper); + PageResult pageResult = PageResultUtil.convert(pageList); + List datas = pageResult.getDatas(); + List results = datas.stream().map(FailExportTaskBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java new file mode 100644 index 0000000..f37ceaf --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java @@ -0,0 +1,31 @@ +package com.lframework.starter.mq.core.dto; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AddExportTaskDto implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + private String name; + + /** + * 请求类名 + */ + private String reqClassName; + + /** + * 请求类方法参数 + */ + private String reqParams; + + /** + * 用户Token + */ + private String token; +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java new file mode 100644 index 0000000..7d3a8c7 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java @@ -0,0 +1,16 @@ +package com.lframework.starter.mq.core.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ExecuteExportTaskDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + private String taskId; + + private String token; +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java new file mode 100644 index 0000000..c9a621d --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java @@ -0,0 +1,18 @@ +package com.lframework.starter.mq.core.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ExportTaskSummaryDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + private Integer unFinishedCount; + + private Integer successCount; + + private Integer failCount; +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java new file mode 100644 index 0000000..9db82a3 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java @@ -0,0 +1,107 @@ +package com.lframework.starter.mq.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.mq.core.enums.ExportTaskStatus; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 导出任务 + *

+ * + * @author zmj + * @since 2025-04-10 + */ +@Data +@TableName("tbl_export_task") +public class ExportTask extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ExportTask"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 上传记录ID + */ + private String recordId; + + /** + * 状态 + */ + private ExportTaskStatus status; + + /** + * 错误信息 + */ + private String errorMsg; + + /** + * 请求类名 + */ + private String reqClassName; + + + /** + * 请求类方法参数 + */ + private String reqParams; + + /** + * 请求类方法参数签名 + */ + private String reqParamsSign; + + /** + * 总数据条数 + */ + private Long totalCount; + + /** + * 当前完成数据条数 + */ + private Long curCount; + + /** + * 文件大小 + */ + private String fileSize; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 结束时间 + */ + private LocalDateTime finishTime; +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java new file mode 100644 index 0000000..0eac865 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java @@ -0,0 +1,34 @@ +package com.lframework.starter.mq.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum ExportTaskStatus implements BaseEnum { + CREATED(0, "等待导出"), + EXPORTING(1, "正在导出"), + SUCCESS(2, "导出成功"), + FAIL(3, "导出失败"); + + @EnumValue + private final Integer code; + + private final String desc; + + ExportTaskStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java new file mode 100644 index 0000000..5f4bb5d --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java @@ -0,0 +1,15 @@ +package com.lframework.starter.mq.core.events; + +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +public class ExportTaskNotifyEvent extends ApplicationEvent { + + @Getter + private String createById; + + public ExportTaskNotifyEvent(Object source, String createById) { + super(source); + this.createById = createById; + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java new file mode 100644 index 0000000..c41951b --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java @@ -0,0 +1,164 @@ +package com.lframework.starter.mq.core.handlers; + +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.core.components.export.ExportTaskWorker; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.mq.core.service.ExportTaskService; +import com.lframework.starter.web.core.components.excel.ExcelModel; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.ExcelUtil; +import com.lframework.starter.web.core.utils.UploadUtil; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class ExportTaskHandler { + + // 每页条数 + private static final int PER_PAGE_SIZE = 10000; + + // 上报处理条数的攒批数量 + private static final int COUNT_BATCH_SIZE = 100; + + private ExportTaskWorker exportTaskWorker; + + private long timeout; + + private int curCount; + + private String taskId; + + public ExportTaskHandler(String taskId, ExportTaskWorker exportTaskWorker, + long timeout) { + this.taskId = taskId; + this.exportTaskWorker = exportTaskWorker; + this.timeout = timeout; + } + + public void execute(String json) { + + ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class); + + ExportTask exportTask = exportTaskService.getById(taskId); + + String tmpLocation = ApplicationUtil.getEnv().getProperty("spring.servlet.multipart.location"); + tmpLocation = tmpLocation.endsWith(File.separator) ? tmpLocation : tmpLocation + File.separator; + try { + // 将导出任务状态置为正在导出 + exportTaskService.setExporting(taskId); + + P params = exportTaskWorker.parseParams(json); + + long beginTs = System.currentTimeMillis(); + int pageIndex = 1; + File xlsxFile = FileUtil.newFile(tmpLocation + taskId + ".xlsx"); + + ExcelWriter writer = ExcelUtil.createWriter( + FileUtil.getOutputStream(xlsxFile), + exportTaskWorker.getModelClass(), + null, + ExcelTypeEnum.XLSX + ); + + WriteSheet sheet = ExcelUtil.createSheet("Sheet1"); + + boolean setTotalCount = false; + + try { + while (true) { + + PageResult pageResult = + exportTaskWorker.getDataList(pageIndex, PER_PAGE_SIZE, params); + + this.checkCurrentUser(); + + if (!setTotalCount) { + exportTaskService.setTotalCount(taskId, pageResult.getTotalCount()); + setTotalCount = true; + } + + long calcTs = System.currentTimeMillis() - beginTs; + if (calcTs > timeout * 1000L) { + throw new DefaultClientException("导出超时"); + } + + List dataList = pageResult.getDatas(); + List modelList = new ArrayList<>(dataList.size()); + + for (D data : dataList) { + modelList.add(exportTaskWorker.exportData(data)); + this.reportCurCount(); + } + + // 核心:分段写 + writer.write(modelList, sheet); + + if (!pageResult.isHasNext()) { + break; + } + + pageIndex++; + } + } finally { + writer.finish(); + } + + UploadDto uploadDto = UploadUtil.upload(xlsxFile, + CollectionUtil.toList("export-task", exportTask.getCreateById()), true); + + // 将导出任务状态置为导出完成 + exportTaskService.setSuccess(taskId, uploadDto.getSecurityUploadRecordId(), + FileUtil.readableFileSize(xlsxFile.length())); + } catch (ClientException e) { + this.handleError(e); + } catch (Exception e) { + log.error(e.getMessage(), e); + this.handleError(e); + } + } + + protected void reportCurCount() { + this.curCount++; + if (this.curCount >= COUNT_BATCH_SIZE) { + ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class); + exportTaskService.addCurCount(taskId, this.curCount); + this.curCount = 0; + } + } + + /** + * 处理异常 + * + * @param e + */ + protected void handleError(Exception e) { + ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class); + // 将导出任务状态置为失败 + exportTaskService.setFail(taskId, + StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage()); + + exportTaskWorker.handleError(e); + } + + protected void checkCurrentUser() { + // 必须一直检测session是否在线,否则可能会导致查出的数据超出了当前用户可访问的数据 + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + if (currentUser == null || SecurityUtil.getSessionByLoginId(currentUser.getLoginId()) == null) { + throw new DefaultClientException("导出用户已退出登录,无法导出"); + } + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java new file mode 100644 index 0000000..901b948 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java @@ -0,0 +1,128 @@ +package com.lframework.starter.mq.core.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.mq.core.enums.ExportTaskStatus; +import com.lframework.starter.mq.core.events.ExportTaskNotifyEvent; +import com.lframework.starter.mq.core.mappers.ExportTaskMapper; +import com.lframework.starter.mq.core.service.ExportTaskService; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Slf4j +@Service +public class ExportTaskServiceImpl extends BaseMpServiceImpl + implements ExportTaskService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(ExportTask task) { + this.save(task); + + ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById())); + return task.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setExporting(String id) { + + ExportTask task = this.getById(id); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class) + .eq(ExportTask::getId, id) + .eq(ExportTask::getStatus, ExportTaskStatus.CREATED) + .set(ExportTask::getStatus, ExportTaskStatus.EXPORTING); + + if (!this.update(updateWrapper)) { + log.error("导出任务 ID {} 设置为 正在导出 失败", id); + throw new DefaultSysException( + "导出任务设置为“" + ExportTaskStatus.EXPORTING.getDesc() + "”失败"); + } + + ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setSuccess(String id, String securityUploadRecordId, String fileSize) { + + ExportTask task = this.getById(id); + String recordId = securityUploadRecordId; + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class) + .eq(ExportTask::getId, id) + .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING) + .set(ExportTask::getRecordId, recordId) + .set(ExportTask::getStatus, ExportTaskStatus.SUCCESS) + .set(ExportTask::getFinishTime, LocalDateTime.now()) + .set(ExportTask::getFileSize, fileSize) + .setSql("cur_count = total_count"); + if (!this.update(updateWrapper)) { + log.error("导出任务 ID {} 设置为 导出成功 失败", id); + throw new DefaultSysException( + "导出任务设置为“" + ExportTaskStatus.SUCCESS.getDesc() + "”失败"); + } + ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setFail(String id, String errorMsg) { + ExportTask task = this.getById(id); + Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class) + .eq(ExportTask::getId, id) + .set(ExportTask::getStatus, ExportTaskStatus.FAIL) + .set(ExportTask::getErrorMsg, errorMsg) + .set(ExportTask::getFinishTime, LocalDateTime.now()); + if (!this.update(updateWrapper)) { + log.error("导出任务 ID {} 设置为 导出失败 失败", id); + throw new DefaultSysException( + "导出任务设置为“" + ExportTaskStatus.FAIL.getDesc() + "”失败"); + } + ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setTotalCount(String id, Long totalCount) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class) + .eq(ExportTask::getId, id) + .eq(ExportTask::getStatus, ExportTaskStatus.EXPORTING) + .set(ExportTask::getTotalCount, totalCount); + + if (!this.update(updateWrapper)) { + log.error("导出任务 ID {} 设置 数据总条数 失败", id); + throw new DefaultSysException( + "导出任务设置数据总条数失败"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addCurCount(String id, int addCount) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class) + .eq(ExportTask::getId, id) + .eq(ExportTask::getStatus, ExportTaskStatus.EXPORTING) + .setSql("cur_count = cur_count + " + addCount); + + if (!this.update(updateWrapper)) { + log.error("导出任务 ID {} 设置 当前导出条数 失败", id); + throw new DefaultSysException( + "导出任务设置当前导出条数失败"); + } + } + + @Override + public ExportTaskSummaryDto getSummaryByUserId(String userId) { + return getBaseMapper().getSummaryByUserId(userId); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java new file mode 100644 index 0000000..0794548 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java @@ -0,0 +1,24 @@ +package com.lframework.starter.mq.core.mappers; + +import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.web.core.mapper.BaseMapper; + +/** + *

+ * ExportTaskMapper 接口 + *

+ * + * @author zmj + * @since 2025-04-10 + */ +public interface ExportTaskMapper extends BaseMapper { + + /** + * 根据用户ID统计导出任务 + * + * @param userId + * @return + */ + ExportTaskSummaryDto getSummaryByUserId(String userId); +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java new file mode 100644 index 0000000..796f778 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java @@ -0,0 +1,83 @@ +package com.lframework.starter.mq.core.producer; + +import com.lframework.starter.mq.core.queue.QueueDefinition; + +import java.io.Serializable; + +/** + * MQ生产者 + * + * @author zmj + * @since 2022/8/25 + */ +public interface MqProducer { + + /** + * 发送延时消息 + * + * @param definition 队列 + * @param data 数据 + * @param millis 毫秒 + */ + void sendDelayMessage(QueueDefinition definition, Serializable data, long millis); + + /** + * 发送即时消息 + * + * @param definition 队列 + * @param data 数据 + */ + void sendMessage(QueueDefinition definition, Serializable data); + + /** + * 发送延时消息 + * + * @param definition 队列 + * @param millis 毫秒 + */ + void sendDelayMessage(QueueDefinition definition, long millis); + + /** + * 发送即时消息 + * + * @param definition 队列 + */ + void sendMessage(QueueDefinition definition); + + /** + * 发送延时消息 + * + * @param definition 队列 + * @param data 数据 + * @param millis 毫秒 + * @param tenantId 租户ID + */ + void sendDelayMessage(QueueDefinition definition, Serializable data, long millis, + Integer tenantId); + + /** + * 发送即时消息 + * + * @param definition 队列 + * @param data 数据 + * @param tenantId 租户ID + */ + void sendMessage(QueueDefinition definition, Serializable data, Integer tenantId); + + /** + * 发送延时消息 + * + * @param definition 队列 + * @param millis 毫秒 + * @param tenantId 租户ID + */ + void sendDelayMessage(QueueDefinition definition, long millis, Integer tenantId); + + /** + * 发送即时消息 + * + * @param definition 队列 + * @param tenantId 租户ID + */ + void sendMessage(QueueDefinition definition, Integer tenantId); +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java new file mode 100644 index 0000000..9f8a1c2 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java @@ -0,0 +1,8 @@ +package com.lframework.starter.mq.core.queue; + +/** + * 队列定义 + */ +public interface QueueDefinition { + +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java new file mode 100644 index 0000000..1a3b4c7 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java @@ -0,0 +1,67 @@ +package com.lframework.starter.mq.core.service; + +import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.web.core.service.BaseMpService; + +/** + * 导出任务 Service + * + * @author zmj + */ +public interface ExportTaskService extends BaseMpService { + + /** + * 新增 + * + * @param task + * @return + */ + String create(ExportTask task); + + /** + * 设置为正在导出 + * + * @param id + */ + void setExporting(String id); + + /** + * 设置为成功 + * + * @param id + */ + void setSuccess(String id, String securityUploadRecordId, String fileSize); + + /** + * 设置为失败 + * + * @param id + * @param errorMsg + */ + void setFail(String id, String errorMsg); + + /** + * 设置数据总条数 + * + * @param id + * @param totalCount + */ + void setTotalCount(String id, Long totalCount); + + /** + * 增加当前导出条数 + * + * @param id + * @param addCount + */ + void addCurCount(String id, int addCount); + + /** + * 根据用户ID统计导出任务 + * + * @param userId + * @return + */ + ExportTaskSummaryDto getSummaryByUserId(String userId); +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java new file mode 100644 index 0000000..d537d7f --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java @@ -0,0 +1,46 @@ +package com.lframework.starter.mq.core.service; + +import com.lframework.starter.mq.core.dto.AddExportTaskDto; +import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto; +import com.lframework.starter.web.core.service.BaseService; +import com.lframework.starter.web.inner.dto.message.SysMailMessageDto; +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto; +import com.lframework.starter.web.inner.dto.notify.SysNotifyDto; + +public interface MqProducerService extends BaseService { + + /** + * 发送消息通知 + * + * @param dto + */ + void createSysNotify(SysNotifyDto dto); + + /** + * 发送邮件消息 + * + * @param dto + */ + void createSysMailMessage(SysMailMessageDto dto); + + /** + * 发送站内信 + * + * @param dto + */ + void createSysSiteMessage(SysSiteMessageDto dto); + + /** + * 新增导出任务 + * + * @param dto + */ + void addExportTask(AddExportTaskDto dto); + + /** + * 执行导出任务 + * + * @param dto + */ + void executeExportTask(ExecuteExportTaskDto dto); +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java new file mode 100644 index 0000000..dd9c124 --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java @@ -0,0 +1,28 @@ +package com.lframework.starter.mq.core.utils; + +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.mq.core.components.export.ExportTaskWorker; +import com.lframework.starter.mq.core.dto.AddExportTaskDto; +import com.lframework.starter.mq.core.service.MqProducerService; +import com.lframework.starter.web.core.components.security.UserTokenResolver; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.JsonUtil; + +import java.time.LocalDateTime; + +public class ExportTaskUtil { + + public static void exportTask(String taskName, + Class> clazz, + Object params) { + MqProducerService mqProducerService = ApplicationUtil.getBean(MqProducerService.class); + UserTokenResolver userTokenResolver = ApplicationUtil.getBean(UserTokenResolver.class); + AddExportTaskDto dto = new AddExportTaskDto(); + dto.setName(taskName + "_" + DateUtil.formatDateTime(LocalDateTime.now(), "yyyyMMddHHmmss")); + dto.setReqClassName(clazz.getName()); + dto.setReqParams(JsonUtil.toJsonString(params)); + dto.setToken(userTokenResolver.getToken()); + + mqProducerService.addExportTask(dto); + } +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java new file mode 100644 index 0000000..309de8c --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java @@ -0,0 +1,15 @@ +package com.lframework.starter.mq.core.vo; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryFailExportTaskVo extends PageVo { + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java new file mode 100644 index 0000000..019bb3f --- /dev/null +++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java @@ -0,0 +1,15 @@ +package com.lframework.starter.mq.core.vo; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySuccessExportTaskVo extends PageVo { + + /** + * 名称 + */ + @Schema($schema = "名称") + private String name; +} diff --git a/mq-starter/mq-core/src/main/resources/META-INF/spring.factories b/mq-starter/mq-core/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..d7c42dd --- /dev/null +++ b/mq-starter/mq-core/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.mq.core.config.MqBeanAutoConfiguration,\ + com.lframework.starter.mq.core.config.MqSwaggerAutoConfiguration \ No newline at end of file diff --git a/mq-starter/mq-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/mq-starter/mq-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..aee53c2 --- /dev/null +++ b/mq-starter/mq-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.lframework.starter.mq.core.config.MqBeanAutoConfiguration +com.lframework.starter.mq.core.config.MqSwaggerAutoConfiguration diff --git a/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml b/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml new file mode 100644 index 0000000..1c3e8d1 --- /dev/null +++ b/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/mq-starter/pom.xml b/mq-starter/pom.xml new file mode 100644 index 0000000..6546cdd --- /dev/null +++ b/mq-starter/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.lframework + framework + 1.0.0 + + + mq-starter + pom + + + mq-core + activemq-starter + rabbitmq-starter + + + + + + com.lframework + mq-core + ${jugg.version} + + + com.lframework + activemq-starter + ${jugg.version} + + + com.lframework + rabbitmq-starter + ${jugg.version} + + + + \ No newline at end of file diff --git a/mq-starter/rabbitmq-starter/README.md b/mq-starter/rabbitmq-starter/README.md new file mode 100644 index 0000000..f73e775 --- /dev/null +++ b/mq-starter/rabbitmq-starter/README.md @@ -0,0 +1,14 @@ +# rabbitmq-starter —— RabbitMQ 消息队列实现 + +## 概述 + +RabbitMQ 消息队列的 Spring Boot Starter 实现。基于 Spring AMQP + RabbitMQ 提供可靠的消息投递能力。 + +## 核心能力 + +- RabbitMQ 连接工厂自动配置 +- 消息生产者(实现 MqProducer 接口) +- 消息队列与交换机声明 +- 消息发送确认(Publisher Confirms / Returns) +- 应用启动/关闭时的队列状态管理 +- MQ 运行状态监听 diff --git a/mq-starter/rabbitmq-starter/pom.xml b/mq-starter/rabbitmq-starter/pom.xml new file mode 100644 index 0000000..fdca762 --- /dev/null +++ b/mq-starter/rabbitmq-starter/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + mq-starter + com.lframework + 1.0.0 + + + rabbitmq-starter + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + com.lframework + mq-core + + + + org.springframework.boot + spring-boot-starter-amqp + + + + \ No newline at end of file diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java new file mode 100644 index 0000000..a74c842 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java @@ -0,0 +1,98 @@ +package com.lframework.starter.mq.rabbitmq.config; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.mq.rabbitmq.impl.RabbitMqProducerServiceImpl; +import com.lframework.starter.mq.rabbitmq.listeners.app.ExportTaskNotifyListener; +import com.lframework.starter.mq.rabbitmq.listeners.mq.ExportTaskListener; +import com.lframework.starter.mq.rabbitmq.listeners.mq.SysMailMessageListener; +import com.lframework.starter.mq.rabbitmq.listeners.mq.SysNotifyListener; +import com.lframework.starter.mq.rabbitmq.listeners.mq.SysSiteMessageListener; +import com.lframework.starter.mq.rabbitmq.producer.RabbitMqProducer; +import org.aopalliance.aop.Advice; +import org.springframework.amqp.rabbit.annotation.EnableRabbit; +import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.retry.MessageRecoverer; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.amqp.DirectRabbitListenerContainerFactoryConfigurer; +import org.springframework.boot.autoconfigure.amqp.RabbitProperties; +import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer; +import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@EnableRabbit +@Configuration +@Import({ + RabbitMqProducerServiceImpl.class, + SysMailMessageListener.class, + SysNotifyListener.class, + SysSiteMessageListener.class, + ExportTaskNotifyListener.class, + ExportTaskListener.class, +}) +public class RabbitMqAutoConfiguration { + + private final ObjectProvider messageConverter; + + private final ObjectProvider messageRecoverer; + + private final ObjectProvider retryTemplateCustomizers; + + private final RabbitProperties properties; + + RabbitMqAutoConfiguration(ObjectProvider messageConverter, + ObjectProvider messageRecoverer, + ObjectProvider retryTemplateCustomizers, + RabbitProperties properties) { + this.messageConverter = messageConverter; + this.messageRecoverer = messageRecoverer; + this.retryTemplateCustomizers = retryTemplateCustomizers; + this.properties = properties; + } + + @Bean + public RabbitMqProducer activeMQProducer(RabbitTemplate rabbitTemplate) { + return new RabbitMqProducer(rabbitTemplate); + } + + @Bean(name = "rabbitListenerContainerFactory") + @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "simple", + matchIfMissing = true) + SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory( + SimpleRabbitListenerContainerFactoryConfigurer configurer, + ConnectionFactory connectionFactory) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + configurer.configure(factory, connectionFactory); + factory.setAdviceChain(combineAdvice(factory.getAdviceChain())); + return factory; + } + + @Bean(name = "rabbitListenerContainerFactory") + @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "direct") + DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory( + DirectRabbitListenerContainerFactoryConfigurer configurer, + ConnectionFactory connectionFactory) { + DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory(); + configurer.configure(factory, connectionFactory); + factory.setAdviceChain(combineAdvice(factory.getAdviceChain())); + return factory; + } + + private Advice[] combineAdvice(Advice[] advices) { + Advice[] result = new Advice[(ArrayUtil.isEmpty(advices) ? 0 : advices.length) + 1]; + if (!ArrayUtil.isEmpty(advices)) { + for (int i = 0; i < advices.length; i++) { + result[i] = advices[i]; + } + } + + result[result.length - 1] = new TenantMethodInterceptor(); + return result; + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java new file mode 100644 index 0000000..2c46e08 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java @@ -0,0 +1,63 @@ +package com.lframework.starter.mq.rabbitmq.config; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import lombok.extern.slf4j.Slf4j; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.amqp.core.Message; + +@Slf4j +public class TenantMethodInterceptor implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + boolean isTenantEnabled = TenantUtil.enableTenant(); + Integer tenantId = null; + + if (isTenantEnabled) { + log.debug("RabbitMq开始处理TenantId"); + tenantId = convertTenantId(invocation); + log.debug("TenantId = {}", tenantId); + if (tenantId != null) { + TenantContextHolder.setTenantId(tenantId); + } + } + + try { + return invocation.proceed(); + } catch (Throwable e) { + log.error(e.getMessage(), e); + throw e; + } finally { + TenantContextHolder.clearTenantId(); + } + } + + private Integer convertTenantId(MethodInvocation invocation) { + Object[] args = invocation.getArguments(); + + if (ArrayUtil.isEmpty(args)) { + return null; + } + + for (Object arg : args) { + if (arg instanceof Message) { + Message message = (Message) arg; + Object headerValue = message.getMessageProperties().getHeader("tenantId"); + if (headerValue instanceof Integer) { + return (Integer) headerValue; + } else if (headerValue != null) { + try { + return Integer.parseInt(headerValue.toString()); + } catch (NumberFormatException e) { + return null; + } + } + } + } + + return null; + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java new file mode 100644 index 0000000..05f24c9 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java @@ -0,0 +1,40 @@ +package com.lframework.starter.mq.rabbitmq.constants; + +import com.lframework.starter.mq.core.queue.QueueDefinition; +import com.lframework.starter.mq.rabbitmq.queue.RabbitMQQueueDefinition; + +public class RabbitMqConstants { + + /** + * 消息通知 + */ + public static final QueueDefinition SYS_NOTIFY = new RabbitMQQueueDefinition( + RabbitMqStringPool.SYS_NOTIFY_EXCHANGE, RabbitMqStringPool.SYS_NOTIFY_ROUTING_KEY); + + /** + * 邮件消息 + */ + public static final QueueDefinition SYS_MAIL_MESSAGE = new RabbitMQQueueDefinition( + RabbitMqStringPool.SYS_MAIL_MESSAGE_EXCHANGE, + RabbitMqStringPool.SYS_MAIL_MESSAGE_ROUTING_KEY); + + /** + * 站内信 + */ + public static final QueueDefinition SYS_SITE_MESSAGE = new RabbitMQQueueDefinition( + RabbitMqStringPool.SYS_SITE_MESSAGE_EXCHANGE, + RabbitMqStringPool.SYS_SITE_MESSAGE_ROUTING_KEY); + + /** + * 新增导出任务 + */ + public static final QueueDefinition ADD_EXPORT_TASK = new RabbitMQQueueDefinition( + RabbitMqStringPool.ADD_EXPORT_TASK_EXCHANGE, RabbitMqStringPool.ADD_EXPORT_TASK_ROUTING_KEY); + + /** + * 执行导出任务 + */ + public static final QueueDefinition EXECUTE_EXPORT_TASK = new RabbitMQQueueDefinition( + RabbitMqStringPool.EXECUTE_EXPORT_TASK_EXCHANGE, + RabbitMqStringPool.EXECUTE_EXPORT_TASK_ROUTING_KEY); +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java new file mode 100644 index 0000000..4d609e8 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java @@ -0,0 +1,39 @@ +package com.lframework.starter.mq.rabbitmq.constants; + +public interface RabbitMqStringPool { + + // 增加库存 + String ADD_STOCK_EXCHANGE = "add_stock.fanout"; + + // 扣减库存 + String SUB_STOCK_EXCHANGE = "sub_stock.fanout"; + + // 审核通过订单 + String APPROVE_PASS_ORDER_EXCHANGE = "approve_pass_order.fanout"; + + // 消息通知 + String SYS_NOTIFY_EXCHANGE = "sys_notify.direct"; + String SYS_NOTIFY_ROUTING_KEY = "sys_notify_routing_key"; + String SYS_NOTIFY_QUEUE = "sys_notify"; + + // 邮件消息 + String SYS_MAIL_MESSAGE_EXCHANGE = "sys_mail_message.direct"; + String SYS_MAIL_MESSAGE_ROUTING_KEY = "sys_mail_message_routing_key"; + String SYS_MAIL_MESSAGE_QUEUE = "sys_mail_message"; + + // 站内信 + String SYS_SITE_MESSAGE_EXCHANGE = "sys_site_message.direct"; + String SYS_SITE_MESSAGE_ROUTING_KEY = "sys_site_message_routing_key"; + String SYS_SITE_MESSAGE_QUEUE = "sys_site_message"; + + // 新增导出任务 + String ADD_EXPORT_TASK_EXCHANGE = "add_export_task.direct"; + String ADD_EXPORT_TASK_ROUTING_KEY = "add_export_task_routing_key"; + String ADD_EXPORT_TASK_QUEUE = "add_export_task"; + + // 执行导出任务 + String EXECUTE_EXPORT_TASK_EXCHANGE = "execute_export_task.direct"; + String EXECUTE_EXPORT_TASK_ROUTING_KEY = "execute_export_task_routing_key"; + String EXECUTE_EXPORT_TASK_QUEUE = "execute_export_task"; + +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java new file mode 100644 index 0000000..5702b23 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java @@ -0,0 +1,42 @@ +package com.lframework.starter.mq.rabbitmq.impl; + +import com.lframework.starter.mq.core.dto.AddExportTaskDto; +import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto; +import com.lframework.starter.mq.core.producer.MqProducer; +import com.lframework.starter.mq.core.service.MqProducerService; +import com.lframework.starter.mq.rabbitmq.constants.RabbitMqConstants; +import com.lframework.starter.web.inner.dto.message.SysMailMessageDto; +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto; +import com.lframework.starter.web.inner.dto.notify.SysNotifyDto; +import org.springframework.beans.factory.annotation.Autowired; + +public class RabbitMqProducerServiceImpl implements MqProducerService { + + @Autowired + private MqProducer mqProducer; + + @Override + public void createSysNotify(SysNotifyDto dto) { + mqProducer.sendMessage(RabbitMqConstants.SYS_NOTIFY, dto); + } + + @Override + public void createSysMailMessage(SysMailMessageDto dto) { + mqProducer.sendMessage(RabbitMqConstants.SYS_MAIL_MESSAGE, dto); + } + + @Override + public void createSysSiteMessage(SysSiteMessageDto dto) { + mqProducer.sendMessage(RabbitMqConstants.SYS_SITE_MESSAGE, dto); + } + + @Override + public void addExportTask(AddExportTaskDto dto) { + mqProducer.sendMessage(RabbitMqConstants.ADD_EXPORT_TASK, dto); + } + + @Override + public void executeExportTask(ExecuteExportTaskDto dto) { + mqProducer.sendMessage(RabbitMqConstants.EXECUTE_EXPORT_TASK, dto); + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java new file mode 100644 index 0000000..0cec9e9 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java @@ -0,0 +1,41 @@ +package com.lframework.starter.mq.rabbitmq.listeners.app; + +import com.lframework.starter.mq.core.events.ExportTaskNotifyEvent; +import com.lframework.starter.mq.core.service.ExportTaskService; +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.events.UserConnectEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +public class ExportTaskNotifyListener implements ApplicationListener { + + @Autowired + private WsDataPusher wsDataPusher; + + @Autowired + private ExportTaskService exportTaskService; + + @TransactionalEventListener + public void execute(ExportTaskNotifyEvent event) { + this.notify(event.getCreateById()); + } + + @Override + public void onApplicationEvent(UserConnectEvent event) { + this.notify(event.getUser().getId()); + } + + private void notify(String userId) { + // 发送广播 + WsPushData pushData = new WsPushData(); + pushData.setBizType("exportTask"); + pushData.setDataObj(exportTaskService.getSummaryByUserId(userId)); + pushData.setIncludeUserId(userId); + + wsDataPusher.push(pushData); + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java new file mode 100644 index 0000000..18b3522 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java @@ -0,0 +1,125 @@ +package com.lframework.starter.mq.rabbitmq.listeners.mq; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.core.dto.AddExportTaskDto; +import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto; +import com.lframework.starter.mq.core.entity.ExportTask; +import com.lframework.starter.mq.core.enums.ExportTaskStatus; +import com.lframework.starter.mq.core.handlers.ExportTaskHandler; +import com.lframework.starter.mq.core.service.ExportTaskService; +import com.lframework.starter.mq.core.service.MqProducerService; +import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.stereotype.Component; + +@Slf4j +@Component("exportTaskListener") +public class ExportTaskListener { + + @Autowired + private ExportTaskService exportTaskService; + + @Autowired + private MqProducerService mqProducerService; + + @Autowired + private SysConfService sysConfService; + + @RabbitListener(bindings = { + @QueueBinding(value = @Queue(value = RabbitMqStringPool.ADD_EXPORT_TASK_QUEUE), key = RabbitMqStringPool.ADD_EXPORT_TASK_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.ADD_EXPORT_TASK_EXCHANGE))}, concurrency = "2") + public void addExportTask(Message message) { + + AddExportTaskDto dto = message.getPayload(); + + log.info("接收到新增导出任务MQ message = {}", dto); + + AbstractUserDetails currentUser = SecurityUtil.getUserByToken(dto.getToken()); + if (currentUser == null) { + log.info("导出用户已退出登录,无法导出"); + return; + } + + try { + SecurityUtil.setCurrentUser(currentUser); + + // 新增导出任务 + ExportTask task = new ExportTask(); + task.setId(IdUtil.getId()); + task.setName(dto.getName()); + task.setStatus(ExportTaskStatus.CREATED); + task.setReqClassName(dto.getReqClassName()); + task.setReqParams(dto.getReqParams()); + + task.setReqParamsSign(SecureUtil.md5(dto.getReqClassName() + ":" + dto.getReqParams())); + + exportTaskService.create(task); + + ExecuteExportTaskDto taskDto = new ExecuteExportTaskDto(); + taskDto.setTaskId(task.getId()); + taskDto.setToken(dto.getToken()); + + mqProducerService.executeExportTask(taskDto); + + } finally { + SecurityUtil.removeCurrentUser(); + } + } + + @RabbitListener(bindings = { + @QueueBinding(value = @Queue(value = RabbitMqStringPool.EXECUTE_EXPORT_TASK_QUEUE), key = RabbitMqStringPool.EXECUTE_EXPORT_TASK_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.EXECUTE_EXPORT_TASK_EXCHANGE))}) + public void executeExportTask(Message message) { + + ExecuteExportTaskDto dto = message.getPayload(); + + log.info("接收到执行导出任务MQ message = {}", dto); + + ExportTask task = exportTaskService.getById(dto.getTaskId()); + AbstractUserDetails currentUser = SecurityUtil.getUserByToken(dto.getToken()); + + try { + if (currentUser == null) { + throw new DefaultClientException("导出用户已退出登录,无法导出"); + } + + SecurityUtil.setCurrentUser(currentUser); + + Wrapper checkWrapper = Wrappers.lambdaQuery(ExportTask.class) + .eq(ExportTask::getReqParamsSign, task.getReqParamsSign()) + .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING) + .ne(ExportTask::getId, task.getId()); + if (exportTaskService.count(checkWrapper) > 0) { + throw new DefaultClientException("导出任务重复,请勿重复导出。"); + } + + ExportTaskHandler exportTaskHandler = new ExportTaskHandler(task.getId(), + ReflectUtil.newInstance(task.getReqClassName()), + sysConfService.getLong("export.timeout", 600L)); + exportTaskHandler.execute(task.getReqParams()); + } catch (ClientException e) { + exportTaskService.setFail(task.getId(), + StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage(), e); + exportTaskService.setFail(task.getId(), + StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage()); + } finally { + SecurityUtil.removeCurrentUser(); + } + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java new file mode 100644 index 0000000..2d9dd4c --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java @@ -0,0 +1,131 @@ +package com.lframework.starter.mq.rabbitmq.listeners.mq; + +import cn.hutool.extra.mail.MailException; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.dto.message.SysMailMessageDto; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.enums.system.SysMailMessageSendStatus; +import com.lframework.starter.web.inner.service.MailService; +import com.lframework.starter.web.inner.service.system.SysMailMessageService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.stereotype.Component; + +import javax.mail.Address; +import javax.mail.SendFailedException; +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class SysMailMessageListener { + + @Autowired + private SysMailMessageService sysMailMessageService; + + @Autowired + private SysUserService sysUserService; + + @RabbitListener(bindings = { + @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_MAIL_MESSAGE_QUEUE), key = RabbitMqStringPool.SYS_MAIL_MESSAGE_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_MAIL_MESSAGE_EXCHANGE))}) + public void execute(Message message) { + + SysMailMessageDto dto = message.getPayload(); + log.info("接收到发送邮件消息 {}", dto); + + if (CollectionUtil.isNotEmpty(dto.getMailList())) { + dto.setMailList( + dto.getMailList().stream().filter(t -> RegUtil.isMatch(PatternPool.EMAIL, t)).collect( + Collectors.toList())); + } + + if (CollectionUtil.isEmpty(dto.getMailList())) { + log.info("邮箱地址为空,不发送"); + return; + } + + String title = dto.getTitle(); + String content = dto.getContent(); + if (StringUtil.isBlank(title) || StringUtil.isBlank(content) || StringUtil.isBlank( + dto.getBizKey())) { + log.info("标题、内容、业务键不能为空,不发送"); + return; + } + + SysUser createBy = StringUtil.isBlank(dto.getCreateUserId()) ? null + : sysUserService.findById(dto.getCreateUserId()); + + List recordList = dto.getMailList().stream().distinct().map(t -> { + SysMailMessage record = new SysMailMessage(); + record.setId(IdUtil.getId()); + record.setTitle(title); + record.setContent(content); + record.setMail(t); + record.setBizKey(dto.getBizKey()); + record.setSendStatus(SysMailMessageSendStatus.UN_SEND); + if (createBy != null) { + record.setCreateById(createBy.getId()); + record.setCreateBy(createBy.getName()); + record.setUpdateBy(createBy.getName()); + record.setUpdateById(createBy.getId()); + } + + return record; + }).collect(Collectors.toList()); + + sysMailMessageService.saveBatch(recordList); + + try { + MailService mailService = ApplicationUtil.getBean(MailService.class); + mailService.send( + recordList.stream().map(SysMailMessage::getMail).collect(Collectors.toList()), + title, content); + + // 全部成功 + recordList.forEach(t -> t.setSendStatus(SysMailMessageSendStatus.SENDED)); + + } catch (MailException e) { + Throwable throwable = e.getCause(); + if (throwable instanceof SendFailedException) { + //部分失败 + Address[] invalidAddresses = ((SendFailedException) throwable).getInvalidAddresses(); + for (Address invalidAddress : invalidAddresses) { + String mail = invalidAddress.toString(); + recordList.stream().filter(t -> mail.equals(t.getMail())) + .findFirst().ifPresent(record -> record.setSendStatus(SysMailMessageSendStatus.FAIL)); + recordList.stream().filter(t -> t.getSendStatus() == SysMailMessageSendStatus.UN_SEND + ).forEach(record -> record.setSendStatus(SysMailMessageSendStatus.SENDED)); + } + } else { + // 全部失败 + recordList.forEach(t -> t.setSendStatus(SysMailMessageSendStatus.FAIL)); + log.error(e.getMessage(), e); + } + } + + sysMailMessageService.updateBatchById(recordList.stream().map(t -> { + SysMailMessage record = new SysMailMessage(); + record.setId(t.getId()); + record.setSendStatus(t.getSendStatus()); + record.setCreateById(t.getCreateById()); + record.setCreateBy(t.getCreateBy()); + record.setUpdateById(t.getUpdateById()); + record.setUpdateBy(t.getUpdateBy()); + + return record; + }).collect(Collectors.toList())); + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java new file mode 100644 index 0000000..463983e --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java @@ -0,0 +1,175 @@ +package com.lframework.starter.mq.rabbitmq.listeners.mq; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.mq.core.service.MqProducerService; +import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool; +import com.lframework.starter.web.core.components.notify.SysNotifyRuleEmail; +import com.lframework.starter.web.core.components.notify.SysNotifyRuleSys; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.dto.message.SysMailMessageDto; +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto; +import com.lframework.starter.web.inner.dto.notify.SysNotifyDto; +import com.lframework.starter.web.inner.dto.notify.SysNotifyParamsDto; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.enums.system.SysNotifyMessageType; +import com.lframework.starter.web.inner.service.system.SysNotifyGroupService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class SysNotifyListener { + + @Autowired + private SysNotifyGroupService sysNotifyGroupService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private MqProducerService mqProducerService; + + private static final int BATCH_SIZE = 100; + + @RabbitListener(bindings = { + @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_NOTIFY_QUEUE), key = RabbitMqStringPool.SYS_NOTIFY_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_NOTIFY_EXCHANGE))}) + public void execute(Message message) { + SysNotifyDto dto = message.getPayload(); + log.debug("接收到消息:{}", dto); + + SysNotifyGroup notifyGroup = sysNotifyGroupService.findById(dto.getNotifyGroupId()); + if (notifyGroup == null) { + log.info("消息通知组不存在,通知组ID:{}", dto.getNotifyGroupId()); + return; + } + if (!notifyGroup.getAvailable()) { + log.info("消息通知组不可用,通知组ID:{}", dto.getNotifyGroupId()); + return; + } + + Set userIds = sysNotifyGroupService.getReceiveUserIds(notifyGroup.getId()); + if (CollectionUtil.isEmpty(userIds)) { + log.info("消息通知组不存在接收人,通知组ID:{}", dto.getNotifyGroupId()); + return; + } + + List messageTypeCodes = Arrays.stream( + notifyGroup.getMessageType().split(StringPool.STR_SPLIT)).map(Integer::valueOf).collect( + Collectors.toList()); + for (Integer messageTypeCode : messageTypeCodes) { + SysNotifyMessageType messageType = EnumUtil.getByCode(SysNotifyMessageType.class, + messageTypeCode); + switch (messageType) { + case EMAIL: { + Map ruleMap = ApplicationUtil.getBeansOfType( + SysNotifyRuleEmail.class); + + for (SysNotifyRuleEmail rule : ruleMap.values()) { + if (!rule.match(dto.getBizType())) { + continue; + } + + log.info("匹配到rule,开始发送邮件"); + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class) + .select(SysUser::getEmail) + .in(SysUser::getId, userIds) + .eq(SysUser::getAvailable, true) + .isNotNull(SysUser::getEmail) + .ne(SysUser::getEmail, StringPool.EMPTY_STR); + List userList = sysUserService.list(queryWrapper); + if (CollectionUtil.isNotEmpty(userList)) { + SysNotifyParamsDto paramsDto = new SysNotifyParamsDto(); + paramsDto.setVariables(dto.getVariables()); + + String title = rule.getTitle(paramsDto); + String content = rule.getContent(paramsDto); + + List allMailList = userList.stream().map(SysUser::getEmail).distinct() + .collect( + Collectors.toList()); + List> splitMailList = CollectionUtil.split(allMailList, BATCH_SIZE); + for (List mailList : splitMailList) { + SysMailMessageDto messageDto = new SysMailMessageDto(); + messageDto.setMailList(mailList); + messageDto.setTitle(title); + messageDto.setContent(content); + messageDto.setBizKey(IdUtil.getId()); + messageDto.setCreateUserId(dto.getCreateUserId()); + + mqProducerService.createSysMailMessage(messageDto); + } + } + break; + } + break; + } + + case SYS: { + Map ruleMap = ApplicationUtil.getBeansOfType( + SysNotifyRuleSys.class); + + for (SysNotifyRuleSys rule : ruleMap.values()) { + if (!rule.match(dto.getBizType())) { + continue; + } + + log.info("匹配到rule,开始发送站内信"); + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class) + .select(SysUser::getId) + .in(SysUser::getId, userIds) + .eq(SysUser::getAvailable, true); + List userList = sysUserService.list(queryWrapper); + if (CollectionUtil.isNotEmpty(userList)) { + SysNotifyParamsDto paramsDto = new SysNotifyParamsDto(); + paramsDto.setVariables(dto.getVariables()); + + String title = rule.getTitle(paramsDto); + String content = rule.getContent(paramsDto); + + List allUserIdList = userList.stream().map(SysUser::getId).distinct() + .collect( + Collectors.toList()); + List> splitUserIdList = CollectionUtil.split(allUserIdList, BATCH_SIZE); + for (List userIdList : splitUserIdList) { + SysSiteMessageDto messageDto = new SysSiteMessageDto(); + messageDto.setUserIdList(userIdList); + messageDto.setTitle(title); + messageDto.setContent(content); + messageDto.setBizKey(IdUtil.getId()); + messageDto.setCreateUserId(dto.getCreateUserId()); + + mqProducerService.createSysSiteMessage(messageDto); + } + } + break; + } + break; + } + + default: { + throw new DefaultSysException("未知的MessageType: " + messageTypeCode); + } + } + } + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java new file mode 100644 index 0000000..997aa9e --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java @@ -0,0 +1,92 @@ +package com.lframework.starter.mq.rabbitmq.listeners.mq; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.service.system.SysSiteMessageService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.dto.WsPushData; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class SysSiteMessageListener { + + @Autowired + private SysSiteMessageService sysSiteMessageService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private WsDataPusher wsDataPusher; + + @RabbitListener(bindings = { + @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_SITE_MESSAGE_QUEUE), key = RabbitMqStringPool.SYS_SITE_MESSAGE_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_SITE_MESSAGE_EXCHANGE))}) + public void execute(Message message) { + + SysSiteMessageDto dto = message.getPayload(); + log.info("接收到发送站内信消息 {}", dto); + + if (CollectionUtil.isEmpty(dto.getUserIdList())) { + log.info("接收人为空,不发送"); + return; + } + + String title = dto.getTitle(); + String content = dto.getContent(); + if (StringUtil.isBlank(title) || StringUtil.isBlank(content) || StringUtil.isBlank( + dto.getBizKey())) { + log.info("标题、内容、业务键不能为空,不发送"); + return; + } + + SysUser createBy = StringUtil.isBlank(dto.getCreateUserId()) ? null + : sysUserService.findById(dto.getCreateUserId()); + + List recordList = dto.getUserIdList().stream().distinct().map(t -> { + SysSiteMessage record = new SysSiteMessage(); + record.setId(IdUtil.getId()); + record.setTitle(title); + record.setContent(content); + record.setReceiverId(t); + record.setBizKey(dto.getBizKey()); + if (createBy != null) { + record.setCreateById(createBy.getId()); + record.setCreateBy(createBy.getName()); + record.setUpdateBy(createBy.getName()); + record.setUpdateById(createBy.getId()); + } + + return record; + }).collect(Collectors.toList()); + + sysSiteMessageService.saveBatch(recordList); + + for (SysSiteMessage sysSiteMessage : recordList) { + try { + WsPushData pushData = new WsPushData(); + pushData.setBizType("siteMessage"); + pushData.setIncludeUserId(sysSiteMessage.getReceiverId()); + wsDataPusher.push(pushData); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java new file mode 100644 index 0000000..1b393bb --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java @@ -0,0 +1,139 @@ +package com.lframework.starter.mq.rabbitmq.producer; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.mq.core.producer.MqProducer; +import com.lframework.starter.mq.core.queue.QueueDefinition; +import com.lframework.starter.mq.rabbitmq.queue.RabbitMQQueueDefinition; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import java.io.Serializable; + +/** + * RabbitMQ生产者 + * + * @author zmj + * @since 2022/8/25 + */ +public class RabbitMqProducer implements MqProducer { + + private final RabbitTemplate rabbitTemplate; + + private final Object EMPTY_MSG = new Object(); + + public RabbitMqProducer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @Override + public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis) { + + sendDelayMessage(definition, data, millis, TenantContextHolder.getTenantId()); + } + + @Override + public void sendMessage(QueueDefinition definition, Serializable data) { + + sendMessage(definition, data, TenantContextHolder.getTenantId()); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, long millis) { + sendDelayMessage(definition, millis, TenantContextHolder.getTenantId()); + } + + @Override + public void sendMessage(QueueDefinition definition) { + sendMessage(definition, TenantContextHolder.getTenantId()); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis, + Integer tenantId) { + Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0); + rabbitTemplate.convertAndSend( + convertExchange(definition), + convertRoutingKey(definition), + data, + m -> { + m.getMessageProperties().setDelay((int) millis); + if (TenantUtil.enableTenant() && tenantId != null) { + m.getMessageProperties().setHeader("tenantId", tenantId); + } + + return m; + } + ); + } + + @Override + public void sendMessage(QueueDefinition definition, Serializable data, Integer tenantId) { + rabbitTemplate.convertAndSend(convertExchange(definition), convertRoutingKey(definition), data, + m -> { + if (TenantUtil.enableTenant() && tenantId != null) { + m.getMessageProperties().setHeader("tenantId", tenantId); + } + + return m; + }); + } + + @Override + public void sendDelayMessage(QueueDefinition definition, long millis, Integer tenantId) { + Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0); + rabbitTemplate.convertAndSend( + convertExchange(definition), + convertRoutingKey(definition), + EMPTY_MSG, + m -> { + m.getMessageProperties().setDelay((int) millis); + + if (TenantUtil.enableTenant() && tenantId != null) { + m.getMessageProperties().setHeader("tenantId", tenantId); + } + + return m; + } + ); + } + + @Override + public void sendMessage(QueueDefinition definition, Integer tenantId) { + rabbitTemplate.convertAndSend(convertExchange(definition), convertRoutingKey(definition), + EMPTY_MSG, m -> { + if (TenantUtil.enableTenant() && tenantId != null) { + m.getMessageProperties().setHeader("tenantId", tenantId); + } + + return m; + }); + } + + private String convertExchange(QueueDefinition definition) { + if (definition == null) { + throw new DefaultSysException("definition不能为空!"); + } + + if (definition instanceof RabbitMQQueueDefinition) { + return ((RabbitMQQueueDefinition) definition).getExchange(); + } else { + throw new DefaultSysException( + "没有找到" + definition.getClass().getName() + "对应的QueueDefinition"); + } + } + + private String convertRoutingKey(QueueDefinition definition) { + if (definition == null) { + throw new DefaultSysException("definition不能为空!"); + } + + if (definition instanceof RabbitMQQueueDefinition) { + return ((RabbitMQQueueDefinition) definition).getRoutingKey(); + } else { + throw new DefaultSysException( + "没有找到" + definition.getClass().getName() + "对应的QueueDefinition"); + } + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java new file mode 100644 index 0000000..707109a --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java @@ -0,0 +1,27 @@ +package com.lframework.starter.mq.rabbitmq.queue; + +import com.lframework.starter.mq.core.queue.QueueDefinition; +import lombok.Getter; + +@Getter +public class RabbitMQQueueDefinition implements QueueDefinition { + + /** + * 交换机名 + */ + private final String exchange; + + /** + * 路由键 + */ + private String routingKey; + + public RabbitMQQueueDefinition(String exchange) { + this.exchange = exchange; + } + + public RabbitMQQueueDefinition(String exchange, String routingKey) { + this.exchange = exchange; + this.routingKey = routingKey; + } +} diff --git a/mq-starter/rabbitmq-starter/src/main/java/lombok.config b/mq-starter/rabbitmq-starter/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..258ac18 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.mq.rabbitmq.config.RabbitMqAutoConfiguration \ No newline at end of file diff --git a/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..c672750 --- /dev/null +++ b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.lframework.starter.mq.rabbitmq.config.RabbitMqAutoConfiguration diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..30411f1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,427 @@ + + + 4.0.0 + + com.lframework + framework + pom + framework + + common + web-starter + mq-starter + bpm-starter + + 1.0.0 + + + 常用的开发框架整合并配置 + + + + 17 + ${java.version} + ${java.version} + 1.18.32 + UTF-8 + UTF-8 + 3.11.0 + 3.2.12 + 1.0.0 + 1.7.21 + 1.1.7 + 5.7.17 + 1.2.16 + 1.3.1 + 3.6.1 + 2.3.2 + 0.9.1 + 3.3.4 + 4.5.10 + 1.6.1 + 1.13 + 3.0.9 + 1.6.2 + 4.5.0 + 1.44.0 + 2023.0.1.3 + 2.3.2 + 2.2.0 + 2023.0.5 + 2.1.1 + 2.1.1 + 2.1.1 + 3.16.3 + 3.19.7 + 5.6.133 + 1.7.4 + 0.2.5 + + + + + + org.apache.logging.log4j + log4j-bom + 2.22.1 + pom + import + + + + org.springframework.boot + spring-boot-dependencies + ${spring.version} + pom + import + + + + spring-cloud-dependencies + org.springframework.cloud + import + pom + ${spring-cloud.version} + + + + com.lframework + common + ${jugg.version} + + + + com.lframework + web-starter + ${jugg.version} + + + + com.lframework + cloud-starter + ${jugg.version} + + + + com.lframework + mq-starter + ${jugg.version} + + + + com.lframework + bpm-starter + ${jugg.version} + + + + + org.projectlombok + lombok + ${lombok.version} + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + cn.hutool + hutool-bom + ${hutool.version} + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid-spring-boot-starter.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper-spring-boot-starter.version} + + + org.mybatis + mybatis + + + org.mybatis + mybatis-spring + + + + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.7 + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${dynamic-datasource-spring-boot-starter.version} + + + + + com.github.penggle + kaptcha + ${kaptcha.version} + + + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + + + com.alibaba + easyexcel + ${easyexcel.version} + + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + + dom4j + dom4j + ${dom4j.version} + + + + + commons-codec + commons-codec + ${commons-codec.version} + + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + + com.sun.mail + javax.mail + ${javax.mail.version} + + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j-openapi3-jakarta-spring-boot-starter.version} + + + + + cn.dev33 + sa-token-spring-boot3-starter + ${sa-token.version} + + + + cn.dev33 + sa-token-redis-jackson + ${sa-token.version} + + + + cn.dev33 + sa-token-alone-redis + ${sa-token.version} + + + + spring-cloud-starter-alibaba-nacos-discovery + + + nacos-client + com.alibaba.nacos + + + ${spring-cloud-alibaba.version} + com.alibaba.cloud + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + ${spring-cloud-alibaba.version} + + + nacos-client + com.alibaba.nacos + + + + + + nacos-client + com.alibaba.nacos + ${spring-cloud-alibaba-nacos.version} + + + + spring-cloud-alibaba-seata + + + seata-spring-boot-starter + io.seata + + + com.alibaba.cloud + ${spring-cloud-alibaba.version} + + + + seata-spring-boot-starter + io.seata + ${spring-cloud-alibaba-seata.version} + + + + org.ssssssss + magic-api-spring-boot-starter + ${magic-api-spring-boot-starter.version} + + + org.ssssssss + magic-api-plugin-cluster + ${magic-api-plugin-cluster.version} + + + org.ssssssss + magic-api-servlet-jakarta + ${magic-api-servlet-jakarta.version} + + + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun-sdk-oss.version} + + + + + com.huaweicloud + esdk-obs-java + ${esdk-obs-java.version} + + + + + com.qcloud + cos_api + ${cos_api.version} + + + + + org.dromara.warm + warm-flow-mybatis-plus-sb-starter + ${warm-flow.version} + + + com.baomidou + mybatis-plus-extension + + + + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + ${warm-flow.version} + + + + org.dromara.warm + warm-flow-plugin-ui-core + ${warm-flow.version} + + + + org.jcodec + jcodec + ${jcodec.version} + + + + org.jcodec + jcodec-javase + ${jcodec.version} + + + + com.baomidou + mybatis-plus + 3.5.7 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + UTF-8 + true + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/web-starter/README.md b/web-starter/README.md new file mode 100644 index 0000000..2e2290f --- /dev/null +++ b/web-starter/README.md @@ -0,0 +1,59 @@ +# web-starter —— Web 框架整合启动器 + +## 概述 + +web-starter 是苍穹 ERP 的核心 web 框架整合模块,封装了 Spring Boot Web 开发所需的所有基础设施能力,以自动配置方式提供开箱即用的体验。 + +## 核心能力 + +### ORM 与数据库 +- **MyBatis-Plus 3.5.7** —— ORM 框架,支持 Lambda 查询、分页、自动填充 +- **Druid** —— 数据库连接池 +- **Dynamic Datasource** —— 多数据源支持 +- **PageHelper** —— 分页插件 + +### 认证与授权 +- **Sa-Token 1.44** —— 认证鉴权框架(Spring Boot 3 集成 + Redis 序列化) +- **@SaCheckPermission / @SaCheckRole** —— 权限注解 + +### 缓存与会话 +- **Redis**(Spring Data Redis + Lettuce 连接池) +- **Spring Session + Redis** —— Session 集中存储 + +### 任务调度 +- **Quartz** —— 分布式任务调度(JDBC 存储) + +### 文件处理 +- **EasyExcel** —— Excel 导入导出 +- **OSS 客户端** —— 阿里云 OSS / 华为云 OBS / 腾讯云 COS + +### API 文档 +- **Knife4j 4.5.0** —— OpenAPI 3 接口文档 + +### 动态 API +- **Magic-API 2.1.1** —— 在线编写接口脚本(Groovy),支持数据库存储、集群模式 + +### 其他 +- **WebSocket** —— 实时消息推送(基于 Redis Pub/Sub 广播) +- **验证码** —— Kaptcha 图形验证码 +- **操作日志** —— 业务操作日志记录 +- **数据脱敏/加密** —— 敏感字段处理 +- **租户隔离** —— 多租户数据隔离 +- **ID 生成器** —— 雪花算法(支持 workerId / dataCenterId 配置) + +## 内置管理功能 + +web-starter 还包含了 ERP 系统管理模块的内置实现: + +- 用户管理、角色管理、权限(菜单)管理 +- 部门管理 +- 数据字典 +- 系统参数配置 +- 操作日志查询 +- 定时任务管理 +- 消息通知(站内信、邮件) +- 公告管理 +- 模块管理 +- 代码生成器 +- OpenAPI 管理 +- 租户管理 diff --git a/web-starter/pom.xml b/web-starter/pom.xml new file mode 100644 index 0000000..8f23d97 --- /dev/null +++ b/web-starter/pom.xml @@ -0,0 +1,221 @@ + + + 4.0.0 + + com.lframework + framework + 1.0.0 + + + web-starter + + + 17 + 17 + UTF-8 + + + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + com.mysql + mysql-connector-j + + + + com.alibaba + druid-spring-boot-starter + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + com.baomidou + dynamic-datasource-spring-boot-starter + + + + com.lframework + common + + + + org.springframework.boot + spring-boot-starter-web + + + + jackson-module-jaxb-annotations + com.fasterxml.jackson.module + + + + org.springframework.boot + spring-boot-starter-aop + + + + com.github.penggle + kaptcha + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + com.fasterxml.jackson.module + jackson-module-parameter-names + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + org.codehaus.groovy + groovy-all + pom + + + + com.alibaba + easyexcel + + + org.ow2.asm + asm + + + + + + org.springframework.security + spring-security-web + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework.boot + spring-boot-starter-quartz + + + + org.freemarker + freemarker + + + + org.springframework.session + spring-session-data-redis + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.apache.commons + commons-pool2 + + + + cn.dev33 + sa-token-spring-boot3-starter + + + + cn.dev33 + sa-token-redis-jackson + + + + + + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + + + + com.aliyun.oss + aliyun-sdk-oss + + + + com.huaweicloud + esdk-obs-java + + + + com.qcloud + cos_api + + + + + org.ssssssss + magic-api-spring-boot-starter + + + org.ssssssss + magic-api-servlet-javaee + + + + + org.ssssssss + magic-api-plugin-cluster + + + org.ssssssss + magic-api-servlet-javaee + + + + + org.ssssssss + magic-api-servlet-jakarta + + + + org.jcodec + jcodec + + + + org.jcodec + jcodec-javase + + + \ No newline at end of file diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/CacheAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/CacheAutoConfiguration.java new file mode 100644 index 0000000..cdd73ee --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/CacheAutoConfiguration.java @@ -0,0 +1,53 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.config.properties.CacheProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.core.RedisTemplate; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Configuration +@EnableCaching +@EnableConfigurationProperties(CacheProperties.class) +public class CacheAutoConfiguration extends CachingConfigurerSupport { + + @Autowired + private RedisTemplate redisTemplate; + + @Bean + public RedisCacheWriter writer() { + return RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()); + } + + @Bean + public CacheManager cacheManager(CacheProperties properties) { + Map configurationMap = new HashMap<>(); + if (!CollectionUtil.isEmpty(properties.getRegions())) { + properties.getRegions().forEach((k, v) -> { + configurationMap.put(k, RedisCacheConfiguration + .defaultCacheConfig().entryTtl(Duration.ofSeconds(v))); + }); + } + + return RedisCacheManager.builder(writer()) + .initialCacheNames(configurationMap.keySet()) + .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofSeconds(properties.getTtl()))) + .withInitialCacheConfigurations(configurationMap) + .build(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/KaptchaAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/KaptchaAutoConfiguration.java new file mode 100644 index 0000000..913562c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/KaptchaAutoConfiguration.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.config; + +import com.google.code.kaptcha.Producer; +import com.google.code.kaptcha.util.Config; +import com.lframework.starter.web.config.properties.KaptchaProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * 验证码配置 + * + * @author zmj + */ +@Configuration +@EnableConfigurationProperties(KaptchaProperties.class) +public class KaptchaAutoConfiguration { + + @Bean + @Primary + public Producer getProducer(KaptchaProperties properties) { + + Config config = new Config(properties.props()); + + return config.getProducerImpl(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java new file mode 100644 index 0000000..309e7e8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java @@ -0,0 +1,86 @@ +package com.lframework.starter.web.config; + +import io.lettuce.core.resource.ClientResources; +import io.lettuce.core.resource.NettyCustomizer; +import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.handler.timeout.IdleStateHandler; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; + +public class LettuceAutoConfiguration { + + @Value("${spring.redis.lettuce.reader-idle-time-seconds:30}") + private Integer readerIdleTimeSeconds; + + // @Bean + public LettuceInitializingBean lettuceInitializingBean(RedisConnectionFactory redisConnectionFactory) { + return new LettuceInitializingBean(redisConnectionFactory); + } + + @Bean + public ClientResources clientResources() { + NettyCustomizer nettyCustomizer = new NettyCustomizer() { + @Override + public void afterChannelInitialized(Channel channel) { + channel.pipeline().addLast( + //第一个参数readerIdleTimeSeconds设置为小于超时时间timeout,单位为秒, + //每隔readerIdleTimeSeconds会进行重连,在超时之前重连就能避免命令超时报错。 + new IdleStateHandler(readerIdleTimeSeconds, 0, 0)); + channel.pipeline().addLast(new ChannelDuplexHandler() { + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object isEvt) throws Exception { + if (isEvt instanceof IdleStateEvent) { + ctx.disconnect(); + } + } + }); + } + }; + return ClientResources.builder().nettyCustomizer(nettyCustomizer).build(); + } + + @Bean + public CustomLettuceClientConfigurationBuilderCustomizer customLettuceClientConfigurationBuilderCustomizer() { + return new CustomLettuceClientConfigurationBuilderCustomizer(clientResources()); + } + + public static class CustomLettuceClientConfigurationBuilderCustomizer implements + LettuceClientConfigurationBuilderCustomizer { + + private ClientResources clientResources; + + public CustomLettuceClientConfigurationBuilderCustomizer(ClientResources clientResources) { + this.clientResources = clientResources; + } + + @Override + public void customize(LettuceClientConfigurationBuilder clientConfigurationBuilder) { + clientConfigurationBuilder.clientResources(clientResources); + } + } + + public static class LettuceInitializingBean implements InitializingBean { + + private RedisConnectionFactory redisConnectionFactory; + + public LettuceInitializingBean(RedisConnectionFactory redisConnectionFactory) { + this.redisConnectionFactory = redisConnectionFactory; + } + + @Override + public void afterPropertiesSet() throws Exception { + if (redisConnectionFactory instanceof LettuceConnectionFactory) { + LettuceConnectionFactory c = (LettuceConnectionFactory) redisConnectionFactory; + c.setValidateConnection(true); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java new file mode 100644 index 0000000..d4ce12a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.common.locker.LockBuilder; +import com.lframework.starter.web.core.annotations.locker.EnableLock; +import com.lframework.starter.web.core.annotations.locker.LockType; +import com.lframework.starter.web.core.components.locker.DefaultLockBuilder; +import com.lframework.starter.web.core.components.locker.RedisLockBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.type.AnnotationMetadata; + +import java.util.Map; + +public class LockAutoConfiguration implements ImportSelector { + + @Override + public String[] selectImports(AnnotationMetadata metadata) { + Map annotationAttributes = metadata + .getAnnotationAttributes(EnableLock.class.getName()); + + LockType type = (LockType) annotationAttributes.get("type"); + if (type == LockType.REDIS) { + return new String[]{RedisLockConfiguration.class.getName()}; + } + + return new String[]{LockConfiguration.class.getName()}; + } + + public static class LockConfiguration { + + @Bean + public LockBuilder lockBuilder() { + return new DefaultLockBuilder(); + } + } + + public static class RedisLockConfiguration { + + @Bean + public LockBuilder lockBuilder() { + return new RedisLockBuilder(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java new file mode 100644 index 0000000..af14a98 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java @@ -0,0 +1,75 @@ +package com.lframework.starter.web.config; + +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.config.properties.SecretProperties; +import com.lframework.starter.web.core.components.magic.MagicCustomAuthorizationInterceptor; +import com.lframework.starter.web.core.components.magic.MagicCustomJsonValueProvider; +import com.lframework.starter.web.core.components.magic.MagicCustomMagicFunction; +import com.lframework.starter.web.core.components.magic.MagicCustomSqlCache; +import com.lframework.starter.web.core.utils.DataSourceUtil; +import com.lframework.starter.web.core.utils.EncryptUtil; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.service.TenantService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Map; + +@Configuration +@Import({ + MagicCustomAuthorizationInterceptor.class, + MagicCustomJsonValueProvider.class, + MagicCustomMagicFunction.class, + MagicCustomSqlCache.class +}) +public class MagicCustomAutoConfiguration { + + @Autowired + private DynamicDataSourceProperties dynamicDataSourceProperties; + + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(10); + taskScheduler.initialize(); + return taskScheduler; + } + + @Bean + public MagicDynamicDataSource magicDynamicDataSource(DynamicRoutingDataSource dataSource, + TenantService tenantService, BasicDataSourceCreator basicDataSourceCreator, + SecretProperties secretProperties) { + Map dataSourceMap = dataSource.getDataSources(); + MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource(); + dynamicDataSource.setDefault(dataSourceMap.get("master")); + + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource() + .get("master"); + // 这里只加载启用的租户 + Wrapper queryWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getAvailable, Boolean.TRUE); + List tenants = tenantService.list(queryWrapper); + + for (Tenant tenant : tenants) { + dynamicDataSource.add(String.valueOf(tenant.getId()), + basicDataSourceCreator.createDataSource( + DataSourceUtil.createDataSourceProperty(dataSourceProperty, tenant.getJdbcUrl(), + tenant.getJdbcUsername(), + EncryptUtil.decrypt(tenant.getJdbcPassword(), secretProperties)))); + } + + return dynamicDataSource; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java new file mode 100644 index 0000000..2c1fd90 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.config; + +import cn.hutool.extra.mail.MailAccount; +import com.lframework.starter.web.config.properties.MailProperties; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.impl.MailServiceImpl; +import com.lframework.starter.web.inner.service.MailService; +import com.lframework.starter.web.inner.service.SysConfService; +import com.sun.mail.util.MailSSLSocketFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +import java.security.GeneralSecurityException; + +@Configuration +public class MailAutoConfiguration { + + @Bean + @Scope("prototype") + @ConditionalOnMissingBean(MailService.class) + public MailService getMailService(SysConfService sysConfService) + throws GeneralSecurityException { + + String configStr = sysConfService.findRequiredByKey("mail"); + MailProperties properties = JsonUtil.parseObject(configStr, MailProperties.class); + MailAccount account = new MailAccount(); + account.setHost(properties.getHost()); + account.setPort(properties.getPort()); + account.setUser(properties.getUser()); + account.setPass(properties.getPass()); + account.setFrom(properties.getFrom()); + account.setSslEnable(properties.getSslEnable()); + account.setTimeout(properties.getTimeOut()); + account.setConnectionTimeout(properties.getConnectTimeOut()); + + MailSSLSocketFactory sf = new MailSSLSocketFactory(); + sf.setTrustAllHosts(true); + account.setCustomProperty("mail.smtp.ssl.socketFactory", sf); + + return new MailServiceImpl(account); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java new file mode 100644 index 0000000..c76696d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.lframework.starter.web.core.components.permission.DataPermissionHandlerImpl; +import com.lframework.starter.web.core.handlers.DefaultBaseEntityFillHandler; +import com.lframework.starter.web.core.interceptors.CustomSortInterceptor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(MetaObjectHandler.class) + public MetaObjectHandler getMetaObjectHandler() { + + return new DefaultBaseEntityFillHandler(); + } + + @Bean + @ConditionalOnMissingBean(MybatisPlusInterceptor.class) + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor( + new DataPermissionInterceptor(new DataPermissionHandlerImpl())); + interceptor.addInnerInterceptor(new CustomSortInterceptor()); + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } + +// @Bean +// public MybatisPlusUpdateAllColumnInjector mybatisPlusUpdateAllColumnInjector() { +// return new MybatisPlusUpdateAllColumnInjector(); +// } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java new file mode 100644 index 0000000..282b07c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.components.captcha.CaptchaValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisBeanAutoConfiguration { + + @Bean + public CaptchaValidator captchaValidator() { + return new CaptchaValidator(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java new file mode 100644 index 0000000..db8f1b7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.components.security.PasswordEncoderWrapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(PasswordEncoder.class) + public PasswordEncoder getPasswordEncoder() { + + return new BCryptPasswordEncoder(); + } + + @Bean + public PasswordEncoderWrapper passwordEncoderWrapper() { + return new PasswordEncoderWrapper(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java new file mode 100644 index 0000000..19bfe3a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java @@ -0,0 +1,58 @@ +package com.lframework.starter.web.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import com.lframework.starter.web.core.components.redis.RedisHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericToStringSerializer; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; + +@Configuration +public class RedisAutoConfiguration { + + @Bean + @Primary + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer( + Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + + om.registerModule(new ParameterNamesModule()).registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()); // new module, NOT JSR310Module + om.findAndRegisterModules(); + + om.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + + jackson2JsonRedisSerializer.setObjectMapper(om); + + template.setKeySerializer(new GenericToStringSerializer<>(Object.class)); + template.setHashKeySerializer(new GenericToStringSerializer<>(Object.class)); + + template.setValueSerializer(new JdkSerializationRedisSerializer()); + template.setHashValueSerializer(new JdkSerializationRedisSerializer()); + + template.afterPropertiesSet(); + return template; + } + + @Bean + public RedisHandler redisHandler() { + return new RedisHandler(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java new file mode 100644 index 0000000..a2daedc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java @@ -0,0 +1,145 @@ +package com.lframework.starter.web.config; + +import cn.dev33.satoken.dao.SaTokenDao; +import io.lettuce.core.resource.ClientResources; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; + +class SaTokenAutoConfiguration { + + @Bean + public SaAloneRedisInject saAloneRedisInject( + ObjectProvider saTokenDaoProvider, + ObjectProvider builderCustomizers, + ClientResources clientResources) { + return new SaAloneRedisInject(saTokenDaoProvider, builderCustomizers, clientResources); + } + + public static class SaAloneRedisInject implements EnvironmentAware { + + /** + * 配置信息的前缀 + */ + public static final String ALONE_PREFIX = "sa-token.alone-redis"; + + /** + * Sa-Token 持久层接口 + */ + private ObjectProvider saTokenDaoProvider; + + private ObjectProvider builderCustomizers; + + private ClientResources clientResources; + + public SaAloneRedisInject(ObjectProvider saTokenDaoProvider, + ObjectProvider builderCustomizers, + ClientResources clientResources) { + this.saTokenDaoProvider = saTokenDaoProvider; + this.builderCustomizers = builderCustomizers; + this.clientResources = clientResources; + } + + /** + * 开始注入 + */ + @Override + public void setEnvironment(Environment environment) { + try { + Object saTokenDao = saTokenDaoProvider.getIfAvailable(); + // 如果为空,则不进行任何操作 + if (saTokenDao == null) { + return; + } + // 如果配置文件不包含相关配置,则不进行任何操作 + if (environment.getProperty(ALONE_PREFIX + ".host") == null) { + return; + } + + // ------------------- 开始注入 + + // 获取cfg对象 + RedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, RedisProperties.class) + .get(); + + // 1. Redis配置 + RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); + redisConfig.setHostName(cfg.getHost()); + redisConfig.setPort(cfg.getPort()); + redisConfig.setDatabase(cfg.getDatabase()); + redisConfig.setPassword(RedisPassword.of(cfg.getPassword())); + + // 2. 连接池配置 + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + // pool配置 + RedisProperties.Lettuce lettuce = cfg.getLettuce(); + if (lettuce.getPool() != null) { + RedisProperties.Pool pool = cfg.getLettuce().getPool(); + // 连接池最大连接数 + poolConfig.setMaxTotal(pool.getMaxActive()); + // 连接池中的最大空闲连接 + poolConfig.setMaxIdle(pool.getMaxIdle()); + // 连接池中的最小空闲连接 + poolConfig.setMinIdle(pool.getMinIdle()); + // 连接池最大阻塞等待时间(使用负值表示没有限制) + poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis()); + } + LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder(); + // timeout + if (cfg.getTimeout() != null) { + builder.commandTimeout(cfg.getTimeout()); + } + // shutdownTimeout + if (lettuce.getShutdownTimeout() != null) { + builder.shutdownTimeout(lettuce.getShutdownTimeout()); + } + builder.clientResources(clientResources); + builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); + // 创建Factory对象 + LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build(); + LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig); + factory.afterPropertiesSet(); + + // 3. 开始初始化 SaTokenDao(兼容新版本:通过反射调用 init 并关闭 isInit) + try { + java.lang.reflect.Field isInitField = saTokenDao.getClass().getDeclaredField("isInit"); + isInitField.setAccessible(true); + isInitField.set(saTokenDao, false); + } catch (NoSuchFieldException ignore) { + // 新版本可能无该字段,忽略 + } + try { + java.lang.reflect.Method initMethod = saTokenDao.getClass() + .getMethod("init", org.springframework.data.redis.connection.RedisConnectionFactory.class); + initMethod.invoke(saTokenDao, factory); + } catch (NoSuchMethodException ignore) { + // 新版本如果没有 init 方法,忽略 + } + return; + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 骗过编辑器,增加配置文件代码提示 + * + * @return 配置对象 + */ + @ConfigurationProperties(prefix = ALONE_PREFIX) + public RedisProperties getSaAloneRedisConfig() { + return new RedisProperties(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java new file mode 100644 index 0000000..7167bb7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.components.security.PermitAllService; +import com.lframework.starter.web.core.components.tenant.TenantInterceptor; +import com.lframework.starter.web.core.interceptors.LoginInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class SecurityAutoConfiguration implements WebMvcConfigurer { + + @Autowired + private PermitAllService permitAllService; + + @Autowired + private TenantInterceptor tenantInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + registry.addInterceptor(new LoginInterceptor(permitAllService)); + registry.addInterceptor(tenantInterceptor); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java new file mode 100644 index 0000000..fdfcc28 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java @@ -0,0 +1,47 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.utils.ApplicationUtil; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.net.InetAddress; + +/** + * Swagger Configuration + */ +@Configuration +public class SwaggerAutoConfiguration { + + @Bean + @ConditionalOnProperty(value = "knife4j.enable", matchIfMissing = true) + public SwaggerReadyListener swaggerReadyListener() { + + return new SwaggerReadyListener(); + } + + /** + * Application启动成功监听器 + */ + @Slf4j + public static class SwaggerReadyListener implements ApplicationListener { + + @SneakyThrows + @Override + public void onApplicationEvent(@org.springframework.lang.NonNull ApplicationReadyEvent applicationReadyEvent) { + + log.info("\n----------------------------------------------------------\n\t" + + "Application '{}' 已启动! 访问地址:\n\t" + "Local: \thttp://localhost:{}\n\t" + + "External: \thttp://{}:{}\n\t" + "Doc: \thttp://{}:{}/doc.html\n" + + "----------------------------------------------------------", + ApplicationUtil.getProperty("spring.application.name"), + ApplicationUtil.getProperty("server.port"), + InetAddress.getLocalHost().getHostAddress(), ApplicationUtil.getProperty("server.port"), + InetAddress.getLocalHost().getHostAddress(), ApplicationUtil.getProperty("server.port")); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java new file mode 100644 index 0000000..270c5c6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java @@ -0,0 +1,93 @@ +package com.lframework.starter.web.config; + +import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.lframework.starter.web.config.properties.SecretProperties; +import com.lframework.starter.web.core.components.tenant.TenantInterceptor; +import com.lframework.starter.web.core.interceptors.TenantInterceptorImpl; +import com.lframework.starter.web.core.listeners.TenantListener.ClearTenantListener; +import com.lframework.starter.web.core.listeners.TenantListener.ReloadTenantListener; +import com.lframework.starter.web.core.listeners.TenantListener.SetTenantListener; +import com.lframework.starter.web.core.utils.DataSourceUtil; +import com.lframework.starter.web.core.utils.EncryptUtil; +import com.lframework.starter.web.inner.service.TenantService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Configuration +public class TenantAutoConfiguration { + + @Autowired + private DynamicDataSourceProperties dynamicDataSourceProperties; + + @Bean + public TenantInterceptor tenantInterceptor(TenantService tenantService) { + return new TenantInterceptorImpl(tenantService); + } + + @Bean + public ReloadTenantListener reloadTenantListener() { + return new ReloadTenantListener(); + } + + @Bean + public SetTenantListener setTenantListener() { + return new SetTenantListener(); + } + + @Bean + public ClearTenantListener clearTenantListener() { + return new ClearTenantListener(); + } + + @Bean + public AbstractJdbcDataSourceProvider tenantDataSourceProvider( + SecretProperties secretProperties) { + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource() + .get("master"); + return new AbstractJdbcDataSourceProvider(dataSourceProperty.getDriverClassName(), + dataSourceProperty.getUrl(), dataSourceProperty.getUsername(), + dataSourceProperty.getPassword()) { + @Override + protected Map executeStmt(Statement statement) + throws SQLException { + Map dataSourcePropertyMap = new HashMap<>(); + // 这里只加载启用的租户 + ResultSet rs = statement.executeQuery("select * from tenant where available = true"); + while (rs.next()) { + try { + String name = rs.getString("id"); + String username = rs.getString("jdbc_username"); + String password = rs.getString("jdbc_password"); + String url = rs.getString("jdbc_url"); + + DataSourceProperty property = DataSourceUtil.createDataSourceProperty( + dataSourceProperty, + url, username, EncryptUtil.decrypt(password, secretProperties)); + + if (!DataSourceUtil.validConnection(property.getUrl(), property.getUsername(), + property.getPassword())) { + log.warn("租户 {} 数据源连接失败 url {}", name, url); + continue; + } + log.info("加载租户 {} 数据源 url {}", name, property.getUrl()); + dataSourcePropertyMap.put(name, property); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + return dataSourcePropertyMap; + } + }; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java new file mode 100644 index 0000000..01f6eb4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java @@ -0,0 +1,66 @@ +package com.lframework.starter.web.config; + +import com.baomidou.dynamic.datasource.processor.DsHeaderProcessor; +import com.baomidou.dynamic.datasource.processor.DsProcessor; +import com.baomidou.dynamic.datasource.processor.DsSessionProcessor; +import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor; +import com.baomidou.dynamic.datasource.processor.jakarta.DsJakartaHeaderProcessor; +import com.baomidou.dynamic.datasource.processor.jakarta.DsJakartaSessionProcessor; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.constants.MyBatisStringPool; +import com.lframework.starter.web.core.utils.TenantUtil; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.boot.SpringBootVersion; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@AutoConfigureBefore(value = DynamicDataSourceAutoConfiguration.class) +public class TenantDynamicDataSourceAutoConfiguration { + + public class DsCurTenantProcessor extends DsProcessor { + + private String primary; + + public DsCurTenantProcessor(String primary) { + this.primary = primary; + } + + @Override + public boolean matches(String key) { + return key.equals(MyBatisStringPool.DS_KEY_CUR_TENANT); + } + + @Override + public String doDetermineDatasource(MethodInvocation invocation, String key) { + + if (TenantUtil.enableTenant()) { + return TenantContextHolder.getTenantIdStr(); + } + return this.primary; + } + } + + @Bean + public DsProcessor dsProcessor(DynamicDataSourceProperties properties) { + String version = SpringBootVersion.getVersion(); + DsProcessor headerProcessor; + DsProcessor sessionProcessor; + if (version.startsWith("3")) { + headerProcessor = new DsJakartaHeaderProcessor(); + sessionProcessor = new DsJakartaSessionProcessor(); + } else { + headerProcessor = new DsHeaderProcessor(); + sessionProcessor = new DsSessionProcessor(); + } + DsCurTenantProcessor curTenantProcessor = new DsCurTenantProcessor(properties.getPrimary()); + DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor(); + headerProcessor.setNextProcessor(sessionProcessor); + sessionProcessor.setNextProcessor(spelExpressionProcessor); + spelExpressionProcessor.setNextProcessor(curTenantProcessor); + return headerProcessor; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/TransactionAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/TransactionAutoConfiguration.java new file mode 100644 index 0000000..2b57318 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/TransactionAutoConfiguration.java @@ -0,0 +1,70 @@ +package com.lframework.starter.web.config; + +import org.springframework.aop.Advisor; +import org.springframework.aop.aspectj.AspectJExpressionPointcut; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.interceptor.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * 事务管理器配置 + * + * @author zmj + */ +@Configuration +@EnableTransactionManagement +public class TransactionAutoConfiguration { + + private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.lframework..*.*Service.add*(..)) || execution (* com.lframework..*.*Service.save*(..)) || execution (* com.lframework..*.*Service.insert*(..)) || execution (* com.lframework..*.*Service.update*(..)) || execution (* com.lframework..*.*Service.delete*(..)) || execution (* com.lframework..*.*Service.find*(..)) || execution (* com.lframework..*.*Service.select*(..))"; + + @Autowired + private PlatformTransactionManager transactionManager; + + @Bean + public TransactionInterceptor txAdvice() { + + NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); + /* 当前没有事务:只有select,非事务执行;有update,insert,delete操作,自动提交; + * 当前有事务:如果有update,insert,delete操作,支持当前事务 */ + RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute(); + readOnlyTx.setReadOnly(true); + readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); + /* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务 */ + RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(); + requiredTx.setRollbackRules( + Collections.singletonList(new RollbackRuleAttribute(Exception.class))); + requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); + // requiredTx.setTimeout(TX_METHOD_TIMEOUT); + Map txMap = new HashMap<>(); + txMap.put("add*", requiredTx); + txMap.put("save*", requiredTx); + txMap.put("insert*", requiredTx); + + txMap.put("update*", requiredTx); + txMap.put("delete*", requiredTx); + + txMap.put("find*", readOnlyTx); + txMap.put("select*", readOnlyTx); + source.setNameMap(txMap); + TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source); + return txAdvice; + } + + @Bean + public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor txAdvice) { + + AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); + pointcut.setExpression(AOP_POINTCUT_EXPRESSION); + return new DefaultPointcutAdvisor(pointcut, txAdvice); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java new file mode 100644 index 0000000..f84d2bb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.SecurityUploadProperties; +import com.lframework.starter.web.config.properties.UploadProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.io.File; + +@Configuration +@EnableConfigurationProperties({UploadProperties.class, SecurityUploadProperties.class}) +public class UploadAutoConfiguration implements WebMvcConfigurer { + + @Autowired + private UploadProperties properties; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + + if (StringUtil.isNotBlank(properties.getUrl()) && StringUtil.isNotBlank( + properties.getLocation())) { + + String url = properties.getUrl(); + String location = properties.getLocation(); + + registry.addResourceHandler(url.endsWith("/") ? url + "**" : url + "/**") + .addResourceLocations( + "file:" + (location.endsWith(File.separator) ? location : location + File.separator)); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java new file mode 100644 index 0000000..6ab1583 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java @@ -0,0 +1,242 @@ +package com.lframework.starter.web.config; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jdk8.PackageVersion; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.IdWorker; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.DefaultSettingProperties; +import com.lframework.starter.web.config.properties.SecretProperties; +import com.lframework.starter.web.config.properties.WebProperties; +import com.lframework.starter.web.core.components.security.CheckPermissionHandler; +import com.lframework.starter.web.core.components.security.CheckPermissionHandlerImpl; +import com.lframework.starter.web.core.components.security.PermitAllService; +import com.lframework.starter.web.core.components.sign.CheckSignHandler; +import com.lframework.starter.web.core.components.sign.handler.DefaultCheckSignHandler; +import com.lframework.starter.web.core.components.trace.DefaultTraceBuilder; +import com.lframework.starter.web.core.components.trace.TraceBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import java.io.IOException; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +import static cn.hutool.core.date.DatePattern.*; + +/** + * Web配置 + * + * @author zmj + */ +@Configuration +@EnableConfigurationProperties({WebProperties.class, DefaultSettingProperties.class, SecretProperties.class}) +public class WebAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(CorsFilter.class) + public CorsFilter getCorsFilter() { + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + // Boot3/Spring6: allowCredentials=true 时不能使用 allowedOrigins="*" + config.setAllowCredentials(true); + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + config.addExposedHeader("*"); + // 对接口配置跨域设置 + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } + + @Bean + public Converter localDateTimeConvert() { + + return new Converter() { + @Override + public LocalDateTime convert(String source) { + + if (StringUtil.isBlank(source)) { + return null; + } + + DateTimeFormatter df = DateTimeFormatter.ofPattern(StringPool.DATE_TIME_PATTERN); + LocalDateTime dateTime = LocalDateTime.parse(source, df); + return dateTime; + } + }; + } + + @Bean + public Converter localDateConvert() { + + return new Converter() { + @Override + public LocalDate convert(String source) { + + if (StringUtil.isBlank(source)) { + return null; + } + + DateTimeFormatter df = DateTimeFormatter.ofPattern(StringPool.DATE_PATTERN); + LocalDate date = LocalDate.parse(source, df); + return date; + } + }; + } + + @Bean + public Converter localTimeConvert() { + + return new Converter() { + @Override + public LocalTime convert(String source) { + + if (StringUtil.isBlank(source)) { + return null; + } + + DateTimeFormatter df = DateTimeFormatter.ofPattern(StringPool.TIME_PATTERN); + LocalTime time = LocalTime.parse(source, df); + return time; + } + }; + } + + @Bean + public ObjectMapper getObjectMapper(Jackson2ObjectMapperBuilder builder) { + + ObjectMapper om = builder.build().configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) + .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .registerModule(new ParameterNamesModule()).registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()).registerModule(new JavaLocalDateTimeModule()) + .registerModule(new JavaBigDecimalModule()); + return om; + } + + /** + * 自定义模块,用于格式化LocalDateTime、LocalDate、LocalTime + * + * @author lframework@163.com + */ + class JavaLocalDateTimeModule extends SimpleModule { + + public JavaLocalDateTimeModule() { + super(PackageVersion.VERSION); + this.addSerializer(LocalDateTime.class, + new LocalDateTimeSerializer(DateTimeFormatter.ofPattern( + NORM_DATETIME_PATTERN))); + this.addSerializer(LocalDate.class, + new LocalDateSerializer(DateTimeFormatter.ofPattern(NORM_DATE_PATTERN))); + this.addSerializer(LocalTime.class, + new LocalTimeSerializer(DateTimeFormatter.ofPattern(NORM_TIME_PATTERN))); + this.addDeserializer(LocalDateTime.class, + new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN))); + this.addDeserializer(LocalDate.class, + new LocalDateDeserializer(DateTimeFormatter.ofPattern(NORM_DATE_PATTERN))); + this.addDeserializer(LocalTime.class, + new LocalTimeDeserializer(DateTimeFormatter.ofPattern(NORM_TIME_PATTERN))); + } + } + + /** + * 自定义模块,用于格式化BigDecimal + * + * @author lframework@163.com + */ + class JavaBigDecimalModule extends SimpleModule { + + public JavaBigDecimalModule() { + super(PackageVersion.VERSION); + // 添加BigDecimal序列化器,避免科学计数法,舍弃无效的小数0 + this.addSerializer(BigDecimal.class, new BigDecimalSerializer()); + } + } + + /** + * BigDecimal自定义序列化器 + * 不使用科学计数法,并且舍弃小数的无效0 + * + * @author lframework@163.com + */ + class BigDecimalSerializer extends JsonSerializer { + + @Override + public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + if (value == null) { + gen.writeNull(); + } else { + // 使用stripTrailingZeros()去除尾部无效的0,然后使用toPlainString()避免科学计数法 + gen.writeNumber(value.stripTrailingZeros().toPlainString()); + } + } + } + + @Bean + public IdWorker getIdWorker(WebProperties webProperties) { + + Long workerId = webProperties.getWorkerId(); + Long centerId = webProperties.getCenterId(); + + if (workerId <= 0 || centerId <= 0) { + return new IdWorker(); + } + return new IdWorker(workerId, centerId); + } + + @Bean + @ConditionalOnMissingBean(PermitAllService.class) + public PermitAllService permitAllService() { + + return new PermitAllService(); + } + + @Bean("permission") + @ConditionalOnMissingBean(CheckPermissionHandler.class) + public CheckPermissionHandler checkPermissionHandler() { + + return new CheckPermissionHandlerImpl(); + } + + @Bean + @ConditionalOnMissingBean(TraceBuilder.class) + public TraceBuilder getTraceBuilder() { + return new DefaultTraceBuilder(); + } + + @Bean + @ConditionalOnMissingBean(CheckSignHandler.class) + public CheckSignHandler getCheckSignHandler() { + return new DefaultCheckSignHandler(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java new file mode 100644 index 0000000..5b3db5e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java @@ -0,0 +1,375 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.aop.*; +import com.lframework.starter.web.core.components.cache.CacheVariables; +import com.lframework.starter.web.core.components.generator.handler.impl.*; +import com.lframework.starter.web.core.components.resp.InvokeResultErrorBuilderWrapper; +import com.lframework.starter.web.core.components.resp.ResponseErrorBuilder; +import com.lframework.starter.web.core.components.security.UserTokenResolverImpl; +import com.lframework.starter.web.core.components.sign.CheckSignFactory; +import com.lframework.starter.web.core.components.sign.DefaultCheckSignFactory; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.core.components.upload.handler.impl.*; +import com.lframework.starter.web.core.handlers.exception.WebExceptionHandler; +import com.lframework.starter.web.inner.components.oplog.AuthOpLogType; +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.components.permission.OrderDataPermissionDataPermissionType; +import com.lframework.starter.web.inner.components.permission.ProductDataPermissionDataPermissionType; +import com.lframework.starter.web.inner.components.timeline.*; +import com.lframework.starter.web.inner.controller.AuthController; +import com.lframework.starter.web.inner.controller.QrtzController; +import com.lframework.starter.web.inner.controller.UserCenterController; +import com.lframework.starter.web.inner.controller.system.*; +import com.lframework.starter.web.inner.enums.system.SysDeptNodeType; +import com.lframework.starter.web.inner.handlers.exception.*; +import com.lframework.starter.web.inner.impl.*; +import com.lframework.starter.web.inner.impl.system.*; +import com.lframework.starter.web.inner.listeners.OpLogTimerListener; +import com.lframework.starter.web.inner.listeners.app.SysNotifyGroupForDeleteSysUserGroupListener; +import com.lframework.starter.web.inner.listeners.app.SysUserDeptForDeleteSysDeptListener; +import com.lframework.starter.web.inner.listeners.app.SysUserRoleForDeleteSysRoleListener; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; + +@Slf4j +@Configuration +@Import({ + WebExceptionHandler.class, + DicCityServiceImpl.class, + GenerateCodeServiceImpl.class, + OpLogsServiceImpl.class, + OrderTimeLineServiceImpl.class, + RecursionMappingServiceImpl.class, + SecurityUploadRecordServiceImpl.class, + DefaultSysSelectorController.class, + OpLogController.class, + SysDataDicCategoryController.class, + SysDataDicController.class, + SysDataDicItemController.class, + SysDataPermissionDataController.class, + SysDataPermissionModelDetailController.class, + SysDeptController.class, + SysGenerateCodeController.class, + SysMailMessageController.class, + SysMenuController.class, + SysModuleController.class, + SysNoticeController.class, + SysNotifyGroupController.class, + SysOpenDomainController.class, + SysParameterController.class, + SysRoleCategoryController.class, + SysRoleController.class, + SysRoleMenuController.class, + SysSiteMessageController.class, + SysUserController.class, + SysUserDeptController.class, + SysUserGroupController.class, + SysUserRoleController.class, + TenantController.class, + AuthController.class, + QrtzController.class, + UserCenterController.class, + SysDataDicCategoryServiceImpl.class, + SysDataDicItemServiceImpl.class, + SysDataDicServiceImpl.class, + SysDataPermissionDataServiceImpl.class, + SysDataPermissionModelDetailServiceImpl.class, + SysDeptServiceImpl.class, + SysGenerateCodeServiceImpl.class, + SysMailMessageServiceImpl.class, + SysMenuServiceImpl.class, + SysNoticeLogServiceImpl.class, + SysNoticeServiceImpl.class, + SysNoticeServiceImpl.ReloadNoticeListener.class, + SysNotifyGroupReceiverServiceImpl.class, + SysNotifyGroupServiceImpl.class, + SysOpenDomainServiceImpl.class, + SysParameterServiceImpl.class, + SysRoleCategoryServiceImpl.class, + SysRoleMenuServiceImpl.class, + SysRoleServiceImpl.class, + SysSiteMessageServiceImpl.class, + SysSiteMessageServiceImpl.ReloadSiteMessageListener.class, + SysUserDeptServiceImpl.class, + SysUserGroupDetailServiceImpl.class, + SysUserGroupServiceImpl.class, + SysUserRoleServiceImpl.class, + SysUserServiceImpl.class, + SysUserTelephoneServiceImpl.class, + QrtzServiceImpl.class, + SysModuleServiceImpl.class, + SysModuleTenantServiceImpl.class, + TenantServiceImpl.class, + DefaultUserDetailsService.class, + SysUserDeptForDeleteSysDeptListener.class, + SysUserRoleForDeleteSysRoleListener.class, + SysNotifyGroupForDeleteSysUserGroupListener.class, +}) +@MapperScan("com.lframework.starter.web.**.mappers") +public class WebBeanAutoConfiguration implements EnvironmentAware { + + @Bean + public ControllerAspector controllerAspector() { + + return new ControllerAspector(); + } + + @Bean + public OpenApiAspect openApiAspect() { + return new OpenApiAspect(); + } + + @Bean + public PermissionAspect permissionAspect() { + return new PermissionAspect(); + } + + @Bean + public UploadHandler cosUploadHandler() { + return new CosUploadHandler(); + } + + @Bean + public UploadHandler localUploadHandler() { + return new LocalUploadHandler(); + } + + @Bean + public UploadHandler obsUploadHandler() { + return new ObsUploadHandler(); + } + + @Bean + public UploadHandler ossUploadHandler() { + return new OssUploadHandler(); + } + + @Bean + public SecurityUploadHandler ossSecurityUploadHandler() { + return new OssSecurityUploadHandler(); + } + + @Bean + public SecurityUploadHandler cosSecurityUploadHandler() { + return new CosSecurityUploadHandler(); + } + + @Bean + public SecurityUploadHandler localSecurityUploadHandler() { + return new LocalSecurityUploadHandler(); + } + + @Bean + public SecurityUploadHandler obsSecurityUploadHandler() { + return new ObsSecurityUploadHandler(); + } + + @Bean + public ResponseErrorBuilder invokeResultBuilderWrapper() { + return new InvokeResultErrorBuilderWrapper(); + } + + @Bean + public CheckSignFactory defaultCheckSignFactory() { + return new DefaultCheckSignFactory(); + } + + @Bean("cacheVariables") + public CacheVariables cacheVariables() { + return new CacheVariables(); + } + + @Bean + public UserTokenResolverImpl userTokenResolver() { + return new UserTokenResolverImpl(); + } + + @Bean + public CurrentDateTimeRuleGenerateCodeHandler currentDateTimeRuleGenerateHandler() { + return new CurrentDateTimeRuleGenerateCodeHandler(); + } + + @Bean + public CustomRandomStrGenerateCodeRuleHandler customRandomStrGenerateRuleHandler() { + return new CustomRandomStrGenerateCodeRuleHandler(); + } + + @Bean + public FlowGenerateCodeRuleHandler flowGenerateRuleHandler() { + return new FlowGenerateCodeRuleHandler(); + } + + @Bean + public SnowFlakeGenerateCodeRuleHandler snowFlakeGenerateRuleHandler() { + return new SnowFlakeGenerateCodeRuleHandler(); + } + + @Bean + public StaticStrGenerateCodeRuleHandler staticStrGenerateRuleHandler() { + return new StaticStrGenerateCodeRuleHandler(); + } + + @Bean + public UUIDGenerateCodeRuleHandler uuidGenerateRuleHandler() { + return new UUIDGenerateCodeRuleHandler(); + } + + @Bean + public OrderDataPermissionDataPermissionType orderDataPermissionDataPermissionType() { + return new OrderDataPermissionDataPermissionType(); + } + + @Bean + public ProductDataPermissionDataPermissionType productDataPermissionDataPermissionType() { + return new ProductDataPermissionDataPermissionType(); + } + + @Bean + public ApprovePassOrderTimeLineBizType approvePassOrderTimeLineBizType() { + return new ApprovePassOrderTimeLineBizType(); + } + + @Bean + public ApproveReturnOrderTimeLineBizType approveReturnOrderTimeLineBizType() { + return new ApproveReturnOrderTimeLineBizType(); + } + + @Bean + public CancelApproveOrderTimeLineBizType cancelApproveOrderTimeLineBizType() { + return new CancelApproveOrderTimeLineBizType(); + } + + @Bean + public CreateOrderTimeLineBizType createOrderTimeLineBizType() { + return new CreateOrderTimeLineBizType(); + } + + @Bean + public NormalOrderTimeLineBizType normalOrderTimeLineBizType() { + return new NormalOrderTimeLineBizType(); + } + + @Bean + public SendOrderTimeLineBizType sendOrderTimeLineBizType() { + return new SendOrderTimeLineBizType(); + } + + @Bean + public UpdateOrderTimeLineBizType updateOrderTimeLineBizType() { + return new UpdateOrderTimeLineBizType(); + } + + @Bean + public AccessDeniedExceptionConverter accessDeniedExceptionConverter() { + return new AccessDeniedExceptionConverter(); + } + + @Bean + public BindExceptionConverter bindExceptionConverter() { + return new BindExceptionConverter(); + } + + @Bean + public ClientExceptionConverter clientExceptionConverter() { + return new ClientExceptionConverter(); + } + + @Bean + public ConstraintViolationExceptionConverter constraintViolationExceptionConverter() { + return new ConstraintViolationExceptionConverter(); + } + + @Bean + public ExceptionConverter exceptionConverter() { + return new ExceptionConverter(); + } + + @Bean + public FileUploadExceptionConverter fileUploadExceptionConverter() { + return new FileUploadExceptionConverter(); + } + + @Bean + public HttpMessageNotReadableExceptionConverter httpMessageNotReadableExceptionConverter() { + return new HttpMessageNotReadableExceptionConverter(); + } + + @Bean + public HttpRequestMethodNotSupportedExceptionConverter httpRequestMethodNotSupportedExceptionConverter() { + return new HttpRequestMethodNotSupportedExceptionConverter(); + } + + @Bean + public MethodArgumentNotValidExceptionConverter methodArgumentNotValidExceptionConverter() { + return new MethodArgumentNotValidExceptionConverter(); + } + + @Bean + public NotPermissionExceptionConverter notPermissionExceptionConverter() { + return new NotPermissionExceptionConverter(); + } + + @Bean + public SysExceptionConverter sysExceptionConverter() { + return new SysExceptionConverter(); + } + + @Bean + public TypeMismatchExceptionConverter typeMismatchExceptionConverter() { + return new TypeMismatchExceptionConverter(); + } + + @Bean + public UnexpectedTypeExceptionConverter unexpectedTypeExceptionConverter() { + return new UnexpectedTypeExceptionConverter(); + } + + @Bean + @ConditionalOnProperty(value = "op-logs.enabled", matchIfMissing = true) + public OpLogAspector opLogAspector() { + return new OpLogAspector(); + } + + @Bean + public OrderTimeLineLogAspect orderTimeLineLogAspect() { + return new OrderTimeLineLogAspect(); + } + + @Bean + public OpLogTimerListener opLogTimerListener() { + return new OpLogTimerListener(); + } + + @Bean + public AuthOpLogType authOpLogType() { + return new AuthOpLogType(); + } + + @Bean + public SystemOpLogType systemOpLogType() { + return new SystemOpLogType(); + } + + @Bean + public OtherOpLogType otherOpLogType() { + return new OtherOpLogType(); + } + + @Override + public void setEnvironment(Environment environment) { + log.info("web-starter加载完成"); + } + + @Bean + public SysDeptNodeType sysDeptNodeType() { + return new SysDeptNodeType(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java new file mode 100644 index 0000000..7d33af9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.utils.ApplicationUtil; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebCommonAutoConfiguration { + + @Bean + public ApplicationUtil applicationUtil() { + return new ApplicationUtil(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java new file mode 100644 index 0000000..690f166 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.web.core.components.security.PermitAllService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMvcAutoConfiguration implements WebMvcConfigurer { + + @Autowired + private PermitAllService permitAllService; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // Sa-Token 注解拦截器在不同版本间类名差异较大,且当前项目已由 LoginInterceptor 统一鉴权。 + // 这里仅保留扩展点,避免因 Sa-Token 版本差异导致应用启动失败。 + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java new file mode 100644 index 0000000..f8e93aa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.config; + +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebSwaggerAutoConfiguration { + + @Bean + public GroupedOpenApi webApi() { + + return GroupedOpenApi.builder() + .group("系统功能模块") + .packagesToScan("com.lframework.starter.web.inner") + .pathsToMatch("/**") + .build(); + } + + @Bean + public GroupedOpenApi genApi() { + + return GroupedOpenApi.builder() + .group("代码生成模块") + .packagesToScan("com.lframework.starter.web.gen") + .pathsToMatch("/**") + .build(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java new file mode 100644 index 0000000..7fa619e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java @@ -0,0 +1,84 @@ +package com.lframework.starter.web.config; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.WsProperties; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.websocket.components.WsDataPushWorker; +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.components.WsDataPusherImpl; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.handler.WsHandler; +import com.lframework.starter.web.websocket.interceptor.WsHandshakeInterceptor; +import com.lframework.starter.web.websocket.listener.WsUserConnectListener; +import com.lframework.starter.web.websocket.listener.WsUserDisConnectListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistration; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +import java.nio.charset.StandardCharsets; + +@Configuration +@EnableConfigurationProperties(WsProperties.class) +@ConditionalOnProperty(prefix = "jugg.ws", value = "enabled", havingValue = "true") +public class WsAutoConfiguration implements WebSocketConfigurer { + + @Autowired + private WsProperties properties; + + @Bean + public WsDataPusher wsDataPusher(@Qualifier("redisTemplate") RedisTemplate redisTemplate) { + return new WsDataPusherImpl(redisTemplate, properties); + } + + @Bean + public RedisMessageListenerContainer redisMessageListenerContainer( + RedisConnectionFactory redisConnectionFactory) { + RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer(); + redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory); + redisMessageListenerContainer.addMessageListener((message, pattern) -> { + WsDataPushWorker.push( + JsonUtil.parseObject(StringUtil.str(message.getBody(), StandardCharsets.UTF_8), + WsPushData.class)); + }, ChannelTopic.of(properties.getTopic())); + return redisMessageListenerContainer; + } + + @Bean + public WsHandler wsHandler() { + return new WsHandler(); + } + + @Bean + public WsHandshakeInterceptor wsHandshakeInterceptor() { + return new WsHandshakeInterceptor(); + } + + @Bean + public WsUserConnectListener wsUserConnectListener() { + return new WsUserConnectListener(); + } + + @Bean + public WsUserDisConnectListener wsUserDisConnectListener() { + return new WsUserDisConnectListener(); + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + WebSocketHandlerRegistration registration = registry.addHandler(wsHandler(), "/message/bus") + .addInterceptors(wsHandshakeInterceptor()); + if (properties.isSupportCrossDomain()) { + registration.setAllowedOrigins("*"); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/CacheProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/CacheProperties.java new file mode 100644 index 0000000..38d985d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/CacheProperties.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Map; + +@Data +@ConfigurationProperties(prefix = "jugg.cache") +public class CacheProperties { + + /** + * 公共缓存过期时间 + */ + private Long ttl = 1800L; + + /** + * 特殊指定缓存过期时间 + */ + private Map regions; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java new file mode 100644 index 0000000..59a8a67 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.default-setting") +public class DefaultSettingProperties { + + /** + * 默认的用户ID,用于写入数据库时的createById和updateById的自动赋值,如果有登录人则取登录人ID,如果没有则取默认用户ID,如果不配置,默认是1 + */ + private String defaultUserId = "1"; + + /** + * 默认的用户姓名,用于写入数据库时的createBy和updateBy的自动赋值,如果有登录人则取登录人姓名,如果没有则取默认用户姓名,如果不配置,默认是系统管理员 + */ + private String defaultUserName = "系统管理员"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/KaptchaProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/KaptchaProperties.java new file mode 100644 index 0000000..f48ac1f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/KaptchaProperties.java @@ -0,0 +1,325 @@ +package com.lframework.starter.web.config.properties; + +import com.google.code.kaptcha.Constants; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Properties; + +/** + * 验证码配置信息 + * + * @author zmj + */ +@ConfigurationProperties(prefix = "jugg.kaptcha") +public class KaptchaProperties { + + private static final int DEFAULT_EXPIRE_TIME = 5; + + private Integer expireTime = DEFAULT_EXPIRE_TIME; + + private String sessionConfigKey = Constants.KAPTCHA_SESSION_KEY; + + private String sessionConfigDate = Constants.KAPTCHA_SESSION_DATE; + + private Boolean border = true; + + private String borderColor = "black"; + + private String borderThickness = "1"; + + private String noiseColor = "black"; + + private String noiseImpl = "com.google.code.kaptcha.impl.DefaultNoise"; + + private String obscurificatorImpl = "com.google.code.kaptcha.impl.WaterRipple"; + + private String producerImpl = "com.google.code.kaptcha.impl.DefaultKaptcha"; + + private String textProducerImpl = "com.google.code.kaptcha.text.impl.DefaultTextCreator"; + + private String textProducerCharString = "abcde2345678gfynmnpwx"; + + private String textProducerCharLength = "5"; + + private String textProducerFontNames = "Arial,Courier"; + + private String textProducerFontColor = "black"; + + private String textProducerFontSize = "40"; + + private String textProducerCharSpace = "2"; + + private String wordRenderImpl = "com.google.code.kaptcha.text.impl.DefaultWordRenderer"; + + private String backGroundImpl = "com.google.code.kaptcha.impl.DefaultBackground"; + + private String backGroundClrFrom = "lightGray"; + + private String backGroundClrTo = "white"; + + private String imageWidth = "200"; + + private String imageHeight = "50"; + + public Properties props() { + + Properties properties = new Properties(); + properties.put(Constants.KAPTCHA_SESSION_CONFIG_KEY, this.getSessionConfigKey()); + properties.put(Constants.KAPTCHA_SESSION_CONFIG_DATE, this.getSessionConfigDate()); + properties.put(Constants.KAPTCHA_BORDER, this.getBorder()); + properties.put(Constants.KAPTCHA_BORDER_COLOR, this.getBorderColor()); + properties.put(Constants.KAPTCHA_BORDER_THICKNESS, this.getBorderThickness()); + properties.put(Constants.KAPTCHA_NOISE_COLOR, this.getNoiseColor()); + properties.put(Constants.KAPTCHA_NOISE_IMPL, this.getNoiseImpl()); + properties.put(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, this.getObscurificatorImpl()); + properties.put(Constants.KAPTCHA_PRODUCER_IMPL, this.getProducerImpl()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_IMPL, this.getTextProducerImpl()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, this.getTextProducerCharString()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, this.getTextProducerCharLength()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, this.getTextProducerFontNames()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, this.getTextProducerFontColor()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, this.getTextProducerFontSize()); + properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, this.getTextProducerCharSpace()); + properties.put(Constants.KAPTCHA_WORDRENDERER_IMPL, this.getWordRenderImpl()); + properties.put(Constants.KAPTCHA_BACKGROUND_IMPL, this.getBackGroundImpl()); + properties.put(Constants.KAPTCHA_BACKGROUND_CLR_FROM, this.getBackGroundClrFrom()); + properties.put(Constants.KAPTCHA_BACKGROUND_CLR_TO, this.getBackGroundClrTo()); + properties.put(Constants.KAPTCHA_IMAGE_WIDTH, this.getImageWidth()); + properties.put(Constants.KAPTCHA_IMAGE_HEIGHT, this.getImageHeight()); + + return properties; + } + + public Integer getExpireTime() { + + return expireTime; + } + + public void setExpireTime(Integer expireTime) { + + if (expireTime < 0) { + expireTime = DEFAULT_EXPIRE_TIME; + } + this.expireTime = expireTime; + } + + public String getSessionConfigKey() { + + return sessionConfigKey; + } + + public void setSessionConfigKey(String sessionConfigKey) { + + this.sessionConfigKey = sessionConfigKey; + } + + public String getSessionConfigDate() { + + return sessionConfigDate; + } + + public void setSessionConfigDate(String sessionConfigDate) { + + this.sessionConfigDate = sessionConfigDate; + } + + public Boolean getBorder() { + + return border; + } + + public void setBorder(Boolean border) { + + this.border = border; + } + + public String getBorderColor() { + + return borderColor; + } + + public void setBorderColor(String borderColor) { + + this.borderColor = borderColor; + } + + public String getBorderThickness() { + + return borderThickness; + } + + public void setBorderThickness(String borderThickness) { + + this.borderThickness = borderThickness; + } + + public String getNoiseColor() { + + return noiseColor; + } + + public void setNoiseColor(String noiseColor) { + + this.noiseColor = noiseColor; + } + + public String getNoiseImpl() { + + return noiseImpl; + } + + public void setNoiseImpl(String noiseImpl) { + + this.noiseImpl = noiseImpl; + } + + public String getObscurificatorImpl() { + + return obscurificatorImpl; + } + + public void setObscurificatorImpl(String obscurificatorImpl) { + + this.obscurificatorImpl = obscurificatorImpl; + } + + public String getProducerImpl() { + + return producerImpl; + } + + public void setProducerImpl(String producerImpl) { + + this.producerImpl = producerImpl; + } + + public String getTextProducerImpl() { + + return textProducerImpl; + } + + public void setTextProducerImpl(String textProducerImpl) { + + this.textProducerImpl = textProducerImpl; + } + + public String getTextProducerCharString() { + + return textProducerCharString; + } + + public void setTextProducerCharString(String textProducerCharString) { + + this.textProducerCharString = textProducerCharString; + } + + public String getTextProducerCharLength() { + + return textProducerCharLength; + } + + public void setTextProducerCharLength(String textProducerCharLength) { + + this.textProducerCharLength = textProducerCharLength; + } + + public String getTextProducerFontNames() { + + return textProducerFontNames; + } + + public void setTextProducerFontNames(String textProducerFontNames) { + + this.textProducerFontNames = textProducerFontNames; + } + + public String getTextProducerFontColor() { + + return textProducerFontColor; + } + + public void setTextProducerFontColor(String textProducerFontColor) { + + this.textProducerFontColor = textProducerFontColor; + } + + public String getTextProducerFontSize() { + + return textProducerFontSize; + } + + public void setTextProducerFontSize(String textProducerFontSize) { + + this.textProducerFontSize = textProducerFontSize; + } + + public String getTextProducerCharSpace() { + + return textProducerCharSpace; + } + + public void setTextProducerCharSpace(String textProducerCharSpace) { + + this.textProducerCharSpace = textProducerCharSpace; + } + + public String getWordRenderImpl() { + + return wordRenderImpl; + } + + public void setWordRenderImpl(String wordRenderImpl) { + + this.wordRenderImpl = wordRenderImpl; + } + + public String getBackGroundImpl() { + + return backGroundImpl; + } + + public void setBackGroundImpl(String backGroundImpl) { + + this.backGroundImpl = backGroundImpl; + } + + public String getBackGroundClrFrom() { + + return backGroundClrFrom; + } + + public void setBackGroundClrFrom(String backGroundClrFrom) { + + this.backGroundClrFrom = backGroundClrFrom; + } + + public String getBackGroundClrTo() { + + return backGroundClrTo; + } + + public void setBackGroundClrTo(String backGroundClrTo) { + + this.backGroundClrTo = backGroundClrTo; + } + + public String getImageWidth() { + + return imageWidth; + } + + public void setImageWidth(String imageWidth) { + + this.imageWidth = imageWidth; + } + + public String getImageHeight() { + + return imageHeight; + } + + public void setImageHeight(String imageHeight) { + + this.imageHeight = imageHeight; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/MailProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/MailProperties.java new file mode 100644 index 0000000..4967bad --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/MailProperties.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; + +/** + * 邮箱配置 + */ +@Data +public class MailProperties { + + /** + * 邮件服务器的SMTP地址 + */ + private String host; + + /** + * 邮件服务器的SMTP端口 + */ + private Integer port = 25; + + /** + * 发件人 + */ + private String from; + + /** + * 用户名 + */ + private String user; + + /** + * 密码 + */ + private String pass; + + /** + * 使用SSL安全连接 + */ + private Boolean sslEnable; + + /** + * SMTP超时时间 默认30s + */ + private Long timeOut = 30000L; + + /** + * 连接超时时间 默认1s + */ + private Long connectTimeOut = 1000L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecretProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecretProperties.java new file mode 100644 index 0000000..cf45ef6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecretProperties.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.secret") +public class SecretProperties { + + /** + * 秘钥 + */ + private String key; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java new file mode 100644 index 0000000..c5b19a9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.security-upload") +public class SecurityUploadProperties { + + /** + * 下载时的域名 + */ + private String domain; + + /** + * 上传文件的路径 + */ + private String location; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/UploadProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/UploadProperties.java new file mode 100644 index 0000000..c8d87a8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/UploadProperties.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.upload") +public class UploadProperties { + + /** + * 下载时的域名 + */ + private String domain; + + /** + * 载时的baseUrl,与domain的区别:会在url后面拼接/**作为静态资源的url,而domain是后端系统的具体域名,下载时的完整url例如:upload.domain + upload.url/xxx.jpg + */ + private String url; + + /** + * 上传文件的路径 + */ + private String location; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/WebProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WebProperties.java new file mode 100644 index 0000000..6154636 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WebProperties.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.web") +public class WebProperties { + + /** + * 不需要认证的Url + */ + private String filterUrl; + + /** + * 终端ID + */ + private Long workerId = -1L; + + /** + * 数据中心ID + */ + private Long centerId = -1L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java new file mode 100644 index 0000000..01b64ea --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "jugg.ws") +public class WsProperties { + + /** + * 是否开启WebSocket + */ + private boolean enabled = Boolean.FALSE; + + /** + * 集群发送消息时的topic + */ + private String topic = "jugg:ws:topic"; + + /** + * 是否支持跨域 + */ + private boolean supportCrossDomain = true; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java new file mode 100644 index 0000000..85ace72 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java @@ -0,0 +1,22 @@ +package com.lframework.starter.web.core.annotations.constants; + +public enum EncryType { + // 自动 + AUTO, + // 密码 + PASSWORD, + //中文名 + CHINESE_NAME, + //身份证号 + ID_CARD, + //座机号 + FIXED_PHONE, + //手机号 + MOBILE_PHONE, + //电子邮件 + EMAIL, + //中国大陆车牌,包含普通车辆、新能源车辆 + CAR_LICENSE, + //银行卡 + BANK_CARD +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java new file mode 100644 index 0000000..923baa1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.annotations.convert; + +import com.lframework.starter.web.core.annotations.constants.EncryType; + +import java.lang.annotation.*; + +/** + * Dto转Bo时,是否为脱敏字段 只对字符串有效 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EncryptConvert { + + /** + * 类型 + * + * @return + */ + EncryType type() default EncryType.AUTO; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java new file mode 100644 index 0000000..eee65cd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.annotations.convert; + +import java.lang.annotation.*; + +/** + * Dto转Bo时,是否为Enum字段 + * + * 只支持code是字符串或数字 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EnumConvert { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java new file mode 100644 index 0000000..28a3d06 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java @@ -0,0 +1,13 @@ +package com.lframework.starter.web.core.annotations.convert; + +import java.lang.annotation.*; + +/** + * Dto转Bo时,是否忽略转换 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface IgnoreConvert { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java new file mode 100644 index 0000000..02e5ceb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.core.annotations.ds; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.lframework.starter.web.core.constants.MyBatisStringPool; + +import java.lang.annotation.*; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@DS(MyBatisStringPool.DS_KEY_CUR_TENANT) +public @interface CurTenantDs { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java new file mode 100644 index 0000000..7b13b05 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.core.annotations.excel; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ExcelRequired { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java new file mode 100644 index 0000000..38cce5b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.annotations.locker; + +import com.lframework.starter.web.config.LockAutoConfiguration; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(LockAutoConfiguration.class) +@Documented +public @interface EnableLock { + + /** + * 类型:redis、default + *

+ * redis:基于Redis的分布式锁 + *

+ * default:基于JUC的java锁 + * + * @return + */ + LockType type() default LockType.DEFAULT; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java new file mode 100644 index 0000000..e8dea5d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java @@ -0,0 +1,5 @@ +package com.lframework.starter.web.core.annotations.locker; + +public enum LockType { + DEFAULT, REDIS +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java new file mode 100644 index 0000000..2da186e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.core.annotations.openapi; + +import java.lang.annotation.*; + +/** + * 是否为开放API + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OpenApi { + + /** + * 是否验证签名 + * + * @return + */ + boolean sign() default false; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java new file mode 100644 index 0000000..8c349ab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java @@ -0,0 +1,51 @@ +package com.lframework.starter.web.core.annotations.oplog; + +import com.lframework.starter.web.core.components.oplog.OpLogType; + +import java.lang.annotation.*; + +/** + * 系统日志注解 + * + * @author zmj + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OpLog { + + /** + * 日志类型 用于做业务区分 + * + * @return + */ + Class type(); + + /** + * 日志名称 需要填充参数部分用{}占位,会根据params的值进行填充 + * + * @return + */ + String name() default ""; + + /** + * 需要保存的参数 Spel表达式 + * + * @return + */ + String[] params() default {}; + + /** + * 是否循环填充日志名称 会将params中的collection循环format + * + * @return + */ + boolean loopFormat() default false; + + /** + * 是否自动保存参数 + * + * @return + */ + boolean autoSaveParams() default false; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java new file mode 100644 index 0000000..f017207 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java @@ -0,0 +1,13 @@ +package com.lframework.starter.web.core.annotations.permission; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermission { + + String template(); + + String alias(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java new file mode 100644 index 0000000..c2aa027 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.annotations.permission; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermissionGroup { + + DataPermissions[] value(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java new file mode 100644 index 0000000..96d24d5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.annotations.permission; + +import com.lframework.starter.web.core.components.permission.SysDataPermissionDataPermissionType; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermissions { + + Class type(); + + DataPermission[] value(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java new file mode 100644 index 0000000..1f18689 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.core.annotations.security; + +import com.lframework.starter.web.core.components.security.PermissionCalcType; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface HasPermission { + + /** + * 权限 + *

+ * 当requirePlatform == true时并且value是空时,此时只校验平台权限;如果value不为空,那么同时校验权限。 + *

+ * 当requirePlatform == false时,只校验权限,如果此时value为空,那么校验权限一定不通过。 + * + * @return + */ + String[] value() default {}; + + /** + * 计算方式 + * + * @return + */ + PermissionCalcType calcType() default PermissionCalcType.OR; + + /** + * 是否需要平台权限 + * + * @return + */ + boolean requirePlatform() default false; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java new file mode 100644 index 0000000..336588a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.core.annotations.sort; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Sort { + + /** + * 传入列名 + * + * @return + */ + String value(); + + /** + * SQL列名 + * + * @return + */ + String alias() default ""; + + /** + * 是否自动解析 + *

+ * 如果自动解析,那么alias只需要指定表的别名即可,会直接将alias和转为下划线的value拼接作为SQL列名 + * + * @return + */ + boolean autoParse() default false; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java new file mode 100644 index 0000000..1901516 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.annotations.sort; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Sorts { + + Sort[] value(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java new file mode 100644 index 0000000..0deb705 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java @@ -0,0 +1,58 @@ +package com.lframework.starter.web.core.annotations.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; +import com.lframework.starter.web.inner.components.timeline.NormalOrderTimeLineBizType; + +import java.lang.annotation.*; + +/** + * 单据时间轴记录 + * 如果出现嵌套那么以最外层的为准,不会进行嵌套隔离 + * @author zmj + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OrderTimeLineLog { + + /** + * 业务类型 + * + * @return + */ + Class type() default NormalOrderTimeLineBizType.class; + + /** + * 单据ID + * @return + */ + String[] orderId(); + + /** + * 内容 需要填充参数部分用{}占位,会根据params的值进行填充 + * + * @return + */ + String name() default ""; + + /** + * 需要保存的参数 Spel表达式 + * + * @return + */ + String[] params() default {}; + + /** + * 是否循环填充内容 会将params中的collection循环format + * + * @return + */ + boolean loopFormat() default false; + + /** + * 是否为删除操作 + * 如果为删除操作,那么忽略type、name、loopFormat,直接根据orderId进行删除操作 + * @return + */ + boolean delete() default false; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java new file mode 100644 index 0000000..560a9c1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java @@ -0,0 +1,100 @@ +package com.lframework.starter.web.core.aop; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import java.util.LinkedList; +import java.util.List; + +/** + * Controller切面 + * + * @author zmj + */ +@Aspect +public class ControllerAspector { + + @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)) && execution(public * *(..))") + public void controllerPointCut() { + + } + + @Around(value = "controllerPointCut()") + public Object logController(ProceedingJoinPoint joinPoint) throws Throwable { + + Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass()); + + Object[] args = joinPoint.getArgs(); + + List argList = new LinkedList<>(); + + if (logger.isDebugEnabled()) { + String logMsg; + if (!ArrayUtil.isEmpty(args)) { + for (Object arg : args) { + if (arg instanceof HttpServletRequest) { + argList.add("request"); + continue; + } + + if (arg instanceof HttpServletResponse) { + argList.add("response"); + continue; + } + + if (arg instanceof MultipartFile) { + argList.add("file"); + continue; + } + + argList.add(arg); + } + + if (CollectionUtil.isEmpty(argList)) { + logMsg = "null"; + } else { + try { + logMsg = JsonUtil.toJsonString(argList); + } catch (Exception e) { + logMsg = "unknown"; + } + } + } else { + logMsg = "null"; + } + + logger.debug("Controller={},method={},请求参数={}", joinPoint.getTarget().getClass().getName(), + joinPoint.getSignature().getName(), logMsg); + } else { + logger.info("Controller={},method={},开始请求", joinPoint.getTarget().getClass().getName(), + joinPoint.getSignature().getName()); + } + + long begTime = System.currentTimeMillis(); + Object value = joinPoint.proceed(); + long invokeTime = System.currentTimeMillis() - begTime; + + if (logger.isDebugEnabled()) { + logger.debug("Controller={},method={},返回参数={}", joinPoint.getTarget().getClass().getName(), + joinPoint.getSignature().getName(), JsonUtil.toJsonString(value)); + } else { + logger.info("Controller={},method={},响应成功", joinPoint.getTarget().getClass().getName(), + joinPoint.getSignature().getName()); + } + + logger.info("Controller={},method={},响应时间={}ms", joinPoint.getTarget().getClass().getName(), + joinPoint.getSignature().getName(), invokeTime); + + return value; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java new file mode 100644 index 0000000..b161c0e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java @@ -0,0 +1,190 @@ +package com.lframework.starter.web.core.aop; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.oplog.OpLogType; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.core.utils.SpelUtil; +import com.lframework.starter.web.inner.vo.oplogs.CreateOpLogsVo; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.expression.EvaluationContext; + +import java.util.*; + +/** + * OpLog切面 + * + * @author zmj + */ +@Slf4j +@Aspect +public class OpLogAspector { + + @Pointcut("@annotation(com.lframework.starter.web.core.annotations.oplog.OpLog)") + public void opLogCutPoint() { + + } + + @Around(value = "opLogCutPoint()") + public Object opLog(ProceedingJoinPoint joinPoint) throws Throwable { + + try { + //生成logId,多层嵌套时,隔离不同bean的数据 + String logId = IdUtil.getUUID(); + OpLogUtil.init(logId); + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + Object value = joinPoint.proceed(); + + if (currentUser == null) { + currentUser = SecurityUtil.getCurrentUser(); + } + + if (currentUser != null) { + try { + //获取方法的参数名和参数值 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + List paramNameList = Arrays.asList(methodSignature.getParameterNames()); + List paramList = Arrays.asList(joinPoint.getArgs()); + + //将方法的参数名和参数值一一对应的放入上下文中 + EvaluationContext ctx = SpelUtil.buildContext(); + for (int i = 0; i < paramNameList.size(); i++) { + ctx.setVariable(paramNameList.get(i), paramList.get(i)); + } + + //将返回值放入上下文中 + ctx.setVariable("_result", value); + + Map variables = OpLogUtil.getVariables(); + if (!CollectionUtil.isEmpty(variables)) { + variables.forEach((k, v) -> { + ctx.setVariable(k, v); + }); + } + + // 解析SpEL表达式获取结果 + Object[] params; + OpLog opLog = methodSignature.getMethod().getAnnotation(OpLog.class); + if (!ArrayUtil.isEmpty(opLog.params())) { + params = new Object[opLog.params().length]; + for (int i = 0; i < opLog.params().length; i++) { + String param = opLog.params()[i]; + Object p = SpelUtil.parse(param, ctx); + params[i] = p; + } + } else { + params = new String[0]; + } + + List paramsList = new ArrayList<>(); + //循环format + if (opLog.loopFormat() && Arrays.stream(params).anyMatch(t -> t instanceof Collection)) { + String[] strParams = new String[params.length]; + //collectionIndex的索引 + List collectionIndexes = new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + //先处理不是Collection的元素 + if (params[i] instanceof Collection) { + collectionIndexes.add(i); + continue; + } + strParams[i] = params[i] == null ? null : params[i].toString(); + } + + paramsList.add(strParams); + + if (!CollectionUtil.isEmpty(collectionIndexes)) { + //将所有的collection组合,例:collection1的size是2 collection2的size是3 则组合后的条数为2*3=6 + for (Integer collectionIndex : collectionIndexes) { + List tmpParamsList = new ArrayList<>(); + for (String[] paramsArr : paramsList) { + + Collection collection = (Collection) params[collectionIndex]; + for (Object o : collection) { + String[] tmp = new String[paramsArr.length]; + for (int j = 0; j < paramsArr.length; j++) { + if (j == collectionIndex) { + tmp[j] = o == null ? null : o.toString(); + } else { + tmp[j] = paramsArr[j]; + } + } + + tmpParamsList.add(tmp); + } + } + + paramsList.clear(); + paramsList.addAll(tmpParamsList); + } + } else { + paramsList.add(strParams); + } + } else { + String[] strParams = new String[params.length]; + for (int i = 0; i < params.length; i++) { + strParams[i] = params[i] == null ? null : params[i].toString(); + } + paramsList.add(strParams); + } + + List createOpLogsVoList = new ArrayList<>(); + for (String[] strArr : paramsList) { + String extra = OpLogUtil.getExtra(); + if (extra == null) { + if (opLog.autoSaveParams()) { + // 没有手动指定extra + if (CollectionUtil.isNotEmpty(paramNameList)) { + if (paramNameList.size() == 1) { + // 只有一个参数 + OpLogUtil.setExtra(ctx.lookupVariable(paramNameList.get(0))); + } else { + // 多个参数 + Map paramMap = new LinkedHashMap<>(paramNameList.size(), 1); + for (String paramName : paramNameList) { + paramMap.put(paramName, ctx.lookupVariable(paramName)); + } + OpLogUtil.setExtra(paramMap); + } + } + extra = OpLogUtil.getExtra(); + } + } + + String finalExtra = extra; + CreateOpLogsVo vo = new CreateOpLogsVo(); + vo.setName(StringUtil.format(opLog.name(), strArr)); + OpLogType opLogTypeBean = ApplicationUtil.getBean(opLog.type()); + vo.setLogType(opLogTypeBean.getCode()); + vo.setExtra(finalExtra); + vo.setIp(currentUser.getIp()); + createOpLogsVoList.add(vo); + } + + if (CollectionUtil.isNotEmpty(createOpLogsVoList)) { + OpLogUtil.addLogs(createOpLogsVoList); + } + OpLogUtil.submitLog(currentUser); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + return value; + } finally { + OpLogUtil.clear(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpenApiAspect.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpenApiAspect.java new file mode 100644 index 0000000..aa71fb5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpenApiAspect.java @@ -0,0 +1,75 @@ +package com.lframework.starter.web.core.aop; + +import com.lframework.starter.common.exceptions.impl.AccessDeniedException; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.openapi.OpenApi; +import com.lframework.starter.web.core.components.sign.CheckSignFactory; +import com.lframework.starter.web.core.components.sign.CheckSignHandler; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.vo.openapi.OpenApiReqVo; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * OpenApi切面 + * + * @author zmj + */ +@Aspect +public class OpenApiAspect { + + @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)) && @annotation(com.lframework.starter.web.core.annotations.openapi.OpenApi) && execution(public * *(..))") + public void openApiPointCut() { + + } + + @Around(value = "openApiPointCut()") + public Object openApi(ProceedingJoinPoint joinPoint) throws Throwable { + + Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass()); + + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + + OpenApi openApi = signature.getMethod().getAnnotation(OpenApi.class); + + Object[] args = joinPoint.getArgs(); + + CheckSignFactory checkSignFactory = ApplicationUtil.getBean(CheckSignFactory.class); + CheckSignHandler checkSignHandler = checkSignFactory.getInstance(); + + if (openApi.sign()) { + if (ArrayUtil.isEmpty(args)) { + throw new AccessDeniedException("验签失败!"); + } + List reqList = Arrays.stream(args).filter(t -> t instanceof OpenApiReqVo) + .map(t -> (OpenApiReqVo) t).collect(Collectors.toList()); + + if (CollectionUtil.isEmpty(reqList)) { + throw new AccessDeniedException("验签失败!"); + } + for (OpenApiReqVo req : reqList) { + if (!checkSignHandler.check(req)) { + throw new AccessDeniedException("验签失败!"); + } + + checkSignHandler.setTenantId(req); + } + } + + // 如果openApi.sign() 为false,那么需要接口自己设置TenantId + + Object value = joinPoint.proceed(); + + return value; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/OrderTimeLineLogAspect.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OrderTimeLineLogAspect.java new file mode 100644 index 0000000..f3f0af9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OrderTimeLineLogAspect.java @@ -0,0 +1,223 @@ +package com.lframework.starter.web.core.aop; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.DefaultSettingProperties; +import com.lframework.starter.web.core.annotations.timeline.OrderTimeLineLog; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.SpelUtil; +import com.lframework.starter.web.inner.entity.OrderTimeLine; +import com.lframework.starter.web.inner.service.OrderTimeLineService; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.expression.EvaluationContext; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * 单据时间轴切面 + * + * @author zmj + */ +@Slf4j +@Aspect +public class OrderTimeLineLogAspect { + + @Autowired + private DefaultSettingProperties defaultSettingProperties; + + private final ThreadLocal POOL = new InheritableThreadLocal<>(); + + @Pointcut("@annotation(com.lframework.starter.web.core.annotations.timeline.OrderTimeLineLog)") + public void orderTimeLineLogCutPoint() { + + } + + @Around(value = "orderTimeLineLogCutPoint()") + public Object orderTimeLineLog(ProceedingJoinPoint joinPoint) throws Throwable { + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + String curUserId = + currentUser == null ? defaultSettingProperties.getDefaultUserId() : currentUser.getId(); + String curUserName = + currentUser == null ? defaultSettingProperties.getDefaultUserName() : currentUser.getName(); + + Object value = null; + + try { + if (POOL.get() != null) { + POOL.set(POOL.get() + 1); + // 如果出现嵌套,那么以最外层的为准,不进行嵌套隔离 + return joinPoint.proceed(); + } + + POOL.set(1); + + value = joinPoint.proceed(); + + try { + //获取方法的参数名和参数值 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + List paramNameList = Arrays.asList(methodSignature.getParameterNames()); + List paramList = Arrays.asList(joinPoint.getArgs()); + + //将方法的参数名和参数值一一对应的放入上下文中 + EvaluationContext ctx = SpelUtil.buildContext(); + for (int i = 0; i < paramNameList.size(); i++) { + ctx.setVariable(paramNameList.get(i), paramList.get(i)); + } + + //将返回值放入上下文中 + ctx.setVariable("_result", value); + + // 解析SpEL表达式获取结果 + Object[] params; + OrderTimeLineLog orderTimeLineLog = methodSignature.getMethod() + .getAnnotation(OrderTimeLineLog.class); + if (!ArrayUtil.isEmpty(orderTimeLineLog.params())) { + params = new Object[orderTimeLineLog.params().length]; + for (int i = 0; i < orderTimeLineLog.params().length; i++) { + String param = orderTimeLineLog.params()[i]; + Object p = SpelUtil.parse(param, ctx); + params[i] = p; + } + } else { + params = new String[0]; + } + + List paramsList = new ArrayList<>(); + //循环format + if (orderTimeLineLog.loopFormat() && Arrays.stream(params) + .anyMatch(t -> t instanceof Collection)) { + String[] strParams = new String[params.length]; + //collectionIndex的索引 + List collectionIndexes = new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + //先处理不是Collection的元素 + if (params[i] instanceof Collection) { + collectionIndexes.add(i); + continue; + } + strParams[i] = params[i] == null ? null : params[i].toString(); + } + + paramsList.add(strParams); + + if (!CollectionUtil.isEmpty(collectionIndexes)) { + //将所有的collection组合,例:collection1的size是2 collection2的size是3 则组合后的条数为2*3=6 + for (Integer collectionIndex : collectionIndexes) { + List tmpParamsList = new ArrayList<>(); + for (String[] paramsArr : paramsList) { + + Collection collection = (Collection) params[collectionIndex]; + for (Object o : collection) { + String[] tmp = new String[paramsArr.length]; + for (int j = 0; j < paramsArr.length; j++) { + if (j == collectionIndex) { + tmp[j] = o == null ? null : o.toString(); + } else { + tmp[j] = paramsArr[j]; + } + } + + tmpParamsList.add(tmp); + } + } + + paramsList.clear(); + paramsList.addAll(tmpParamsList); + } + } else { + paramsList.add(strParams); + } + } else { + String[] strParams = new String[params.length]; + for (int i = 0; i < params.length; i++) { + strParams[i] = params[i] == null ? null : params[i].toString(); + } + paramsList.add(strParams); + } + + Object[] orderIds; + if (!ArrayUtil.isEmpty(orderTimeLineLog.orderId())) { + orderIds = new Object[orderTimeLineLog.orderId().length]; + for (int i = 0; i < orderTimeLineLog.orderId().length; i++) { + String orderId = orderTimeLineLog.orderId()[i]; + Object p = SpelUtil.parse(orderId, ctx); + orderIds[i] = p; + } + } else { + orderIds = new String[0]; + } + + List orderIdList = new ArrayList<>(); + for (Object orderId : orderIds) { + if (orderId == null) { + continue; + } + + if (orderId instanceof Collection) { + Collection c = (Collection) orderId; + CollectionUtil.forEach(c, (item, index) -> orderIdList.add(item.toString())); + } + + orderIdList.add(orderId.toString()); + } + + if (orderTimeLineLog.delete()) { + for (String orderId : orderIdList) { + // 这里不异步,在同事务内执行 + OrderTimeLineService orderTimeLineService = ApplicationUtil.getBean( + OrderTimeLineService.class); + orderTimeLineService.deleteByOrder(orderId); + orderTimeLineService.cleanCacheByKey(orderId); + } + } else { + List records = new ArrayList<>(); + OrderTimeLineService orderTimeLineService = ApplicationUtil.getBean( + OrderTimeLineService.class); + for (String[] strArr : paramsList) { + for (String orderId : orderIdList) { + OrderTimeLine record = new OrderTimeLine(); + record.setId(IdUtil.getId()); + record.setOrderId(orderId); + record.setContent(StringUtil.format(orderTimeLineLog.name(), strArr)); + record.setCreateBy(curUserName); + record.setCreateById(curUserId); + record.setBizType(ApplicationUtil.getBean(orderTimeLineLog.type()).getCode()); + records.add(record); + } + } + if (CollectionUtil.isNotEmpty(records)) { + // 这里不异步,在同事务内执行 + orderTimeLineService.saveBatch(records); + orderTimeLineService.cleanCacheByKeys(orderIdList); + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } finally { + if (POOL.get() != null) { + POOL.set(POOL.get() - 1); + if (POOL.get() <= 0) { + POOL.remove(); + } + } + } + return value; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/PermissionAspect.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/PermissionAspect.java new file mode 100644 index 0000000..644f977 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/PermissionAspect.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.core.aop; + +import com.lframework.starter.common.exceptions.impl.AccessDeniedException; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.security.CheckPermissionHandler; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 鉴权切面 + * + * @author zmj + */ +@Aspect +public class PermissionAspect { + + @Autowired + private CheckPermissionHandler checkPermissionHandler; + + @Pointcut("@annotation(com.lframework.starter.web.core.annotations.security.HasPermission) && execution(public * *(..))") + public void permissionPointCut() { + + } + + @Around(value = "permissionPointCut()") + public Object permission(ProceedingJoinPoint joinPoint) throws Throwable { + + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + + HasPermission hasPermission = signature.getMethod().getAnnotation(HasPermission.class); + + if (!checkPermissionHandler.valid(hasPermission.calcType(), hasPermission.requirePlatform(), hasPermission.value())) { + throw new AccessDeniedException("暂无权限,请联系系统管理员!"); + } + + Object value = joinPoint.proceed(); + + return value; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/bo/BaseBo.java b/web-starter/src/main/java/com/lframework/starter/web/core/bo/BaseBo.java new file mode 100644 index 0000000..bc4986e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/bo/BaseBo.java @@ -0,0 +1,61 @@ +package com.lframework.starter.web.core.bo; + +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.utils.BoUtil; + +import java.io.Serializable; + +/** + * BaseBo + * + * @param + * @author zmj + */ +public abstract class BaseBo implements Serializable, SuperBo { + + private static final long serialVersionUID = 1L; + + public BaseBo() { + + } + + public BaseBo(T dto) { + + this.init(dto); + } + + protected void init(T dto) { + if (dto != null) { + this.convert(dto); + + this.afterInit(dto); + } + } + + /** + * 将dto转为bo + * + * @param dto + */ + public BaseBo convert(T dto) { + + return convert(dto, (SFunction[]) null); + } + + public BaseBo convert(T dto, SFunction... columns) { + + BoUtil.convert(dto, this, columns); + + return this; + } + + /** + * 初始化后置处理 + * + * @param dto + */ + protected void afterInit(T dto) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/bo/ExcelImportBo.java b/web-starter/src/main/java/com/lframework/starter/web/core/bo/ExcelImportBo.java new file mode 100644 index 0000000..75f194a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/bo/ExcelImportBo.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.core.bo; + +import com.lframework.starter.web.core.dto.VoidDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class ExcelImportBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 当前进度(条数) + */ + @Schema(description = "当前进度(条数)") + private Integer process = 0; + + /** + * 成功进度(条数) + */ + @Schema(description = "成功进度(条数)") + private Integer successProcess = 0; + + /** + * 提示信息 + */ + @Schema(description = "提示信息") + private List tipMsgs = new ArrayList<>(); + + /** + * 是否存在错误 + */ + @Schema(description = "是否存在错误") + private Boolean hasError = Boolean.FALSE; + + /** + * 业务完成 + */ + @Schema(description = "业务完成") + private Boolean finished = Boolean.FALSE; + + /** + * 数据 + */ + @Schema(description = "数据") + private Object data; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/bo/SuperBo.java b/web-starter/src/main/java/com/lframework/starter/web/core/bo/SuperBo.java new file mode 100644 index 0000000..3466d2e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/bo/SuperBo.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.core.bo; + +/** + * SuperBo 所有基于Dto的Bo可以继承BaseBo,不基于Dto的Bo无法继承BaseBo可以直接实现SuperBo + */ +public interface SuperBo { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/cache/CacheVariables.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/cache/CacheVariables.java new file mode 100644 index 0000000..5c3d4ba --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/cache/CacheVariables.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.core.components.cache; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; + +/** + * 缓存变量 + */ +public class CacheVariables { + + /** + * 租户ID + * + * @return + */ + public static String tenantId() { + if (!TenantUtil.enableTenant()) { + return StringPool.EMPTY_STR; + } + Integer tenantId = TenantContextHolder.getTenantId(); + if (tenantId == null) { + return StringPool.EMPTY_STR; + } + + return String.valueOf(tenantId) + "::"; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/captcha/CaptchaValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/captcha/CaptchaValidator.java new file mode 100644 index 0000000..11b6eae --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/captcha/CaptchaValidator.java @@ -0,0 +1,53 @@ +package com.lframework.starter.web.core.components.captcha; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.redis.RedisHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 验证码校验 + */ +@Slf4j +public class CaptchaValidator { + + @Autowired + private RedisHandler redisHandler; + + /** + * 校验验证码 如果未通过校验则会抛出异常 + * + * @param sn + * @param captcha + */ + public void validate(String sn, String captcha) { + + log.debug("开始校验验证码,sn={}, captcha={}", sn, captcha); + + if (StringUtil.isEmpty(sn) || StringUtil.isEmpty(captcha)) { + log.debug("sn、captcha为空,校验不通过"); + throw new DefaultClientException("验证码错误,请重新输入!"); + } + + String captchaKey = StringUtil.format(StringPool.LOGIN_CAPTCHA_KEY, sn); + try { + String oriCaptcha = (String) redisHandler.get(captchaKey); + log.debug("从redis中取出正确的captcha={}", oriCaptcha); + + if (StringUtil.isEmpty(oriCaptcha)) { + log.debug("验证码已过期"); + throw new DefaultClientException("验证码已过期,请重新输入!"); + } + + if (!StringUtil.equalsIgnoreCase(oriCaptcha, captcha)) { + log.debug("验证码错误"); + throw new DefaultClientException("验证码错误,请重新输入!"); + } + } finally { + // 无论校验是否通过,都需要重新生成验证码 + redisHandler.del(captchaKey); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelEventListener.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelEventListener.java new file mode 100644 index 0000000..65c3ebf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelEventListener.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.components.excel; + +import com.alibaba.excel.event.AnalysisEventListener; +import lombok.extern.slf4j.Slf4j; + +/** + * Excel事件监听器 用于解析Excel + * + * @param + * @author zmj + */ +@Slf4j +public abstract class ExcelEventListener extends AnalysisEventListener { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelImportListener.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelImportListener.java new file mode 100644 index 0000000..743a573 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelImportListener.java @@ -0,0 +1,264 @@ +package com.lframework.starter.web.core.components.excel; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.context.AnalysisContext; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.excel.ExcelRequired; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.ExcelImportUtil; +import com.lframework.starter.web.core.utils.TransactionUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.TransactionStatus; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Excel导入监听器 主要是用于单表头的Excel文件导入,Model的每个字段都需要标注@ExcelProperty并且不指定index,order属性 + */ +@Slf4j +public abstract class ExcelImportListener extends ExcelEventListener { + + private final SysConfService sysConfService = ApplicationUtil.getBean( + SysConfService.class); + /** + * 数据 + */ + @Getter + protected List datas = new ArrayList<>(); + /** + * 总行数 + */ + protected int totalRows; + /** + * 导入任务ID + */ + protected String taskId; + /** + * 限制的最大行数 + */ + private Integer limitRows; + /** + * 已解析总行数 + */ + private int currentRows; + /** + * 是否存在错误 + */ + private boolean hasError; + /** + * 是否需要中断 + */ + private boolean interrupt; + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + this.totalRows = Math.max(0, context.readSheetHolder().getApproximateTotalRowNumber() - 1); + if (limitRows == null) { + this.limitRows = Integer.valueOf( + sysConfService.findRequiredByKey("excel-import.max-size")); + } + + if (this.totalRows == 0) { + this.interrupt = true; + throw new DefaultClientException("导入文件不能为空,请检查"); + } + + if (this.totalRows > limitRows) { + this.interrupt = true; + throw new DefaultClientException("一次最多允许导入" + limitRows + "条"); + } + Class clazz = context.readWorkbookHolder().getClazz(); + if (clazz != null) { + this.checkHeadMap(headMap, clazz); + } + + this.doInvokeHeadMap(headMap, context); + } + + protected void checkHeadMap(Map headMap, Class clazz) { + List fieldNameList = new ArrayList<>(); + Field[] fields = ReflectUtil.getFields(clazz); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); + if (excelProperty != null) { + String headerName = + ArrayUtil.isEmpty(excelProperty.value()) ? null : excelProperty.value()[0]; + fieldNameList.add(headerName); + } + } + + for (int i = 0; i < fieldNameList.size(); i++) { + String fieldName = fieldNameList.get(i); + if (!StringUtil.equals(fieldName, headMap.get(i))) { + throw new DefaultClientException("第" + (i + 1) + "列应为【" + fieldName + "】,请检查文件"); + } + } + } + + protected void doInvokeHeadMap(Map headMap, AnalysisContext context) { + } + + @Override + public void invoke(T data, AnalysisContext context) { + + if (this.interrupt) { + return; + } + + this.currentRows++; + + this.setProcess(this.totalRows == 0 ? 100 + : Math.min(NumberUtil.mul(NumberUtil.div(this.currentRows, this.totalRows), 100).intValue(), + 100)); + + if (!this.hasError) { + this.datas.add(data); + + // 校验必填项 + this.checkFields(data, context); + + this.doInvoke(data, context); + } + } + + private void checkFields(T data, AnalysisContext context) { + if (data == null) { + return; + } + + Field[] fields = ReflectUtil.getFields(data.getClass()); + for (Field field : fields) { + ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); + if (excelRequired == null) { + continue; + } + + ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); + if (excelIgnore != null) { + continue; + } + + Object val = ReflectUtil.getFieldValue(data, field); + + if (val == null || ((val instanceof CharSequence) && StringUtil.isEmpty( + (CharSequence) val))) { + String fieldName = null; + fieldName = field.getName(); + ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); + if (excelProperty != null) { + String[] fieldNames = excelProperty.value(); + fieldName = ArrayUtil.join(fieldNames, "-"); + } + + throw new DefaultClientException( + "第" + (context.readRowHolder().getRowIndex()) + "行“" + fieldName + "”不能为空"); + } + } + } + + protected abstract void doInvoke(T data, AnalysisContext context); + + protected void setProcess(Integer process) { + ExcelImportUtil.setProcess(this.taskId, process); + } + + protected void setSuccessProcess(Integer process) { + ExcelImportUtil.setSuccessProcess(this.taskId, process); + } + + protected void setSuccessProcessByIndex(Integer curIndex) { + this.setSuccessProcess(this.totalRows == 0 ? 100 + : Math.min(NumberUtil.mul(NumberUtil.div(curIndex + 1, this.totalRows), 100).intValue(), + 100)); + } + + protected boolean addTipMsg(String msg) { + if (StringUtil.isBlank(msg)) { + return true; + } + + return ExcelImportUtil.addTipMsg(this.taskId, msg); + } + + @Override + public void onException(Exception exception, AnalysisContext context) throws Exception { + log.error(exception.getMessage(), exception); + if (!this.addTipMsg(exception.getMessage())) { + this.interrupt = true; + } + this.hasError = true; + ExcelImportUtil.setHasError(this.taskId, true); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + try { + if (this.hasError || this.interrupt) { + return; + } + + this.setProcess(100); + + if (this.requireTransaction()) { + TransactionStatus transactionStatus = TransactionUtil.getTransaction(); + try { + this.afterAllAnalysed(context); + TransactionUtil.commit(transactionStatus); + } catch (Throwable throwable) { + TransactionUtil.rollback(transactionStatus); + if (throwable instanceof Exception) { + try { + this.onException((Exception) throwable, context); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + throw throwable; + } + } else { + this.afterAllAnalysed(context); + } + try { + this.doComplete(); + } catch (Exception e) { + try { + this.onException(e, context); + } catch (Exception ex) { + throw new RuntimeException(e); + } + } + } finally { + ExcelImportUtil.finished(this.taskId); + } + } + + /** + * 事务需要开启事务 + * + * @return + */ + protected boolean requireTransaction() { + return true; + } + + protected abstract void afterAllAnalysed(AnalysisContext context); + + public void setTaskId(String taskId) { + this.taskId = taskId; + + ExcelImportUtil.initUploadTask(taskId); + } + + protected abstract void doComplete(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelModel.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelModel.java new file mode 100644 index 0000000..d5f9efd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/ExcelModel.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.core.components.excel; + +/** + * Excel Bean + * + * @author zmj + */ +public interface ExcelModel { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/RequiredFieldStyleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/RequiredFieldStyleHandler.java new file mode 100644 index 0000000..0c447d8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/excel/RequiredFieldStyleHandler.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.core.components.excel; + +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import org.apache.poi.ss.usermodel.*; + +import java.util.Set; + +/** + * 某些列头(必填)变红 + */ +public class RequiredFieldStyleHandler implements CellWriteHandler { + + private final Set requiredFields; + + public RequiredFieldStyleHandler(Set requiredFields) { + this.requiredFields = requiredFields; + } + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + if (context.getHead() == null) { + return; + } + + Cell cell = context.getCell(); + Workbook workbook = context.getWriteWorkbookHolder().getWorkbook(); + + String fieldName = context.getHeadData().getFieldName(); + + if (requiredFields != null && requiredFields.contains(fieldName)) { + + CellStyle style = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setColor(Font.COLOR_RED); + font.setBold(true); + + style.setFont(font); + cell.setCellStyle(style); + } + } +} \ No newline at end of file diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/GenerateCodeFactory.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/GenerateCodeFactory.java new file mode 100644 index 0000000..33a5450 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/GenerateCodeFactory.java @@ -0,0 +1,112 @@ +package com.lframework.starter.web.core.components.generator; + + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.JsonUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 单号生成器Factory + * + * @author zmj + */ +public class GenerateCodeFactory { + + public static String generate(String configStr) { + return generate(getRules(configStr)); + } + + public static String generate(List ruleList) { + Map handlerMap = ApplicationUtil.getBeansOfType( + GenerateCodeRuleHandler.class); + Collection handlerList = handlerMap.values(); + + StringBuilder builder = new StringBuilder(); + for (GenerateCodeRule rule : ruleList) { + for (GenerateCodeRuleHandler handler : handlerList) { + if (handler.match(rule)) { + builder.append(handler.generate(rule)); + } + } + } + + return builder.toString(); + } + + public static String generateExample(String configStr) { + return generateExample(getRules(configStr)); + } + + public static String generateExample(List ruleList) { + Map handlerMap = ApplicationUtil.getBeansOfType( + GenerateCodeRuleHandler.class); + Collection handlerList = handlerMap.values(); + + StringBuilder builder = new StringBuilder(); + for (GenerateCodeRule rule : ruleList) { + for (GenerateCodeRuleHandler handler : handlerList) { + if (handler.match(rule)) { + builder.append(handler.generateExample(rule)); + } + } + } + + return builder.toString(); + } + + public static List getHandlers(String configStr) { + + Map handlerMap = ApplicationUtil.getBeansOfType( + GenerateCodeRuleHandler.class); + + JSONArray configArr = JsonUtil.parseArray(configStr); + + List results = new ArrayList<>(); + + for (int i = 0; i < configArr.size(); i++) { + JSONObject config = configArr.getJSONObject(i); + + Integer type = config.getInt("type"); + if (type == null) { + throw new DefaultSysException("configStr {} 配置信息错误!"); + } + + Collection handlerList = handlerMap.values(); + for (GenerateCodeRuleHandler handler : handlerList) { + if (handler.match(type)) { + results.add(handler); + } + } + } + + if (results.isEmpty()) { + throw new DefaultSysException("configStr {} 配置信息错误!"); + } + + return results; + } + + public static List getRules(String configStr) { + List ruleHandlerList = GenerateCodeFactory.getHandlers( + configStr); + JSONArray configArr = JsonUtil.parseArray(configStr); + + List results = new ArrayList<>(); + + for (int i = 0; i < ruleHandlerList.size(); i++) { + GenerateCodeRuleHandler ruleHandler = ruleHandlerList.get(i); + results.add(ruleHandler.parseRule(configArr.getStr(i))); + } + + return results; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/GenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/GenerateCodeRuleHandler.java new file mode 100644 index 0000000..ee880b2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/GenerateCodeRuleHandler.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.core.components.generator.handler; + +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; + +public interface GenerateCodeRuleHandler { + + /** + * 根据规则类型匹配 + * + * @param ruleType + * @return + */ + boolean match(Integer ruleType); + + /** + * 根据规则匹配 + * @param rule + * @return + */ + boolean match(GenerateCodeRule rule); + + /** + * 生成单号 + * + * @param rule 规则数据 + * @return + */ + String generate(T rule); + + /** + * 生成示例单号 + * + * @param rule + * @return + */ + String generateExample(T rule); + + /** + * 解析规则 + * + * @param json + * @return + */ + T parseRule(String json); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CurrentDateTimeRuleGenerateCodeHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CurrentDateTimeRuleGenerateCodeHandler.java new file mode 100644 index 0000000..5d513d2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CurrentDateTimeRuleGenerateCodeHandler.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.CurrentDateTimeGenerateCodeRule; +import com.lframework.starter.web.core.utils.JsonUtil; + +import java.time.LocalDateTime; + +public class CurrentDateTimeRuleGenerateCodeHandler implements + GenerateCodeRuleHandler { + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && ruleType == 1; + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof CurrentDateTimeGenerateCodeRule; + } + + @Override + public String generate(CurrentDateTimeGenerateCodeRule rule) { + return DateUtil.formatDateTime(LocalDateTime.now(), rule.getPattern()); + } + + @Override + public String generateExample(CurrentDateTimeGenerateCodeRule rule) { + return generate(rule); + } + + @Override + public CurrentDateTimeGenerateCodeRule parseRule(String json) { + CurrentDateTimeGenerateCodeRule rule = JsonUtil.parseObject(json, + CurrentDateTimeGenerateCodeRule.class); + if (StringUtil.isBlank(rule.getPattern())) { + rule.setPattern("yyyyMMddHHmmss"); + } + return rule; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CustomRandomStrGenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CustomRandomStrGenerateCodeRuleHandler.java new file mode 100644 index 0000000..797cd67 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/CustomRandomStrGenerateCodeRuleHandler.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import cn.hutool.core.util.RandomUtil; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.CustomRandomStrGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.RandomIntGenerateCodeRule; +import com.lframework.starter.web.core.utils.JsonUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class CustomRandomStrGenerateCodeRuleHandler implements + GenerateCodeRuleHandler { + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && (ruleType == 2 || ruleType == 4); + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof CustomRandomStrGenerateCodeRule; + } + + @Override + public String generate(CustomRandomStrGenerateCodeRule rule) { + Integer len = rule.getLen() == null ? 1 : rule.getLen(); + char[] charArr = rule.getPool().toCharArray(); + List pool = new ArrayList<>(); + for (char c : charArr) { + pool.add(String.valueOf(c)); + } + List eles = RandomUtil.randomEles(pool, len); + return StringUtil.join(StringPool.EMPTY_STR, eles); + } + + @Override + public String generateExample(CustomRandomStrGenerateCodeRule rule) { + return generate(rule); + } + + @Override + public CustomRandomStrGenerateCodeRule parseRule(String json) { + Map tmpMap = JsonUtil.parseMap(json, String.class, String.class); + CustomRandomStrGenerateCodeRule rule; + if ("2".equals(tmpMap.get("type"))) { + rule = JsonUtil.parseObject(json, + CustomRandomStrGenerateCodeRule.class); + } else { + rule = JsonUtil.parseObject(json, + RandomIntGenerateCodeRule.class); + } + + if (rule.getLen() == null) { + rule.setLen(1); + } + + return rule; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/FlowGenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/FlowGenerateCodeRuleHandler.java new file mode 100644 index 0000000..c0b4d9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/FlowGenerateCodeRuleHandler.java @@ -0,0 +1,114 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.locker.LockBuilder; +import com.lframework.starter.common.locker.Locker; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.FlowGenerateCodeRule; +import com.lframework.starter.web.core.components.redis.RedisHandler; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDate; + +public class FlowGenerateCodeRuleHandler implements GenerateCodeRuleHandler { + + private static final String LOCK_KEY = "flow_generator_index_"; + + @Autowired + private RedisHandler redisHandler; + + @Autowired + private LockBuilder lockBuilder; + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && ruleType == 3; + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof FlowGenerateCodeRule; + } + + @Override + public String generate(FlowGenerateCodeRule rule) { + Integer codeLen = rule.getLen() == null ? 1 : rule.getLen(); + String lockerName = LOCK_KEY + rule.getKey(); + String redisKey = + lockerName + "_" + (TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() + : "noTenant") + (rule.getExpireType() == 0 ? "_" + DateUtil.formatDate(LocalDate.now()) + : ""); + Locker locker = lockBuilder.buildLocker(redisKey + "_Locker", 60000L, 5000L); + long no; + + if (locker.lock()) { + try { + no = redisHandler.incr(redisKey, rule.getStep()); + } finally { + locker.unLock(); + } + } else { + throw new DefaultClientException("生成单号失败,请稍后重试!"); + } + redisHandler.expire(redisKey, + (rule.getExpireType() == 0 ? 24 * 60 * 60 : rule.getExpireSeconds()) * 1000L); + + String noStr = String.valueOf(no); + if (noStr.length() > codeLen) { + throw new DefaultSysException("单号超长!"); + } + + StringBuilder builder = new StringBuilder(); + for (int i = 0, len = codeLen - noStr.length(); i < len; i++) { + builder.append("0"); + } + + return builder.append(noStr).toString(); + } + + @Override + public String generateExample(FlowGenerateCodeRule rule) { + Integer codeLen = rule.getLen() == null ? 1 : rule.getLen(); + String noStr = "1"; + StringBuilder builder = new StringBuilder(); + for (int i = 0, len = codeLen - noStr.length(); i < len; i++) { + builder.append("0"); + } + + return builder.append(noStr).toString(); + } + + @Override + public FlowGenerateCodeRule parseRule(String json) { + FlowGenerateCodeRule rule = JsonUtil.parseObject(json, FlowGenerateCodeRule.class); + if (StringUtil.isBlank(rule.getKey())) { + rule.setKey(IdUtil.getUUID()); + } + + if (rule.getLen() == null) { + rule.setLen(10); + } + + if (rule.getStep() == null) { + rule.setStep(1); + } + + if (rule.getExpireType() == null) { + rule.setExpireType(0); + } + + if (rule.getExpireSeconds() == null) { + rule.setExpireSeconds(24 * 60 * 60L); + } + + return rule; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/SnowFlakeGenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/SnowFlakeGenerateCodeRuleHandler.java new file mode 100644 index 0000000..bb1374c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/SnowFlakeGenerateCodeRuleHandler.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import com.lframework.starter.common.utils.IdWorker; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.SnowFlakeGenerateCodeRule; +import org.springframework.beans.factory.annotation.Autowired; + +public class SnowFlakeGenerateCodeRuleHandler implements + GenerateCodeRuleHandler { + + @Autowired + private IdWorker idWorker; + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && ruleType == 5; + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof SnowFlakeGenerateCodeRule; + } + + @Override + public String generate(SnowFlakeGenerateCodeRule rule) { + return idWorker.nextIdStr(); + } + + @Override + public String generateExample(SnowFlakeGenerateCodeRule rule) { + return generate(rule); + } + + @Override + public SnowFlakeGenerateCodeRule parseRule(String json) { + return new SnowFlakeGenerateCodeRule(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/StaticStrGenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/StaticStrGenerateCodeRuleHandler.java new file mode 100644 index 0000000..c8bd876 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/StaticStrGenerateCodeRuleHandler.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.StaticStrGenerateCodeRule; +import com.lframework.starter.web.core.utils.JsonUtil; + +public class StaticStrGenerateCodeRuleHandler implements + GenerateCodeRuleHandler { + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && ruleType == 6; + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof StaticStrGenerateCodeRule; + } + + @Override + public String generate(StaticStrGenerateCodeRule rule) { + + return rule.getVal(); + } + + @Override + public String generateExample(StaticStrGenerateCodeRule rule) { + return generate(rule); + } + + @Override + public StaticStrGenerateCodeRule parseRule(String json) { + StaticStrGenerateCodeRule rule = JsonUtil.parseObject(json, StaticStrGenerateCodeRule.class); + + Assert.notNull(rule.getVal()); + + return rule; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/UUIDGenerateCodeRuleHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/UUIDGenerateCodeRuleHandler.java new file mode 100644 index 0000000..4a49194 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/handler/impl/UUIDGenerateCodeRuleHandler.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.generator.handler.impl; + +import com.lframework.starter.web.core.components.generator.handler.GenerateCodeRuleHandler; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.impl.UUIDGenerateCodeRule; +import com.lframework.starter.web.core.utils.IdUtil; + +public class UUIDGenerateCodeRuleHandler implements GenerateCodeRuleHandler { + + @Override + public boolean match(Integer ruleType) { + return ruleType != null && ruleType == 7; + } + + @Override + public boolean match(GenerateCodeRule rule) { + return rule instanceof UUIDGenerateCodeRule; + } + + @Override + public String generate(UUIDGenerateCodeRule rule) { + return IdUtil.getUUID(); + } + + @Override + public String generateExample(UUIDGenerateCodeRule rule) { + return generate(rule); + } + + @Override + public UUIDGenerateCodeRule parseRule(String json) { + return new UUIDGenerateCodeRule(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/AbstractGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/AbstractGenerateCodeRule.java new file mode 100644 index 0000000..4736537 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/AbstractGenerateCodeRule.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.core.components.generator.rule; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public abstract class AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 类型 + */ + private String type; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/GenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/GenerateCodeRule.java new file mode 100644 index 0000000..5850d53 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/GenerateCodeRule.java @@ -0,0 +1,5 @@ +package com.lframework.starter.web.core.components.generator.rule; + +public interface GenerateCodeRule { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CurrentDateTimeGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CurrentDateTimeGenerateCodeRule.java new file mode 100644 index 0000000..3b4dddf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CurrentDateTimeGenerateCodeRule.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 当前时间生成规则 + */ +@Data +public class CurrentDateTimeGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 时间格式 + */ + private String pattern; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CustomRandomStrGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CustomRandomStrGenerateCodeRule.java new file mode 100644 index 0000000..df85f42 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/CustomRandomStrGenerateCodeRule.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 自定义随机字符串生成规则 + */ +@Data +public class CustomRandomStrGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 字符池 + */ + private String pool; + + /** + * 长度 + */ + private Integer len; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/FlowGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/FlowGenerateCodeRule.java new file mode 100644 index 0000000..f450a15 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/FlowGenerateCodeRule.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 流水号生成规则 + */ +@Data +public class FlowGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, + Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 唯一标识 + */ + private String key; + + /** + * 长度 + */ + private Integer len; + + /** + * 步长 + */ + private Integer step; + + /** + * 滚动方式 0按天滚动 1按过期秒数滚动 + */ + private Integer expireType; + + /** + * 过期秒数(过期后会从1重新计数) + */ + private Long expireSeconds; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/RandomIntGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/RandomIntGenerateCodeRule.java new file mode 100644 index 0000000..dfb5b28 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/RandomIntGenerateCodeRule.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 随机整数生成规则 + */ +@Data +public class RandomIntGenerateCodeRule extends CustomRandomStrGenerateCodeRule implements + GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; + + public RandomIntGenerateCodeRule() { + setPool("0123456789"); + } + + /** + * 长度 + */ + private Integer len; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/SnowFlakeGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/SnowFlakeGenerateCodeRule.java new file mode 100644 index 0000000..9ca3393 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/SnowFlakeGenerateCodeRule.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 雪花算法生成规则 + */ +@Data +public class SnowFlakeGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/StaticStrGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/StaticStrGenerateCodeRule.java new file mode 100644 index 0000000..5bd1fa0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/StaticStrGenerateCodeRule.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * 静态字符串生成规则 + */ +@Data +public class StaticStrGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 字符串 + */ + private String val; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/UUIDGenerateCodeRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/UUIDGenerateCodeRule.java new file mode 100644 index 0000000..46f12aa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/generator/rule/impl/UUIDGenerateCodeRule.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.core.components.generator.rule.impl; + +import com.lframework.starter.web.core.components.generator.rule.AbstractGenerateCodeRule; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import lombok.Data; + +import java.io.Serializable; + +/** + * UUID生成规则 + */ +@Data +public class UUIDGenerateCodeRule extends AbstractGenerateCodeRule implements GenerateCodeRule, Serializable { + + private static final long serialVersionUID = 1L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/DefaultLockBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/DefaultLockBuilder.java new file mode 100644 index 0000000..0d02892 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/DefaultLockBuilder.java @@ -0,0 +1,85 @@ +package com.lframework.starter.web.core.components.locker; + +import com.lframework.starter.common.locker.LockBuilder; +import com.lframework.starter.common.locker.Locker; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +@Slf4j +public class DefaultLockBuilder implements LockBuilder { + + private static final Map LOCKERS; + + static { + LOCKERS = new ConcurrentHashMap<>(); + } + + @Override + public Locker buildLocker(String lockName, long expireTime, long waitTime) { + + Locker locker = LOCKERS.get(lockName); + if (locker != null) { + return locker; + } + + synchronized (DefaultLockBuilder.class) { + locker = LOCKERS.get(lockName); + if (locker != null) { + return locker; + } + + locker = new JavaLocker(lockName, waitTime); + + LOCKERS.put(lockName, locker); + } + + return locker; + } + + public static class JavaLocker implements Locker { + + private String lockName; + + private long waitTime; + + private ReentrantLock lock; + + public JavaLocker(String lockName, long waitTime) { + + this.waitTime = waitTime; + this.lockName = lockName; + this.lock = new ReentrantLock(); + } + + @Override + public boolean lock() { + + try { + return this.lock.tryLock(waitTime, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + return false; + } + } + + @Override + public boolean unLock() { + + this.lock.unlock(); + + DefaultLockBuilder.LOCKERS.remove(this.lockName); + + return true; + } + + @Override + public void close() { + + unLock(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/LockFactory.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/LockFactory.java new file mode 100644 index 0000000..5be0344 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/LockFactory.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.core.components.locker; + +import com.lframework.starter.common.locker.LockBuilder; +import com.lframework.starter.common.locker.Locker; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.utils.ApplicationUtil; + +public class LockFactory { + + /** + * 默认获取锁等待时间 毫秒 + */ + public static final long DEFAULT_WAIT_TIME = 5000L; + + /** + * 默认锁过期时间 毫秒 + */ + public static final long DEFAULT_EXPIRE_TIME = 30000L; + + public static Locker getLocker(String lockName) { + + return getLocker(lockName, DEFAULT_EXPIRE_TIME, DEFAULT_WAIT_TIME); + } + + public static Locker getLocker(String lockName, long expireTime) { + + return getLocker(lockName, expireTime, DEFAULT_WAIT_TIME); + } + + public static Locker getLocker(String lockName, long expireTime, long waitTime) { + + Assert.greaterThanZero(expireTime); + Assert.greaterThanZero(waitTime); + + return ApplicationUtil.getBean(LockBuilder.class).buildLocker(lockName, expireTime, waitTime); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/RedisLockBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/RedisLockBuilder.java new file mode 100644 index 0000000..dfeaae8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/locker/RedisLockBuilder.java @@ -0,0 +1,186 @@ +package com.lframework.starter.web.core.components.locker; + +import com.lframework.starter.common.locker.LockBuilder; +import com.lframework.starter.common.locker.Locker; +import com.lframework.starter.web.core.utils.IdUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisStringCommands; +import org.springframework.data.redis.connection.ReturnType; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.types.Expiration; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class RedisLockBuilder implements LockBuilder { + + private static final ThreadLocal> LOCKERS; + + static { + LOCKERS = new InheritableThreadLocal<>(); + } + + @Resource(name = "redisTemplate") + private RedisTemplate redisTemplate; + + @Override + public Locker buildLocker(String lockName, long expireTime, long waitTime) { + + if (LOCKERS.get() == null) { + LOCKERS.set(new HashMap<>()); + } + + Locker locker = LOCKERS.get().get(lockName); + if (locker != null) { + return locker; + } + + locker = new RedisLocker(redisTemplate, lockName, expireTime, waitTime); + LOCKERS.get().put(lockName, locker); + + return locker; + } + + @Slf4j + public static class RedisLocker implements Locker { + + + private static final String SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; + + private static final Long INTERVAL_TIME = 100L; + + private final RedisTemplate redisTemplate; + + private final byte[] key; + + private final byte[] requestId = IdUtil.getUUID().getBytes(); + + private final long expireTime; + + private boolean lock; + + private long waitTime; + + private int lockCount = 0; + + public RedisLocker(RedisTemplate redisTemplate, String key, long expireTime, + long waitTime) { + + this.redisTemplate = redisTemplate; + + this.key = key.getBytes(); + + this.expireTime = expireTime; + + this.waitTime = waitTime; + } + + @Override + public boolean lock() { + + if (this.lock) { + addLockCount(); + return true; + } + + while (!(this.lock = this.redisTemplate.execute(new TryLockRedisCallBack())) + && this.waitTime > 0L) { + try { + Thread.sleep(INTERVAL_TIME); + this.waitTime -= INTERVAL_TIME; + } catch (InterruptedException e) { + log.error("获取lock中断", e); + return false; + } + } + + if (log.isDebugEnabled()) { + log.debug("获取lock完成,result={}, key={}, requestId={}", this.lock, new String(this.key), + this.requestId); + } + + if (this.lock) { + addLockCount(); + } + return this.lock; + } + + private void addLockCount() { + + this.lockCount++; + if (log.isDebugEnabled()) { + log.debug("重入次数:{}", this.lockCount); + } + } + + private void reduceLockCount() { + + this.lockCount--; + if (log.isDebugEnabled()) { + log.debug("重入次数:{}", this.lockCount); + } + } + + @Override + public boolean unLock() { + + if (this.lock) { + if (this.lockCount <= 1) { + boolean release = this.redisTemplate.execute(new ReleaseRedisCallBack()); + if (log.isDebugEnabled()) { + log.debug("释放lock完成,result={}, key={}, requestId={}", this.lock, new String(this.key), + new String(this.requestId)); + } + + this.lock = !release; + + reduceLockCount(); + + RedisLockBuilder.LOCKERS.get().remove(this.key); + + return release; + } else { + + reduceLockCount(); + return true; + } + } + + return true; + } + + @Override + public void close() { + + unLock(); + } + + private class TryLockRedisCallBack implements RedisCallback { + + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + + if (log.isDebugEnabled()) { + log.debug("key={}, requestId={}", new String(key), new String(requestId)); + } + + return connection.set(key, requestId, Expiration.from(expireTime, TimeUnit.MILLISECONDS), + RedisStringCommands.SetOption.ifAbsent()); + } + } + + private class ReleaseRedisCallBack implements RedisCallback { + + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + + return connection.eval(SCRIPT.getBytes(), ReturnType.BOOLEAN, 1, key, requestId); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomAuthorizationInterceptor.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomAuthorizationInterceptor.java new file mode 100644 index 0000000..9055904 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomAuthorizationInterceptor.java @@ -0,0 +1,62 @@ +package com.lframework.starter.web.core.components.magic; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.CheckPermissionHandler; +import com.lframework.starter.web.core.components.security.PermissionCalcType; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.context.MagicUser; +import org.ssssssss.magicapi.core.exception.MagicLoginException; +import org.ssssssss.magicapi.core.interceptor.Authorization; +import org.ssssssss.magicapi.core.interceptor.AuthorizationInterceptor; +import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest; + +/** + * 自定义用户名密码登录 + */ +@Component //注入到Spring容器中 +public class MagicCustomAuthorizationInterceptor implements AuthorizationInterceptor { + + @Autowired + private CheckPermissionHandler checkPermissionHandler; + + /** + * 配置是否需要登录 + */ + @Override + public boolean requireLogin() { + return false; + } + + /** + * 根据Token获取User + */ + @Override + public MagicUser getUserByToken(String token) throws MagicLoginException { + AbstractUserDetails currentUser = SecurityUtil.getUserByToken(token); + if (currentUser == null) { + throw new MagicLoginException("请重新登录!"); + } + + return new MagicUser(currentUser.getId(), currentUser.getName(), token); + } + + @Override + public MagicUser login(String username, String password) throws MagicLoginException { + throw new MagicLoginException("不支持手动登录,请先登录主系统!"); + } + + @Override + public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, + Authorization authorization) { + + String[] profiles = ApplicationUtil.getEnv().getActiveProfiles(); + if (ArrayUtil.isNotEmpty(profiles) && ArrayUtil.contains(profiles, "demo")) { + return authorization == Authorization.VIEW; + } + return checkPermissionHandler.valid(PermissionCalcType.OR, true,"system:online-code:config"); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomJsonValueProvider.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomJsonValueProvider.java new file mode 100644 index 0000000..5da3882 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomJsonValueProvider.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.core.components.magic; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.utils.PageResultUtil; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.context.RequestEntity; +import org.ssssssss.magicapi.core.interceptor.ResultProvider; +import org.ssssssss.magicapi.modules.db.model.Page; + +import java.util.List; +import java.util.Map; + +@Component +public class MagicCustomJsonValueProvider implements ResultProvider { + + /** + * 定义返回结果,默认返回JsonBean + */ + @Override + public Object buildResult(RequestEntity requestEntity, int code, String message, Object data) { + if (code >= 200 && code <= 299) { + return InvokeResultBuilder.success(data); + } else { + throw new DefaultClientException(message); + } + } + + /** + * 定义分页返回结果,该项会被封装在Json结果内, 此方法可以不覆盖,默认返回PageResult + */ + @Override + public Object buildPageResult(RequestEntity requestEntity, Page page, long total, + List> data) { + + return PageResultUtil.newInstance(page.getOffset() / page.getLimit() + 1, page.getLimit(), + total, data); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomMagicFunction.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomMagicFunction.java new file mode 100644 index 0000000..47f2c9c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomMagicFunction.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.core.components.magic; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.config.MagicFunction; +import org.ssssssss.script.annotation.Comment; +import org.ssssssss.script.annotation.Function; + +@Component +public class MagicCustomMagicFunction implements MagicFunction { + + @Function + @Comment("获取登录人ID") + public static AbstractUserDetails current_user() { + AbstractUserDetails user = SecurityUtil.getCurrentUser(); + return user; + } + + @Function + @Comment("获取租户ID") + public static String current_tenant_id() { + return TenantContextHolder.getTenantId() == null ? null + : TenantContextHolder.getTenantId().toString(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomSqlCache.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomSqlCache.java new file mode 100644 index 0000000..218c90c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/magic/MagicCustomSqlCache.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.core.components.magic; + +import com.lframework.starter.web.core.components.redis.RedisHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.modules.db.cache.SqlCache; + +@Component +public class MagicCustomSqlCache implements SqlCache { + + @Autowired + private RedisHandler redisHandler; + + @Override + public void put(String name, String key, Object value) { + redisHandler.hset(name, key, value); + } + + @Override + public void put(String name, String key, Object value, long ttl) { + redisHandler.hset(name, key, value, ttl); + } + + @Override + public T get(String name, String key) { + return (T) redisHandler.hget(name, key); + } + + @Override + public void delete(String name) { + redisHandler.hdel(name); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRule.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRule.java new file mode 100644 index 0000000..779687b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRule.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.components.notify; + +/** + * 消息通知规则 + */ +public interface SysNotifyRule { + + /** + * 根据业务类型匹配 + * + * @param bizType + * @return + */ + boolean match(Integer bizType); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleEmail.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleEmail.java new file mode 100644 index 0000000..b1b45d5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleEmail.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.core.components.notify; + +import com.lframework.starter.web.inner.dto.notify.SysNotifyParamsDto; + +/** + * 消息通知规则(邮件) + */ +public interface SysNotifyRuleEmail extends SysNotifyRule { + + /** + * 获取标题 + * + * @param params + * @return + */ + String getTitle(SysNotifyParamsDto params); + + /** + * 获取内容 + * + * @param params + * @return + */ + String getContent(SysNotifyParamsDto params); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleSys.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleSys.java new file mode 100644 index 0000000..364acdd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/notify/SysNotifyRuleSys.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.core.components.notify; + +import com.lframework.starter.web.inner.dto.notify.SysNotifyParamsDto; + +/** + * 消息通知规则(站内信) + */ +public interface SysNotifyRuleSys extends SysNotifyRule { + + /** + * 获取标题 + * + * @param params + * @return + */ + String getTitle(SysNotifyParamsDto params); + + /** + * 获取内容 + * + * @param params + * @return + */ + String getContent(SysNotifyParamsDto params); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/oplog/OpLogType.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/oplog/OpLogType.java new file mode 100644 index 0000000..c9ea223 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/oplog/OpLogType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.components.oplog; + +public interface OpLogType { + + /** + * 获取编号 + * + * @return + */ + Integer getCode(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/DataPermissionHandlerImpl.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/DataPermissionHandlerImpl.java new file mode 100644 index 0000000..9501249 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/DataPermissionHandlerImpl.java @@ -0,0 +1,183 @@ +package com.lframework.starter.web.core.components.permission; + +import cn.dev33.satoken.session.SaSession; +import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.permission.DataPermission; +import com.lframework.starter.web.core.annotations.permission.DataPermissionGroup; +import com.lframework.starter.web.core.annotations.permission.DataPermissions; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityConstants; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; + +import java.lang.reflect.Method; +import java.util.*; +import java.util.stream.Collectors; + +public class DataPermissionHandlerImpl implements DataPermissionHandler { + + private static final String EMPTY_SQL = "(1 = 1)"; + + @Override + public Expression getSqlSegment(Expression where, String mappedStatementId) { + try { + List sqlSegmentList = this.convertDataPermissionSql(mappedStatementId); + if (CollectionUtil.isEmpty(sqlSegmentList)) { + return null; + } + + List expressionList = new ArrayList<>(); + if (where != null) { + expressionList.add(where); + } + for (String sqlSegment : sqlSegmentList) { + Expression sqlSegmentExpression = CCJSqlParserUtil.parseCondExpression(sqlSegment); + expressionList.add(sqlSegmentExpression); + } + + Expression finalExpression = expressionList.get(0); + for (int i = 1; i < expressionList.size(); i++) { + finalExpression = new AndExpression(finalExpression, expressionList.get(i)); + } + return finalExpression; + } catch (JSQLParserException e) { + e.printStackTrace(); + } + return null; + } + + private String getDataPermission(Class permissionTypeClazz, + List keys, + List values) { + + Map dataPermissionMap = null; + Map dataPermissionVar = null; + try { + AbstractUserDetails currenUser = SecurityUtil.getCurrentUser(); + if (currenUser == null) { + return EMPTY_SQL; + } + + SaSession session = SecurityUtil.getSessionByLoginId(currenUser.getLoginId()); + if (session == null) { + return EMPTY_SQL; + } + + dataPermissionMap = (Map) session.get( + SecurityConstants.DATA_PERMISSION_SQL_MAP); + + dataPermissionVar = (Map) session.get( + SecurityConstants.DATA_PERMISSION_SQL_VAR); + if (CollectionUtil.isEmpty(dataPermissionMap)) { + return EMPTY_SQL; + } + } catch (Exception e) { + return EMPTY_SQL; + } + + Assert.notNull(permissionTypeClazz); + Assert.notNull(keys); + Assert.notNull(values); + + + SysDataPermissionDataPermissionType permissionType = ApplicationUtil.getBean(permissionTypeClazz); + String sqlTemplate = dataPermissionMap.get(permissionType.getCode().toString()); + if (StringUtil.isBlank(sqlTemplate)) { + return EMPTY_SQL; + } + + if (keys.size() != values.size()) { + throw new DefaultSysException("keys和values长度不一致!"); + } + + Map sqlParams = new HashMap<>(); + for (int i = 0; i < keys.size(); i++) { + sqlParams.put(keys.get(i), values.get(i)); + } + + if (CollectionUtil.isNotEmpty(dataPermissionVar)) { + dataPermissionVar.forEach((k, v) -> { + sqlParams.put("__var#" + k, v); + }); + } + + return StringUtil.format(sqlTemplate, sqlParams); + } + + private List convertDataPermissionSql(String statementId) { + // 获取Mapper执行方法上的注解 + Method mapperMethod = null; + try { + mapperMethod = this.findMapperMethod(this.convertMsId(statementId)); + } catch (ClassNotFoundException e) { + return null; + } + if (mapperMethod == null) { + return null; + } + + List results = new ArrayList<>(); + DataPermissionGroup dataPermissionGroup = mapperMethod.getAnnotation(DataPermissionGroup.class); + if (dataPermissionGroup != null) { + DataPermissions[] dataPermissionsArr = dataPermissionGroup.value(); + + if (dataPermissionsArr != null && dataPermissionsArr.length > 0) { + for (DataPermissions dataPermissions : dataPermissionsArr) { + buildDataPermissionSql(results, dataPermissions); + } + } + } else { + DataPermissions dataPermissions = mapperMethod.getAnnotation(DataPermissions.class); + if (dataPermissions != null) { + buildDataPermissionSql(results, dataPermissions); + } + } + return results; + } + + private String convertMsId(String id) { + String pageHelperSuffix = "_COUNT"; + if (id.endsWith(pageHelperSuffix)) { + return id.substring(0, id.length() - pageHelperSuffix.length()); + } + + String mpSuffix = "_mpCount"; + if (id.endsWith(mpSuffix)) { + return id.substring(0, id.length() - mpSuffix.length()); + } + + return id; + } + + private Method findMapperMethod(String statementId) + throws ClassNotFoundException { + int lastDotIndex = statementId.lastIndexOf("."); + String className = statementId.substring(0, lastDotIndex); + String methodName = statementId.substring(lastDotIndex + 1); + + Class mapperInterface = Class.forName(className); + return Arrays.stream(mapperInterface.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .findFirst() + .orElse(null); + } + + private void buildDataPermissionSql(List results, DataPermissions dataPermissions) { + Class dataPermissionType = dataPermissions.type(); + DataPermission[] dataPermissionList = dataPermissions.value(); + String dataPermissionSql = this.getDataPermission(dataPermissionType, + Arrays.stream(dataPermissionList).map(DataPermission::template) + .collect(Collectors.toList()), + Arrays.stream(dataPermissionList).map(DataPermission::alias) + .collect(Collectors.toList())); + results.add(dataPermissionSql); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/SysDataPermissionDataPermissionType.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/SysDataPermissionDataPermissionType.java new file mode 100644 index 0000000..c3a893d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/permission/SysDataPermissionDataPermissionType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.components.permission; + +public interface SysDataPermissionDataPermissionType { + + /** + * 获取编号 + * + * @return + */ + Integer getCode(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/DynamicQrtzJob.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/DynamicQrtzJob.java new file mode 100644 index 0000000..87da548 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/DynamicQrtzJob.java @@ -0,0 +1,59 @@ +package com.lframework.starter.web.core.components.qrtz; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.GroovyUtil; +import com.lframework.starter.web.inner.enums.system.QrtzJobType; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * @author zmj + * @since 2022/8/20 + */ +public class DynamicQrtzJob extends QrtzJob { + + @Override + protected void onExecute(JobExecutionContext context) throws Exception { + + JobDetail jobDetail = context.getJobDetail(); + JobDataMap jobDataMap = jobDetail.getJobDataMap(); + QrtzJobType jobType = EnumUtil.getByCode(QrtzJobType.class, jobDataMap.getInt("jobType")); + if (jobType == QrtzJobType.EXCUTE_CLASS) { + String targetClassName = jobDataMap.getString("targetClassName"); + String targetMethodName = jobDataMap.getString("targetMethodName"); + List targetParamTypes = (List) jobDataMap.get("targetParamTypes"); + List targetParams = (List) jobDataMap.get("targetParams"); + + Class clazz = Class.forName(targetClassName); + Object target = ReflectUtil.newInstance(clazz); + Class[] paramTypes = null; + if (!CollectionUtil.isEmpty(targetParamTypes)) { + paramTypes = new Class[targetParamTypes.size()]; + for (int i = 0; i < targetParamTypes.size(); i++) { + String targetParamType = targetParamTypes.get(i); + paramTypes[i] = Class.forName(targetParamType); + } + } + Object[] params = null; + if (!CollectionUtil.isEmpty(targetParams)) { + params = new Object[targetParams.size()]; + for (int i = 0; i < targetParams.size(); i++) { + String targetParamType = targetParams.get(i); + params[i] = targetParamType; + } + } + + Method method = ReflectUtil.getMethod(clazz, targetMethodName, paramTypes); + ReflectUtil.invoke(target, method, params); + } else { + String script = jobDataMap.getString("script"); + GroovyUtil.excuteScript(script); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzHandler.java new file mode 100644 index 0000000..5bde5f5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzHandler.java @@ -0,0 +1,313 @@ +package com.lframework.starter.web.core.components.qrtz; + +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + +import java.util.Map; + +@Slf4j +public class QrtzHandler { + + private static final SchedulerFactoryBean SCHEDULER_FACTORY = ApplicationUtil.getBean( + SchedulerFactoryBean.class); + + public static void addJob(Class jobClass, String cron, + Map jobDatas) { + + addJob(null, null, jobClass, null, null, cron, jobDatas); + } + + public static void addJob(Class jobClass, String cron) { + + addJob(null, null, jobClass, null, null, cron, null); + } + + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron) { + + addJob(jobName, jobGroupName, jobClass, triggerName, triggerGroupName, cron, null); + } + + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron, Map jobDatas) { + + addJob(jobName, jobGroupName, jobClass, triggerName, triggerGroupName, cron, jobDatas, null); + } + + /** + * 添加任务 + * + * @param jobName 任务名 + * @param jobGroupName 任务组名 + * @param jobClass 任务类Class + * @param triggerName 触发器名 + * @param triggerGroupName 触发器组名 + * @param cron cron表达式 + * @param jobDatas 附加数据 + */ + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron, Map jobDatas, + String description) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + JobBuilder jobBuilder = JobBuilder.newJob(jobClass); + if (!StringUtil.isBlank(jobName)) { + jobBuilder.withIdentity(jobName, jobGroupName); + } + + JobDetail jobDetail = jobBuilder.withDescription( + StringUtil.isBlank(description) ? StringPool.EMPTY_STR : description).build(); + if (!CollectionUtil.isEmpty(jobDatas)) { + jobDatas.forEach((k, v) -> jobDetail.getJobDataMap().put(k, v)); + } + + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + if (!StringUtil.isBlank(triggerName)) { + triggerBuilder.withIdentity(triggerName, triggerGroupName); + } + + triggerBuilder.startNow(); + triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); + CronTrigger trigger = (CronTrigger) triggerBuilder.build(); + sched.scheduleJob(jobDetail, trigger); + + if (!sched.isShutdown()) { + sched.start(); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 查询触发器 + * + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + * @return + */ + public static CronTrigger getTrigger(String triggerName, String triggerGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); + CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey); + + return trigger; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 查询任务 + * + * @param jobName + * @param jobGroupName + * @return + */ + public static JobDetail getJob(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName)); + return jobDetail; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 修改任务Cron + * + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + * @param cron cron表达式 + */ + public static void updateJobCron(String triggerName, String triggerGroupName, String cron) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + CronTrigger trigger = getTrigger(triggerName, triggerGroupName); + if (trigger == null) { + return; + } + + String oriCron = trigger.getCronExpression(); + if (!oriCron.equalsIgnoreCase(cron)) { + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + triggerBuilder.withIdentity(triggerName, triggerGroupName); + triggerBuilder.startNow(); + triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); + trigger = (CronTrigger) triggerBuilder.build(); + sched.rescheduleJob(TriggerKey.triggerKey(triggerName, triggerGroupName), trigger); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 删除任务 + * + * @param jobName 任务名称 + * @param jobGroupName 任务组名称 + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + */ + public static void deleteJob(String jobName, String jobGroupName, String triggerName, + String triggerGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + + TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); + + sched.pauseTrigger(triggerKey); + sched.unscheduleJob(triggerKey); + sched.deleteJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 启动所有任务 + */ + public static void startJobs() { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.start(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 关闭所有任务 + */ + public static void shutdownJobs() { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + if (!sched.isShutdown()) { + sched.shutdown(); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 安全关闭 + * + * @throws SchedulerException + */ + public static void safeShutdown() throws SchedulerException { + + try { + DynamicDataSourceContextHolder.push("master"); + int executingJobSize = SCHEDULER_FACTORY.getScheduler().getCurrentlyExecutingJobs().size(); + log.info("当前运行任务个数:{},等待完成后关闭", executingJobSize); + SCHEDULER_FACTORY.getScheduler().shutdown(true); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 恢复任务 + * + * @param jobName + * @param jobGroupName + */ + public static void resume(String jobName, String jobGroupName) { + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.resumeJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 暂停任务 + * + * @param jobName + * @param jobGroupName + */ + public static void pause(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.pauseJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 触发任务 + * + * @param jobName + * @param jobGroupName + */ + public static void trigger(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.triggerJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzJob.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzJob.java new file mode 100644 index 0000000..621cb6c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/qrtz/QrtzJob.java @@ -0,0 +1,53 @@ +package com.lframework.starter.web.core.components.qrtz; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import java.io.Serializable; + +/** + * 定时任务 + */ +@Slf4j +@DisallowConcurrentExecution +public abstract class QrtzJob implements Job, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + + log.info("开始执行定时任务【{}】", this.getClass().getName()); + long begTime = System.currentTimeMillis(); + + try { + // 这里获取tenantId 如果为空则不设置租户ID + Integer tenantId = (Integer) context.getJobDetail().getJobDataMap().get(StringPool.TENANT_ID_QRTZ); + if (tenantId != null) { + TenantContextHolder.setTenantId(tenantId); + } + this.onExecute(context); + long endTime = System.currentTimeMillis(); + log.info("定时任务【{}】执行完毕,共耗时{}ms", this.getClass().getName(), endTime - begTime); + } catch (Exception e) { + if (e instanceof ClientException) { + log.warn("执行定时任务【{}】失败", this.getClass().getName()); + log.warn(e.getMessage(), e); + } else { + log.error("执行定时任务【{}】失败", this.getClass().getName()); + log.error(e.getMessage(), e); + } + throw new JobExecutionException(e); + } finally { + TenantContextHolder.clearTenantId(); + } + } + + protected abstract void onExecute(JobExecutionContext context) throws Exception; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/redis/RedisHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/redis/RedisHandler.java new file mode 100644 index 0000000..9fb0c01 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/redis/RedisHandler.java @@ -0,0 +1,551 @@ +package com.lframework.starter.web.core.components.redis; + +import com.lframework.starter.common.utils.Assert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * Redis处理器 + * + * @author zmj + */ +public class RedisHandler { + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 指定缓存失效时间 + * + * @param key + * @param time 时间(毫秒) + * @return + */ + public boolean expire(String key, long time) { + + Assert.notNull(key); + if (time < 0) { + //若time < 0 则立即失效 + time = 1; + } + + return redisTemplate.expire(key, time, TimeUnit.MILLISECONDS); + } + + /** + * 根据key 获取过期时间 + * + * @param key + * @return 时间(毫秒) 返回0代表永久有效 + */ + public long getExpire(String key) { + + Assert.notNull(key); + return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS); + } + + /** + * 查看key是否存在 + * + * @param key + * @return + */ + public boolean hasKey(String key) { + + Assert.notNull(key); + return redisTemplate.hasKey(key); + } + + /** + * 删除缓存 + * + * @param keys + */ + public void del(String... keys) { + + Assert.notNull(keys); + + redisTemplate.delete(CollectionUtils.arrayToList(keys)); + } + + //String + + /** + * 普通缓存获取 + * + * @param key + * @return + */ + public Object get(String key) { + + Assert.notNull(key); + + return redisTemplate.opsForValue().get(key); + } + + /** + * 增加普通缓存 + * + * @param key + * @param value + */ + public void set(String key, Object value) { + + Assert.notNull(key); + redisTemplate.opsForValue().set(key, value); + } + + /** + * 增加普通缓存并设置过期时间 + * + * @param key + * @param value + * @param time 小于0时则为永久有效 + */ + public void set(String key, Object value, long time) { + + Assert.notNull(key); + if (time < 0) { + set(key, value); + } else { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS); + } + } + + /** + * 递增 + * + * @param key + * @param delta 增加量 + * @return + */ + public long incr(String key, long delta) { + + Assert.notNull(key); + Assert.greaterThanZero(delta); + + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key + * @param delta 减少量 + * @return + */ + public long decr(String key, long delta) { + + Assert.notNull(key); + Assert.greaterThanZero(delta); + + return redisTemplate.opsForValue().increment(key, -delta); + } + + /** + * 递增 + * + * @param key + * @param delta 增加量 + * @return + */ + public double incr(String key, double delta) { + + Assert.notNull(key); + Assert.greaterThanZero(delta); + + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key + * @param delta 减少量 + * @return + */ + public double decr(String key, double delta) { + + Assert.notNull(key); + Assert.greaterThanZero(delta); + + return redisTemplate.opsForValue().increment(key, -delta); + } + + //Map + + /** + * HashGet + * + * @param key map所对应的key值 + * @param item 获取的数据在map中所对应的key值 + * @return + */ + public Object hget(String key, String item) { + + Assert.notNull(key); + Assert.notNull(item); + return redisTemplate.opsForHash().get(key, item); + } + + /** + * HashGetAll + * + * @param key + * @return + */ + public Map hgetAll(String key) { + + Assert.notNull(key); + + return redisTemplate.opsForHash().entries(key); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key + * @return + */ + public Map hmget(String key) { + + Assert.notNull(key); + return redisTemplate.opsForHash().entries(key); + } + + /** + * 缓存map + * + * @param key + * @param map + */ + public void hmset(String key, Map map) { + + Assert.notNull(key); + Assert.notNull(map); + + redisTemplate.opsForHash().putAll(key, map); + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key + * @param item + * @param value + */ + public void hset(String key, String item, Object value) { + + Assert.notNull(key); + Assert.notNull(item); + redisTemplate.opsForHash().put(key, item, value); + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key + * @param item + * @param value + * @param time 过期时间(毫秒) 如果已存在的hash表有过期时间,将会替换原有时间 + * @return + */ + public boolean hset(String key, String item, Object value, long time) { + + Assert.notNull(key); + Assert.notNull(item); + redisTemplate.opsForHash().put(key, item, value); + if (time < 0) { + time = 1; + } + + return expire(key, time); + } + + /** + * 删除hash表中的值 + * + * @param key + * @param items + */ + public void hdel(String key, String... items) { + + Assert.notNull(key); + Assert.notEmpty(items); + + redisTemplate.opsForHash().delete(key, items); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key + * @param item + * @return + */ + public boolean hHasKey(String key, String item) { + + Assert.notNull(key); + Assert.notNull(item); + + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key + * @param item + * @param by + * @return + */ + public double hincr(String key, String item, double by) { + + Assert.notNull(key); + Assert.notNull(item); + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key + * @param item + * @param by + * @return + */ + public double hdecr(String key, String item, double by) { + + Assert.notNull(key); + Assert.notNull(item); + return redisTemplate.opsForHash().increment(key, item, -by); + } + + //set + + /** + * 根据key获取Set中的所有值 + * + * @param key + * @return + */ + public Set sGet(String key) { + + Assert.notNull(key); + return redisTemplate.opsForSet().members(key); + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key + * @param value + * @return + */ + public boolean sHasKey(String key, Object value) { + + Assert.notNull(key); + return redisTemplate.opsForSet().isMember(key, value); + } + + /** + * 将数据放入set缓存 + * + * @param key + * @param values + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + + Assert.notNull(key); + return redisTemplate.opsForSet().add(key, values); + } + + /** + * 将set数据放入缓存 + * + * @param key + * @param time 时间(毫秒) + * @param values + * @return 成功个数 + */ + public long sSetAndExpire(String key, long time, Object... values) { + + Assert.notNull(key); + long count = redisTemplate.opsForSet().add(key, values); + if (time < 0) { + time = 1; + } + + expire(key, time); + return count; + } + + /** + * 获取set缓存的长度 + * + * @param key + * @return + */ + public long sGetSetSize(String key) { + + Assert.notNull(key); + return redisTemplate.opsForSet().size(key); + } + + /** + * 移除值 + * + * @param key + * @param values + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + + Assert.notNull(key); + long count = redisTemplate.opsForSet().remove(key, values); + return count; + } + + //list + + /** + * 获取list缓存的内容 + * + * @param key + * @param start + * @param end + * @return + */ + public List lGet(String key, long start, long end) { + + Assert.notNull(key); + Assert.greaterThanOrEqualToZero(start); + Assert.greaterThanOrEqualToZero(end); + return redisTemplate.opsForList().range(key, start, end); + } + + /** + * 获取list缓存的长度 + * + * @param key + * @return + */ + public long lGetListSize(String key) { + + return redisTemplate.opsForList().size(key); + } + + /** + * 通过索引 获取list中的值 + * + * @param key + * @param index + * @return + */ + public Object lGetIndex(String key, long index) { + + Assert.notNull(key); + Assert.greaterThanOrEqualToZero(index); + return redisTemplate.opsForList().index(key, index); + } + + /** + * 增加缓存至list中 + * + * @param key + * @param value + */ + public void lSet(String key, Object value) { + + Assert.notNull(key); + redisTemplate.opsForList().rightPush(key, value); + } + + /** + * 增加缓存至list中,并对list设置过期时间 + * + * @param key + * @param value + * @param time 过期时间(毫秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + + Assert.notNull(key); + redisTemplate.opsForList().rightPush(key, value); + if (time < 0) { + time = 1; + } + + return expire(key, time); + } + + /** + * 将list放入缓存 + * + * @param key + * @param value + */ + public void lSet(String key, List value) { + + Assert.notNull(key); + redisTemplate.opsForList().rightPushAll(key, value); + } + + /** + * 将list放入缓存 + * + * @param key + * @param value + * @param time 失效时间(毫秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + + Assert.notNull(key); + redisTemplate.opsForList().rightPushAll(key, value); + + if (time < 0) { + time = 1; + } + + return expire(key, time); + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key + * @param index + * @param value + */ + public void lUpdateIndex(String key, long index, Object value) { + + Assert.notNull(key); + Assert.greaterThanOrEqualToZero(index); + redisTemplate.opsForList().set(key, index, value); + } + + /** + * 移除N个值为value + * + * @param key + * @param count + * @param value + * @return + */ + public long lRemove(String key, long count, Object value) { + + Assert.notNull(key); + Assert.greaterThanZero(count); + long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResult.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResult.java new file mode 100644 index 0000000..554b146 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResult.java @@ -0,0 +1,40 @@ +package com.lframework.starter.web.core.components.resp; + +import com.lframework.starter.common.constants.ResponseConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 统一响应数据 + * + * @author zmj + */ +@Data +public class InvokeResult implements Response { + + private static final long serialVersionUID = 1L; + + /** + * 响应码 + */ + @Schema(description = "响应码,2开头的响应码为成功,否则为失败", example = "200") + private Integer code; + + /** + * 响应信息 + */ + @Schema(description = "响应信息", example = ResponseConstants.INVOKE_RESULT_SUCCESS_MSG) + private String msg; + + /** + * 数据 + */ + @Schema(description = "数据") + private T data; + + /** + * TraceId + */ + @Schema(description = "TraceId") + private String traceId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultBuilder.java new file mode 100644 index 0000000..06b2485 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultBuilder.java @@ -0,0 +1,112 @@ +package com.lframework.starter.web.core.components.resp; + +import com.lframework.starter.common.constants.ResponseConstants; +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.web.core.components.trace.TraceBuilder; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * 统一响应数据Builder + * + * @author zmj + */ +@Slf4j +public class InvokeResultBuilder { + + /** + * 响应成功-无数据 + * + * @return + */ + public static InvokeResult success() { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(ResponseConstants.INVOKE_RESULT_SUCCESS_CODE); + invokeResult.setMsg(ResponseConstants.INVOKE_RESULT_SUCCESS_MSG); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } + + /** + * 响应成功-有数据 + * + * @param data + * @return + */ + public static InvokeResult success(T data) { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(ResponseConstants.INVOKE_RESULT_SUCCESS_CODE); + invokeResult.setMsg(ResponseConstants.INVOKE_RESULT_SUCCESS_MSG); + invokeResult.setData(data); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } + + /** + * 响应失败-无信息 + * + * @return + */ + public static InvokeResult fail() { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(ResponseConstants.INVOKE_RESULT_FAIL_CODE); + invokeResult.setMsg(ResponseConstants.INVOKE_RESULT_FAIL_MSG); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } + + /** + * 响应失败-有信息 + * + * @param msg + * @return + */ + public static InvokeResult fail(String msg) { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(ResponseConstants.INVOKE_RESULT_FAIL_CODE); + invokeResult.setMsg(msg); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } + + /** + * 响应失败-有信息和数据 + * + * @param msg + * @return + */ + public static InvokeResult fail(String msg, T data) { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(ResponseConstants.INVOKE_RESULT_FAIL_CODE); + invokeResult.setMsg(msg); + invokeResult.setData(data); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } + + /** + * 响应失败-根据异常 + * + * @param e + * @return + */ + public static InvokeResult fail(BaseException e) { + + InvokeResult invokeResult = new InvokeResult<>(); + invokeResult.setCode(e.getCode()); + invokeResult.setMsg(e.getMsg()); + invokeResult.setTraceId(ApplicationUtil.getBean(TraceBuilder.class).getTraceId(false)); + + return invokeResult; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultErrorBuilderWrapper.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultErrorBuilderWrapper.java new file mode 100644 index 0000000..d201316 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/InvokeResultErrorBuilderWrapper.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.core.components.resp; + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.web.core.controller.BaseController; + +public class InvokeResultErrorBuilderWrapper implements ResponseErrorBuilder { + + @Override + public boolean isDefault() { + return true; + } + + @Override + public boolean isMatch(Object controller) { + return controller instanceof BaseController; + } + + @Override + public Response fail() { + return InvokeResultBuilder.fail(); + } + + @Override + public Response fail(String msg) { + return InvokeResultBuilder.fail(msg); + } + + @Override + public Response fail(String msg, T data) { + return InvokeResultBuilder.fail(msg, data); + } + + @Override + public Response fail(BaseException e) { + return InvokeResultBuilder.fail(e); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/PageResult.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/PageResult.java new file mode 100644 index 0000000..e2df90f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/PageResult.java @@ -0,0 +1,68 @@ +package com.lframework.starter.web.core.components.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * 统一分页数据 + * + * @param + * @author zmj + */ +@Data +public class PageResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 是否有上一页 + */ + @Schema(description = "是否有上一页") + private boolean hasPrev; + + /** + * 是否有下一页 + */ + @Schema(description = "是否有下一页") + private boolean hasNext; + + /** + * 总记录数 + */ + @Schema(description = "总记录数") + private long totalCount; + + /** + * 每页数据量 + */ + @Schema(description = "每页条数") + private long pageSize; + + /** + * 第几页 + */ + @Schema(description = "当前页码") + private long pageIndex; + + /** + * 总共几页 + */ + @Schema(description = "总页数") + private int totalPage; + + /** + * 数据 + */ + @Schema(description = "数据") + private List datas; + + /** + * 附加数据 + */ + @Schema(description = "附加数据") + private Map extra; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/Response.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/Response.java new file mode 100644 index 0000000..a4fc864 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/Response.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.core.components.resp; + +import java.io.Serializable; + +/** + * 响应数据 + */ +public interface Response extends Serializable { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/ResponseErrorBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/ResponseErrorBuilder.java new file mode 100644 index 0000000..b987b9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/resp/ResponseErrorBuilder.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.core.components.resp; + +import com.lframework.starter.common.exceptions.BaseException; + +public interface ResponseErrorBuilder { + + /** + * 是否为默认builder + * + * @return + */ + boolean isDefault(); + + /** + * 当前controller是否匹配 + * + * @param controller + * @return + */ + boolean isMatch(Object controller); + + /** + * 响应失败-无信息 + * + * @return + */ + Response fail(); + + /** + * 响应失败-有信息 + * + * @param msg + * @return + */ + Response fail(String msg); + + /** + * 响应失败-有信息和数据 + * + * @param msg + * @return + */ + Response fail(String msg, T data); + + /** + * 响应失败-根据异常 + * + * @param e + * @return + */ + Response fail(BaseException e); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetails.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetails.java new file mode 100644 index 0000000..a8cd15a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetails.java @@ -0,0 +1,131 @@ +package com.lframework.starter.web.core.components.security; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Set; + +/** + * 系统内UserDetails都需要继承此类 + * + * @author zmj + */ +@Data +public abstract class AbstractUserDetails implements UserDetails, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID 由AbstractUserDetailsService查询 + */ + private String id; + + /** + * 登录名 由AbstractUserDetailsService查询 + */ + private String username; + + /** + * 姓名 由AbstractUserDetailsService查询 + */ + private String name; + + /** + * 密码 由AbstractUserDetailsService查询 + */ + private String password; + + /** + * 邮箱 + */ + private String email; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 状态 由AbstractUserDetailsService查询 + */ + private Boolean available; + + /** + * 权限 由IMenuService查询 + */ + private Set permissions; + + /** + * 用户IP地址 会自动获取 + */ + private String ip; + + /** + * 锁定状态 + */ + private Boolean lockStatus; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 是否为管理员 + */ + private Boolean isAdmin; + + /** + * loginId + */ + private String loginId; + + /** + * 是否为平台管理租户 + */ + private Boolean isPlatform; + + @Override + public boolean isAccountNonExpired() { + + return true; + } + + @Override + public boolean isAccountNonLocked() { + + return !this.lockStatus; + } + + @Override + public boolean isCredentialsNonExpired() { + + return true; + } + + @Override + public boolean isEnabled() { + + return this.available; + } + + /** + * 是否无权限 + * + * @return + */ + public boolean isNoPermission() { + + return this.permissions == null || this.permissions.size() == 0; + } + + public boolean isAdmin() { + + return this.isAdmin; + } + + @Override + public boolean hasAdminPermission() { + return !isNoPermission() && this.permissions.contains(SecurityConstants.PERMISSION_ADMIN_NAME); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetailsService.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetailsService.java new file mode 100644 index 0000000..35a2896 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/AbstractUserDetailsService.java @@ -0,0 +1,81 @@ +package com.lframework.starter.web.core.components.security; + +import com.lframework.starter.common.exceptions.impl.UserLoginException; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.RequestUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import java.util.List; +import java.util.Set; + +/** + * 所有UserDetailsService都需要继承此类 如果需要更改用户表,那么继承此类注册Bean即可 + * + * @author zmj + */ +@Slf4j +public abstract class AbstractUserDetailsService implements UserDetailsService { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + @Value("${remove-fixed-permissions:false}") + private Boolean removeFixedPermission; + + @Override + public AbstractUserDetails loadUserByUsername(String username) throws UserLoginException { + + //根据登录名查询 + AbstractUserDetails userDetails = this.findByUsername(username); + + if (ObjectUtil.isEmpty(userDetails)) { + log.debug("用户名 {} 不存在", username); + throw new UserLoginException("用户名或密码错误!"); + } + + userDetails.setTenantId(TenantContextHolder.getTenantId()); + + //获取登录IP + userDetails.setIp(RequestUtil.getRequestIp()); + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + + // 先取角色的权限 + userDetails.setPermissions(sysMenuService.getRolePermissionByUserId(userDetails.getId())); + userDetails.setIsAdmin( + userDetails.getPermissions().contains(SecurityConstants.PERMISSION_ADMIN_NAME)); + // 再取菜单的权限 + Set permissions = sysMenuService.getPermissionsByUserId(userDetails.getId(), + userDetails.isAdmin(), moduleIds); + // 合并权限 + permissions.addAll(userDetails.getPermissions()); + if (this.removeFixedPermission) { + permissions.remove(SecurityConstants.PERMISSION_ADMIN_NAME); + } + userDetails.setPermissions(permissions); + + return userDetails; + } + + /** + * 根据登录名查询 + * + * @param username + * @return + */ + public abstract AbstractUserDetails findByUsername(String username); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandler.java new file mode 100644 index 0000000..d8a5c54 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandler.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.core.components.security; + +/** + * 权限验证 + * + * @author zmj + */ +public interface CheckPermissionHandler { + + /** + * 验证权限 + * + * @param permissions + * @return + */ + boolean valid(PermissionCalcType calcType, boolean requirePlatform, String... permissions); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandlerImpl.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandlerImpl.java new file mode 100644 index 0000000..882bff8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/CheckPermissionHandlerImpl.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.core.components.security; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import lombok.extern.slf4j.Slf4j; + +import java.util.Arrays; +import java.util.Set; + +/** + * 权限验证实现 + * + * @author zmj + */ +@Slf4j +public class CheckPermissionHandlerImpl implements CheckPermissionHandler { + + @Override + public boolean valid(PermissionCalcType calcType, boolean requirePlatform, + String... permissions) { + if (ArrayUtil.isEmpty(permissions) && !requirePlatform) { + return false; + } + + AbstractUserDetails user = SecurityUtil.getCurrentUser(); + if (user == null) { + return false; + } + + if (requirePlatform) { + if (!user.getIsPlatform()) { + return false; + } + + if (ArrayUtil.isEmpty(permissions)) { + return true; + } + } + + if (user.hasAdminPermission()) { + if (log.isDebugEnabled()) { + log.debug("当前用户是管理员,通过权限校验"); + } + return true; + } + Set permissionSet = user.getPermissions(); + + boolean valid = CollectionUtil.isNotEmpty(permissionSet) + && (calcType == PermissionCalcType.OR ? + Arrays.stream(permissions).anyMatch( + pattern -> permissionSet.stream().anyMatch(item -> StringUtil.strMatch(pattern, item))) + : Arrays.stream(permissions).allMatch( + pattern -> permissionSet.stream() + .anyMatch(item -> StringUtil.strMatch(pattern, item)))); + + if (log.isDebugEnabled()) { + log.debug("当前用户权限={}, 需要权限={}, 是否通过权限校验={}", permissionSet, permissions, + valid); + } + + return valid; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/DefaultUserDetails.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/DefaultUserDetails.java new file mode 100644 index 0000000..6fa1772 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/DefaultUserDetails.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.components.security; + +import lombok.Data; + +/** + * 默认UserDetails 如果无需增加属性 可直接使用此类 + * + * @author zmj + */ +@Data +public class DefaultUserDetails extends AbstractUserDetails { + + private static final long serialVersionUID = 1L; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PasswordEncoderWrapper.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PasswordEncoderWrapper.java new file mode 100644 index 0000000..5fd241b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PasswordEncoderWrapper.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.core.components.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * 登陆密码Encoder Wrapper 用于包装Encoder 方便统一管理 + * + * @author zmj + */ +public class PasswordEncoderWrapper { + + @Autowired + private PasswordEncoder encoder; + + public PasswordEncoder getEncoder() { + + return encoder; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermissionCalcType.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermissionCalcType.java new file mode 100644 index 0000000..016328c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermissionCalcType.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.core.components.security; + +/** + * 校验权限时的计算方式 + */ +public enum PermissionCalcType { + OR, AND +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermitAllService.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermitAllService.java new file mode 100644 index 0000000..378ad3d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/PermitAllService.java @@ -0,0 +1,86 @@ +package com.lframework.starter.web.core.components.security; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.UploadProperties; +import com.lframework.starter.web.config.properties.WebProperties; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +public class PermitAllService { + + @Autowired + private WebProperties webProperties; + + @Autowired + private UploadProperties uploadProperties; + + private List> permitAllUrls; + + private Set matchers; + + @PostConstruct + public void init() { + + List> results = new ArrayList<>(); + String filterUrl = webProperties.getFilterUrl(); + if (StringUtil.isNotEmpty(filterUrl)) { + String[] filterUrls = filterUrl.split(","); + for (String url : filterUrls) { + // 配置文件配置的url所有method都放行 + results.add(new SimpleEntry<>(null, url)); + } + } + + String uploadUrl = uploadProperties.getUrl(); + // 访问上传文件url + results.add(new SimpleEntry<>(HttpMethod.GET, + uploadUrl.endsWith("/") ? uploadUrl + "**" : uploadUrl + "/**")); + // swagger + results.add(new SimpleEntry<>(null, "/doc.html")); + results.add(new SimpleEntry<>(null, "/webjars/**")); + results.add(new SimpleEntry<>(null, "/v2/api-docs")); + results.add(new SimpleEntry<>(null, "/swagger-resources")); + results.add(new SimpleEntry<>(null, "/swagger-resources/configuration/ui")); + results.add(new SimpleEntry<>(null, "/swagger-resources/configuration/security")); + results.add(new SimpleEntry<>(null, "/v2/api-docs-ext")); + + this.permitAllUrls = results; + + this.matchers = new CopyOnWriteArraySet<>(); + + for (Entry permitAllUrl : this.permitAllUrls) { + this.matchers.add(new AntPathRequestMatcher(permitAllUrl.getValue(), + permitAllUrl.getKey() == null ? null : permitAllUrl.getKey().toString())); + } + } + + /** + * 获取不需要认证的url + * + * @return + */ + public List> getUrls() { + + return this.permitAllUrls; + } + + public boolean isMatch(HttpServletRequest request) { + + return this.matchers.stream().anyMatch(t -> t.matches(request)); + } + + public void addMatch(HttpServletRequest request) { + this.matchers.add(new AntPathRequestMatcher(request.getRequestURI(), + request.getMethod())); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityConstants.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityConstants.java new file mode 100644 index 0000000..680e4d7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityConstants.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.security; + +public interface SecurityConstants { + + /** + * 管理员权限名称 + */ + String PERMISSION_ADMIN_NAME = "admin"; + + /** + * Token起始字符串 + */ + String TOKEN_START_WITH_STR = "Bearer-"; + + /** + * 用户Token在redis中的key + */ + String USER_TOKEN_KEY = "user_token_key_{}"; + + /** + * 用户信息在redis中的key + */ + String USER_INFO_KEY = "user_info_key"; + + /** + * 数据权限SQL在redis中的key + */ + String DATA_PERMISSION_SQL_MAP = "__data_permission_sql_map"; + + /** + * 数据权限SQL变量在redis中的key + */ + String DATA_PERMISSION_SQL_VAR = "__data_permission_sql_var"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityUtil.java new file mode 100644 index 0000000..0a0c86c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/SecurityUtil.java @@ -0,0 +1,119 @@ +package com.lframework.starter.web.core.components.security; + +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.util.net.openssl.ciphers.Authentication; +import org.springframework.web.context.request.RequestContextHolder; + +/** + * Spring Security工具类 + * + * @author zmj + */ +@Slf4j +public class SecurityUtil { + + private static final ThreadLocal LOGIN_POOL = new InheritableThreadLocal<>(); + + /** + * 清除当前登录人 只能用于子线程的登录人信息传递 + */ + public static void removeCurrentUser() { + LOGIN_POOL.remove(); + } + + /** + * 获取当前登录用户信息 + * + * @return + */ + public static AbstractUserDetails getCurrentUser() { + + try { + if (RequestContextHolder.currentRequestAttributes() == null) { + // 非web环境 + return LOGIN_POOL.get(); + } + } catch (Exception e) { + // 非web环境 + return LOGIN_POOL.get(); + } + + try { + SaSession session = StpUtil.getSession(false); + if (session == null) { + return null; + } + return (AbstractUserDetails) session.get(SecurityConstants.USER_INFO_KEY); + } catch (SaTokenException e) { + return null; + } + } + + /** + * 设置当前登录人 只能用于子线程的登录人信息传递 如果使用此方法,需要确保子线程最终会调用removeCurrentUser!否则登录人信息会混乱! + * + * @param user + */ + public static void setCurrentUser(AbstractUserDetails user) { + LOGIN_POOL.set(user); + } + + public static AbstractUserDetails getCurrentUser(Authentication authentication) { + + return getCurrentUser(); + } + + /** + * 手动退出登录 + */ + public static void logout() { + + StpUtil.logout(); + } + + /** + * 获取当前登录人租户ID + * + * 注意和TenantContextHolder的获取租户ID方法区别 + * + * 这里获取租户ID的话,就意味着当前请求已经登录。 + * + * 但是TenantContextHolder的获取租户ID的方法则不一定已经登录。 + * + * @see com.lframework.starter.web.core.components.tenant.TenantContextHolder + * + * @return + */ + public static Integer getCurrentTenantId() { + AbstractUserDetails currentUser = getCurrentUser(); + return currentUser == null ? null : currentUser.getTenantId(); + } + + public static AbstractUserDetails getUserByToken(String token) { + if (token == null) { + return null; + } + + Object loginId = StpUtil.getLoginIdByToken(token); + if (loginId == null) { + return null; + } + + try { + SaSession session = getSessionByLoginId(loginId); + if (session == null) { + return null; + } + return (AbstractUserDetails) session.get(SecurityConstants.USER_INFO_KEY); + } catch (SaTokenException e) { + return null; + } + } + + public static SaSession getSessionByLoginId(Object loginId) { + return StpUtil.getSessionByLoginId(loginId, false); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetails.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetails.java new file mode 100644 index 0000000..e2604eb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetails.java @@ -0,0 +1,62 @@ +package com.lframework.starter.web.core.components.security; + +import java.io.Serializable; + +public interface UserDetails extends Serializable { + + /** + * 用户密码 + * + * @return + */ + String getPassword(); + + /** + * 用户名 + * + * @return + */ + String getUsername(); + + /** + * 用户是否未过期 + * + * @return + */ + boolean isAccountNonExpired(); + + /** + * 用户是否未锁定 + * + * @return + */ + boolean isAccountNonLocked(); + + /** + * 密码是否未过期 + * + * @return + */ + boolean isCredentialsNonExpired(); + + /** + * 用户是否可用 + * + * @return + */ + boolean isEnabled(); + + /** + * 是否管理员 这里指的是管理员身份,可以获取全部菜单 + * + * @return + */ + boolean isAdmin(); + + /** + * 是否有管理员权限 这里值得是管理员具体权限,因为管理员权限会通过权限校验 + * + * @return + */ + boolean hasAdminPermission(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetailsService.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetailsService.java new file mode 100644 index 0000000..b898a06 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserDetailsService.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.components.security; + +import com.lframework.starter.common.exceptions.impl.UserLoginException; + +public interface UserDetailsService { + + /** + * 根据用户名查询 用于登录认证 + * + * @param username + * @return + * @throws UserLoginException + */ + AbstractUserDetails loadUserByUsername(String username) throws UserLoginException; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolver.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolver.java new file mode 100644 index 0000000..9da878c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolver.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.core.components.security; + +/** + * 用户Token解析器 + */ +public interface UserTokenResolver { + + /** + * 获取Token + * + * @return 如果没有token,则返回null + */ + String getToken(); + + /** + * 获取完整Token 与getToken的区别是:Jwt时会拼接前缀。Session时无区别 + * + * @return + */ + String getFullToken(); + + /** + * 获取Token的key + * + * @return + */ + String getTokenKey(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolverImpl.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolverImpl.java new file mode 100644 index 0000000..d251ccf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/security/UserTokenResolverImpl.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.core.components.security; + +import cn.dev33.satoken.stp.StpUtil; + +public class UserTokenResolverImpl implements UserTokenResolver { + + private String tokenKey = "X-Auth-Token"; + + @Override + public String getToken() { + return StpUtil.getTokenValue(); + } + + @Override + public String getFullToken() { + + return getToken(); + } + + @Override + public String getTokenKey() { + + return tokenKey; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignFactory.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignFactory.java new file mode 100644 index 0000000..da4e2c6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignFactory.java @@ -0,0 +1,6 @@ +package com.lframework.starter.web.core.components.sign; + +public interface CheckSignFactory { + + CheckSignHandler getInstance(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignHandler.java new file mode 100644 index 0000000..1622263 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/CheckSignHandler.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.core.components.sign; + +import com.lframework.starter.web.inner.vo.openapi.OpenApiReqVo; + +public interface CheckSignHandler { + + boolean check(OpenApiReqVo req); + + void setTenantId(OpenApiReqVo req); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/DefaultCheckSignFactory.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/DefaultCheckSignFactory.java new file mode 100644 index 0000000..62e6c4e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/DefaultCheckSignFactory.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.components.sign; + +import com.lframework.starter.web.core.utils.ApplicationUtil; + +public class DefaultCheckSignFactory implements CheckSignFactory { + + @Override + public CheckSignHandler getInstance() { + return ApplicationUtil.getBean(CheckSignHandler.class); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/handler/DefaultCheckSignHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/handler/DefaultCheckSignHandler.java new file mode 100644 index 0000000..f80da30 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/handler/DefaultCheckSignHandler.java @@ -0,0 +1,79 @@ +package com.lframework.starter.web.core.components.sign.handler; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.sign.CheckSignHandler; +import com.lframework.starter.web.core.components.sign.util.SignUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import com.lframework.starter.web.inner.service.system.SysOpenDomainService; +import com.lframework.starter.web.inner.vo.openapi.OpenApiReqVo; +import org.springframework.beans.factory.annotation.Autowired; + +public class DefaultCheckSignHandler implements CheckSignHandler { + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + @Override + public boolean check(OpenApiReqVo req) { + Integer clientId = req.getClientId(); + if (clientId == null) { + return false; + } + + String timestamp = req.getTimestamp(); + if (StringUtil.isBlank(timestamp)) { + return false; + } + + // 校验一下timestamp + if (!RegUtil.isMatch(PatternPool.PATTERN_IS_INTEGER, timestamp)) { + return false; + } + + if (System.currentTimeMillis() - Long.parseLong(timestamp) > 1000 * 60 * 5) { // 最多差异五分钟 + return false; + } + + String nonceStr = req.getNonceStr(); + if (StringUtil.isBlank(nonceStr)) { + return false; + } + + String params = req.getParams(); + if (StringUtil.isBlank(params)) { + return false; + } + + String sign = req.getSign(); + if (StringUtil.isBlank(sign)) { + return false; + } + + SysOpenDomain domain = sysOpenDomainService.findById(clientId); + if (domain == null || !domain.getAvailable()) { + return false; + } + + return SignUtil + .validate(clientId.toString(), domain.getApiSecret(), timestamp, nonceStr, params, sign); + } + + @Override + public void setTenantId(OpenApiReqVo req) { + if (TenantUtil.enableTenant()) { + SysOpenDomain domain = sysOpenDomainService.findById(req.getClientId()); + Integer tenantId = domain.getTenantId(); + if (tenantId == null) { + throw new DefaultSysException("开放域没有设置租户ID"); + } else { + // 开放域一定要重新设置租户ID,租户ID肯定是要和开放域配置的租户ID一致 + TenantContextHolder.setTenantId(domain.getTenantId()); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/util/SignUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/util/SignUtil.java new file mode 100644 index 0000000..5d4636f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/sign/util/SignUtil.java @@ -0,0 +1,98 @@ +package com.lframework.starter.web.core.components.sign.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * Api加签、验签工具类 + */ +public class SignUtil { + + private static final Logger log = LoggerFactory.getLogger(SignUtil.class); + + /** + * 加签 + * + * @param clientId 客户端ID + * @param apiSecret Api密钥 + * @param timestamp 时间戳 + * @param nonceStr 随机字符串 + * @param json 请求参数 + * @return + */ + public static String sign(String clientId, String apiSecret, String timestamp, String nonceStr, + String json) { + String str = new StringBuilder().append("clientId=").append(clientId).append("&") + .append("apiSecret=").append(apiSecret) + .append("&").append("timestamp=").append(timestamp).append("&").append("nonceStr=") + .append(nonceStr).append("&").append("params=") + .append(json).toString(); + MessageDigest digest = null; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } + byte[] bs = digest.digest(str.getBytes(StandardCharsets.UTF_8)); + StringBuilder builder = new StringBuilder(); + for (byte b : bs) { + int x = b & 255; + String s = Integer.toHexString(x); + if (x > 0 && x < 16) { + builder.append("0"); + builder.append(s); + } else { + builder.append(s); + } + } + + return builder.toString(); + } + + /** + * 验签 + * + * @param clientId 客户端ID + * @param apiSecret Api密钥 + * @param timestamp 时间戳 + * @param nonceStr 随机字符串 + * @param json 请求参数 + * @param oriSign 原始签值 + * @return + */ + public static boolean validate(String clientId, String apiSecret, String timestamp, + String nonceStr, String json, + String oriSign) { + return sign(clientId, apiSecret, timestamp, nonceStr, json).equals(oriSign); + } + + // 以下为示例 + /* + public static void main(String[] args) { + String clientId = ""; + String apiSecret = ""; + String ts = String.valueOf(System.currentTimeMillis()); + + //此处为示例的获取字符串算法,此处可以自行替换算法 + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 20; i++) { + int number = random.nextInt(62); + builder.append(str.charAt(number)); + } + + String nonceStr = builder.toString(); + + String json = "{\"key1\":\"value1\", \"key2\":\"value2\"}"; + String sign = SignUtil.sign(clientId, apiSecret, ts, nonceStr, json); // 这里是加签 + + boolean isValidate = SignUtil.validate(clientId, apiSecret, ts, nonceStr, json, sign); // 这里是验签 + } + */ +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantContextHolder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantContextHolder.java new file mode 100644 index 0000000..a89b4ef --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantContextHolder.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.core.components.tenant; + +import com.lframework.starter.web.core.event.ClearTenantEvent; +import com.lframework.starter.web.core.event.SetTenantEvent; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.TenantUtil; + +public class TenantContextHolder { + + private static final ThreadLocal TENANT_ID = new InheritableThreadLocal<>(); + + public static void setTenantId(Integer tenantId) { + if (tenantId == null) { + throw new RuntimeException("tenantId不能为空!"); + } + TENANT_ID.set(tenantId); + + SetTenantEvent event = new SetTenantEvent(TenantContextHolder.class, tenantId); + ApplicationUtil.publishEvent(event); + } + + public static Integer getTenantId() { + return TenantUtil.enableTenant() ? TENANT_ID.get() : null; + } + + public static String getTenantIdStr() { + Integer tenantId = getTenantId(); + if (tenantId == null) { + return null; + } else { + return String.valueOf(tenantId); + } + } + + public static void clearTenantId() { + TENANT_ID.remove(); + + ClearTenantEvent event = new ClearTenantEvent(TenantContextHolder.class); + ApplicationUtil.publishEvent(event); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantInterceptor.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantInterceptor.java new file mode 100644 index 0000000..59f8a47 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/tenant/TenantInterceptor.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.core.components.tenant; + +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 租户拦截器,要在LoginInterceptor后拦截 + * + * @author zmj + */ +public interface TenantInterceptor extends HandlerInterceptor { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultCallable.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultCallable.java new file mode 100644 index 0000000..88c3a9e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultCallable.java @@ -0,0 +1,61 @@ +package com.lframework.starter.web.core.components.threads; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; + +import java.util.concurrent.Callable; + +/** + * 默认Callable 可传递当前登录人信息 + * + * @author zmj + * @since 2022/8/19 + */ +public class DefaultCallable implements Callable { + + private final AbstractUserDetails user; + + private final Callable callable; + + private final Integer tenantId; + + public DefaultCallable(Callable callable) { + this.user = SecurityUtil.getCurrentUser(); + this.callable = callable; + this.tenantId = TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() : null; + } + + public DefaultCallable(AbstractUserDetails user, Callable callable) { + this.user = user; + this.callable = callable; + this.tenantId = TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() : null; + } + + public DefaultCallable(AbstractUserDetails user, Callable callable, Integer tenantId) { + this.user = user; + this.callable = callable; + this.tenantId = tenantId; + } + + @Override + public T call() throws Exception { + try { + if (this.user != null) { + SecurityUtil.setCurrentUser(this.user); + } + if (this.tenantId != null) { + TenantContextHolder.setTenantId(this.tenantId); + } + return this.callable.call(); + } finally { + if (this.user != null) { + SecurityUtil.removeCurrentUser(); + } + if (this.tenantId != null) { + TenantContextHolder.clearTenantId(); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultRunnable.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultRunnable.java new file mode 100644 index 0000000..319a6c0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/threads/DefaultRunnable.java @@ -0,0 +1,59 @@ +package com.lframework.starter.web.core.components.threads; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; + +/** + * 默认的Runnable 可传递当前登录人信息 + * + * @author zmj + * @since 2022/8/19 + */ +public class DefaultRunnable implements Runnable { + + private final AbstractUserDetails user; + + private final Runnable runnable; + + private final Integer tenantId; + + public DefaultRunnable(Runnable runnable) { + this.user = SecurityUtil.getCurrentUser(); + this.runnable = runnable; + this.tenantId = TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() : null; + } + + public DefaultRunnable(AbstractUserDetails user, Runnable runnable) { + this.user = user; + this.runnable = runnable; + this.tenantId = TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() : null; + } + + public DefaultRunnable(AbstractUserDetails user, Runnable runnable, Integer tenantId) { + this.user = user; + this.runnable = runnable; + this.tenantId = tenantId; + } + + @Override + public void run() { + try { + if (this.user != null) { + SecurityUtil.setCurrentUser(this.user); + } + if (this.tenantId != null) { + TenantContextHolder.setTenantId(this.tenantId); + } + this.runnable.run(); + } finally { + if (this.user != null) { + SecurityUtil.removeCurrentUser(); + } + if (this.tenantId != null) { + TenantContextHolder.clearTenantId(); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/timeline/OrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/timeline/OrderTimeLineBizType.java new file mode 100644 index 0000000..3f6d83b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/timeline/OrderTimeLineBizType.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.components.timeline; + +/** + * @author zmj + * @since 2022/8/10 + */ +public interface OrderTimeLineBizType { + + /** + * 获取编号 + * + * @return + */ + Integer getCode(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/DefaultTraceBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/DefaultTraceBuilder.java new file mode 100644 index 0000000..10ec1b3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/DefaultTraceBuilder.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.components.trace; + +import org.slf4j.MDC; + +public class DefaultTraceBuilder implements TraceBuilder { + + @Override + public String getTraceId() { + + return MDC.get("X-B3-TraceId"); + } + + @Override + public String getTraceId(boolean create) { + + return getTraceId(); + } + + @Override + public void removeTraceId() { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/TraceBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/TraceBuilder.java new file mode 100644 index 0000000..907ba63 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/trace/TraceBuilder.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.trace; + +public interface TraceBuilder { + + /** + * 获取TraceId + * + * @return + */ + String getTraceId(); + + /** + * 获取TraceId + * + * @param create + * @return + */ + String getTraceId(boolean create); + + /** + * 清空TraceId + */ + void removeTraceId(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/UploadHandlerFactory.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/UploadHandlerFactory.java new file mode 100644 index 0000000..8a8eb6a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/UploadHandlerFactory.java @@ -0,0 +1,40 @@ +package com.lframework.starter.web.core.components.upload; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.core.utils.ApplicationUtil; + +import java.util.Map; + +public class UploadHandlerFactory { + + public static UploadHandler getInstance(String type) { + Assert.notBlank(type); + + Map uploadHandlerMap = ApplicationUtil.getBeansOfType( + UploadHandler.class); + for (UploadHandler value : uploadHandlerMap.values()) { + if (value.getType().equalsIgnoreCase(type)) { + return value; + } + } + + throw new DefaultSysException("没有找到" + type + "对应的UploadHandler"); + } + + public static SecurityUploadHandler getSecurityInstance(String type) { + Assert.notBlank(type); + + Map uploadHandlerMap = ApplicationUtil.getBeansOfType( + SecurityUploadHandler.class); + for (SecurityUploadHandler value : uploadHandlerMap.values()) { + if (value.getType().equalsIgnoreCase(type)) { + return value; + } + } + + throw new DefaultSysException("没有找到" + type + "对应的UploadHandler"); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/UploadClient.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/UploadClient.java new file mode 100644 index 0000000..313dfe3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/UploadClient.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.core.components.upload.client; + +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; + +import java.io.InputStream; +import java.util.List; + +public interface UploadClient { + + /** + * 上传文件 + * + * @param is 输入流 + * @param locations 路径 比如想把文件存在${baseLocation}/datas/2022/01/01目录处,此时locations = ['datas', '2022', + * '01', '01'] + * @param fileName 文件名 + */ + UploadDto upload(InputStream is, List locations, String fileName); + + /** + * 获取预签名URL + * + * @param objectName 文件名(全目录) + * @param expiration 过期时间,单位秒 + * @return + */ + String generatePresignedUrl(String objectName, long expiration); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/CosUploadConfig.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/CosUploadConfig.java new file mode 100644 index 0000000..9f03f88 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/CosUploadConfig.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.components.upload.client.config; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CosUploadConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + private String customUrl; + + private String endpoint; + + private String region; + + private String secretId; + + private String secretKey; + + private String bucketName; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/LocalUploadConfig.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/LocalUploadConfig.java new file mode 100644 index 0000000..d676762 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/LocalUploadConfig.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.core.components.upload.client.config; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class LocalUploadConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + private String domain; + + private String url; + + private String location; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/ObsUploadConfig.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/ObsUploadConfig.java new file mode 100644 index 0000000..cdbad7a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/ObsUploadConfig.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.components.upload.client.config; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ObsUploadConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + private String customUrl; + + private String endpoint; + + private String ak; + + private String sk; + + private String bucketName; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/OssUploadConfig.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/OssUploadConfig.java new file mode 100644 index 0000000..47e46bf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/config/OssUploadConfig.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.components.upload.client.config; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class OssUploadConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + private String customUrl; + + private String endpoint; + + private String internalEndPoint; + + private String accessKeyId; + + private String accessKeySecret; + + private String bucketName; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/dto/UploadDto.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/dto/UploadDto.java new file mode 100644 index 0000000..9a266bc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/dto/UploadDto.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.components.upload.client.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +@Data +public class UploadDto implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * 安全上传记录ID + * + * 只有安全上传时有值 + */ + private String securityUploadRecordId; + + private String url; + + private String objectName; + + private String uploadType; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/CosUploadClient.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/CosUploadClient.java new file mode 100644 index 0000000..988c672 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/CosUploadClient.java @@ -0,0 +1,156 @@ +package com.lframework.starter.web.core.components.upload.client.impl; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.CosUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.Headers; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.endpoint.UserSpecifiedEndpointBuilder; +import com.qcloud.cos.http.HttpMethodName; +import com.qcloud.cos.http.HttpProtocol; +import com.qcloud.cos.model.GeneratePresignedUrlRequest; +import com.qcloud.cos.model.ObjectMetadata; +import com.qcloud.cos.model.PutObjectRequest; +import com.qcloud.cos.model.ResponseHeaderOverrides; +import com.qcloud.cos.region.Region; +import com.qcloud.cos.transfer.TransferManager; +import com.qcloud.cos.transfer.Upload; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; + +@Slf4j +public class CosUploadClient implements UploadClient { + + private CosUploadConfig config; + + public CosUploadClient(CosUploadConfig config) { + this.config = config; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + Assert.notBlank(config.getEndpoint()); + Assert.notBlank(config.getBucketName()); + Assert.notBlank(config.getSecretId()); + Assert.notBlank(config.getSecretKey()); + Assert.notBlank(config.getRegion()); + + String objectName = (CollectionUtil.isEmpty(locations) ? StringPool.EMPTY_STR + : (StringUtil.join("/", locations) + "/")) + fileName; + + TransferManager transferManager = null; + try { + transferManager = createTransferManager(); + + PutObjectRequest request = new PutObjectRequest(config.getBucketName(), objectName, is, + new ObjectMetadata()); + Upload upload = transferManager.upload(request); + upload.waitForUploadResult(); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + if (transferManager != null) { + transferManager.shutdownNow(true); + } + } + String url = config.getEndpoint(); + if (!StringUtil.isBlank(config.getCustomUrl())) { + url = config.getCustomUrl(); + } + UploadDto dto = new UploadDto(); + dto.setUrl(url + (url.endsWith("/") ? StringPool.EMPTY_STR + : "/") + objectName); + dto.setObjectName(objectName); + dto.setUploadType("COS"); + + return dto; + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + Assert.notBlank(config.getBucketName()); + COSClient cosClient = createCosClient(); + LocalDateTime now = LocalDateTime.now(); + + GeneratePresignedUrlRequest req = + new GeneratePresignedUrlRequest(config.getBucketName(), objectName, HttpMethodName.GET); + ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides(); + String responseContentDispositon = null; + try { + responseContentDispositon = "attachment;filename=" + URLEncoder.encode( + objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + String responseCacheControl = "no-cache"; + responseHeaders.setContentDisposition(responseContentDispositon); + responseHeaders.setCacheControl(responseCacheControl); + req.setResponseHeaders(responseHeaders); + Date expirationDate = DateUtil.toDate(now.plusSeconds(expiration)); + req.setExpiration(expirationDate); + req.putCustomRequestHeader(Headers.HOST, + cosClient.getClientConfig().getEndpointBuilder() + .buildGeneralApiEndpoint(config.getBucketName())); + + try { + URL url = cosClient.generatePresignedUrl(req); + return url.toString(); + } finally { + cosClient.shutdown(); + } + } + + private TransferManager createTransferManager() { + + COSClient cosClient = createCosClient(); + + TransferManager transferManager = new TransferManager(cosClient); + + return transferManager; + } + + private COSClient createCosClient() { + + COSCredentials cred = new BasicCOSCredentials(config.getSecretId(), config.getSecretKey()); + + ClientConfig clientConfig = new ClientConfig(); + clientConfig.setRegion(new Region(config.getRegion())); + + String url = config.getEndpoint(); + if (!StringUtil.isBlank(config.getCustomUrl())) { + url = config.getCustomUrl(); + // 设置自定义的域名 + UserSpecifiedEndpointBuilder endpointBuilder = new UserSpecifiedEndpointBuilder( + url.replace("http://", "").replace("https://", ""), "service.cos.myqcloud.com"); + clientConfig.setEndpointBuilder(endpointBuilder); + } + + clientConfig.setHttpProtocol( + url.startsWith("https://") ? HttpProtocol.https : HttpProtocol.http); + + // 设置 socket 读取超时,默认 30s + clientConfig.setSocketTimeout(30 * 1000); + // 设置建立连接超时,默认 30s + clientConfig.setConnectionTimeout(30 * 1000); + + return new COSClient(cred, clientConfig); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/LocalUploadClient.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/LocalUploadClient.java new file mode 100644 index 0000000..e100cdc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/LocalUploadClient.java @@ -0,0 +1,97 @@ +package com.lframework.starter.web.core.components.upload.client.impl; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.redis.RedisHandler; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.LocalUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.service.SysConfService; + +import java.io.File; +import java.io.InputStream; +import java.util.List; + +public class LocalUploadClient implements UploadClient { + + private LocalUploadConfig config; + + public LocalUploadClient(LocalUploadConfig config) { + this.config = config; + } + + @Override + public UploadDto upload(InputStream is, List locations, + String fileName) { + String domain = config.getDomain(); + String baseUrl = config.getUrl(); + String location = config.getLocation(); + + Assert.notNull(is); + Assert.notBlank(domain); + Assert.notBlank(baseUrl); + Assert.notBlank(location); + Assert.notBlank(fileName); + + if (domain.endsWith("/")) { + domain = domain.substring(0, domain.length() - 1); + } + if (!baseUrl.startsWith("/")) { + baseUrl = "/" + baseUrl; + } + + String url = domain + baseUrl; + + if (StringUtil.isEmpty(url)) { + url = StringPool.EMPTY_STR; + } + + if (!url.endsWith("/")) { + url = url + "/"; + } + + if (!location.endsWith(File.separator)) { + // 路径不是以分隔符结尾 + location = location + File.separator; + } + + //文件全路径 比如/upload/datas/2022/01/01/ + String fullPath = location + (CollectionUtil.isEmpty(locations) ? + StringPool.EMPTY_STR : + CollectionUtil.join(locations, File.separator)) + File.separator; + + File dest = FileUtil.touch(fullPath, fileName); + + FileUtil.writeFromStream(is, dest); + + UploadDto dto = new UploadDto(); + dto.setUrl(url + (CollectionUtil.isEmpty(locations) ? + StringPool.EMPTY_STR : + CollectionUtil.join(locations, "/") + "/") + fileName); + dto.setObjectName(fullPath + fileName); + dto.setUploadType("LOCAL"); + return dto; + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + + String baseUrl = config.getDomain(); + String uri = "/download/security"; + String sign = IdUtil.getUUID(); + + SysConfService sysConfService = ApplicationUtil.getBean(SysConfService.class); + Long expire = sysConfService.getLong("security-upload.sign-url-expired", 600L); + + RedisHandler redisHandler = ApplicationUtil.getBean(RedisHandler.class); + redisHandler.hset("security-upload", sign, objectName, + expire * 1000L); + + return baseUrl + uri + "?sign=" + sign; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/ObsUploadClient.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/ObsUploadClient.java new file mode 100644 index 0000000..a00ec76 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/ObsUploadClient.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.core.components.upload.client.impl; + +import cn.hutool.core.util.URLUtil; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.ObsUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.obs.services.ObsClient; +import com.obs.services.model.HttpMethodEnum; +import com.obs.services.model.PutObjectResult; +import com.obs.services.model.TemporarySignatureRequest; +import com.obs.services.model.TemporarySignatureResponse; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class ObsUploadClient implements UploadClient { + + private ObsUploadConfig config; + + public ObsUploadClient(ObsUploadConfig config) { + this.config = config; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + + String endPoint = config.getEndpoint(); + String bucketName = config.getBucketName(); + String ak = config.getAk(); + String sk = config.getSk(); + String customUrl = config.getCustomUrl(); + + Assert.notBlank(endPoint); + Assert.notBlank(bucketName); + Assert.notBlank(ak); + Assert.notBlank(sk); + + String objectName = (CollectionUtil.isEmpty(locations) ? StringPool.EMPTY_STR + : (StringUtil.join("/", locations) + "/")) + fileName; + + try (ObsClient obsClient = new ObsClient(ak, sk, + endPoint)) { + // 不判断桶是否存在,建议桶在控台创建 + PutObjectResult result = obsClient.putObject(bucketName, objectName, is); + + UploadDto dto = new UploadDto(); + dto.setObjectName(objectName); + if (StringUtil.isNotBlank(customUrl)) { + dto.setUrl(customUrl + (customUrl.endsWith("/") ? StringPool.EMPTY_STR + : "/") + objectName); + } else { + dto.setUrl(URLUtil.decode(result.getObjectUrl())); + } + + dto.setUploadType("OBS"); + return dto; + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + String ak = config.getAk(); + String sk = config.getSk(); + String endPoint = config.getEndpoint(); + String bucketName = config.getBucketName(); + + try (ObsClient obsClient = new ObsClient(ak, sk, endPoint)) { + TemporarySignatureRequest req = new TemporarySignatureRequest(); + req.setExpires(expiration); + req.setMethod(HttpMethodEnum.GET); + req.setBucketName(bucketName); + req.setObjectKey(objectName); + + TemporarySignatureResponse resp = obsClient.createTemporarySignature(req); + return resp.getSignedUrl(); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/OssUploadClient.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/OssUploadClient.java new file mode 100644 index 0000000..9babe7b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/client/impl/OssUploadClient.java @@ -0,0 +1,126 @@ +package com.lframework.starter.web.core.components.upload.client.impl; + +import com.aliyun.oss.ClientBuilderConfiguration; +import com.aliyun.oss.HttpMethod; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.common.comm.SignVersion; +import com.aliyun.oss.model.GeneratePresignedUrlRequest; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.OssUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +public class OssUploadClient implements UploadClient { + + private OssUploadConfig config; + + public OssUploadClient(OssUploadConfig config) { + this.config = config; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + + String customUrl = config.getCustomUrl(); + String endPoint = config.getEndpoint(); + String internalEndPoint = config.getInternalEndPoint(); + String accessKeyId = config.getAccessKeyId(); + String accessKeySecret = config.getAccessKeySecret(); + String bucketName = config.getBucketName(); + + Assert.notBlank(endPoint); + Assert.notBlank(bucketName); + Assert.notBlank(accessKeyId); + Assert.notBlank(accessKeySecret); + + OSS ossClient = new OSSClientBuilder().build( + StringUtil.isBlank(internalEndPoint) ? endPoint + : internalEndPoint, accessKeyId, + accessKeySecret); + + String objectName = (CollectionUtil.isEmpty(locations) ? StringPool.EMPTY_STR + : (StringUtil.join("/", locations) + "/")) + fileName; + try { + // 这里不判断桶是否存在,通过控台创建 + ossClient.putObject(bucketName, objectName, is); + + UploadDto dto = new UploadDto(); + + dto.setObjectName(objectName); + + if (StringUtil.isNotBlank(customUrl)) { + dto.setUrl(customUrl + (customUrl.endsWith("/") ? StringPool.EMPTY_STR + : "/") + objectName); + } else { + dto.setUrl("https://" + bucketName + "." + endPoint + "/" + objectName); + } + dto.setUploadType("OSS"); + return dto; + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + String customUrl = config.getCustomUrl(); + String endPoint = config.getEndpoint(); + String accessKeyId = config.getAccessKeyId(); + String accessKeySecret = config.getAccessKeySecret(); + String bucketName = config.getBucketName(); + + Assert.notBlank(endPoint); + Assert.notBlank(bucketName); + Assert.notBlank(accessKeyId); + Assert.notBlank(accessKeySecret); + if (!StringUtil.isBlank(customUrl)) { + // 这里只判断customUrl即可,涉及到下载,不会使用内网endPoint + endPoint = customUrl; + } + + ClientBuilderConfiguration configuration = new ClientBuilderConfiguration(); + // 请注意,设置true开启CNAME选项。 + configuration.setSupportCname(true); + // 显式声明使用 V4 签名算法 + configuration.setSignatureVersion(SignVersion.V4); + + // 生成预签名URL。 + GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, + HttpMethod.GET); + + // 设置下载行为(强制下载而非预览)及文件名 + try { + request.getResponseHeaders().setContentDisposition("attachment;filename=" + URLEncoder.encode( + objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8")); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + + // 设置过期时间。 + LocalDateTime now = LocalDateTime.now(); + request.setExpiration(DateUtil.toDate(now.plusSeconds(expiration))); + + // 通过HTTP GET请求生成预签名URL。 + OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, + accessKeySecret, configuration); + + return ossClient.generatePresignedUrl(request).toString(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/SecurityUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/SecurityUploadHandler.java new file mode 100644 index 0000000..e9c6778 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/SecurityUploadHandler.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.core.components.upload.handler; + +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.service.SecurityUploadRecordService; + +import java.io.InputStream; +import java.util.List; + +public interface SecurityUploadHandler { + + /** + * 获取上传类型 + * + * @return + */ + String getType(); + + /** + * 上传文件 + * + * @param is + * @param locations + * @param fileName + * @return + */ + UploadDto upload(InputStream is, List locations, String fileName); + + default UploadDto createSecurityRecord(UploadDto dto) { + SecurityUploadRecordService securityUploadRecordService = ApplicationUtil.getBean(SecurityUploadRecordService.class); + String id = securityUploadRecordService.create(dto.getUploadType(), dto.getObjectName()); + dto.setSecurityUploadRecordId(id); + return dto; + } + + /** + * 获取预签名URL + * + * @param objectName 文件名(全目录) + * @param expiration 过期时间,单位秒 + * @return + */ + String generatePresignedUrl(String objectName, long expiration); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/UploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/UploadHandler.java new file mode 100644 index 0000000..56a8ac9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/UploadHandler.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.core.components.upload.handler; + +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; + +import java.io.InputStream; +import java.util.List; + +public interface UploadHandler { + + /** + * 获取上传类型 + * + * @return + */ + String getType(); + + /** + * 上传文件 + * + * @param is + * @param locations + * @param fileName + * @return 下载链接 + */ + UploadDto upload(InputStream is, List locations, String fileName); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosSecurityUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosSecurityUploadHandler.java new file mode 100644 index 0000000..f09b050 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosSecurityUploadHandler.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.CosUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.CosUploadClient; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class CosSecurityUploadHandler implements SecurityUploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "COS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("security-upload.cos.config"); + CosUploadConfig config = JsonUtil.parseObject(configStr, CosUploadConfig.class); + + Assert.notBlank(config.getEndpoint()); + Assert.notBlank(config.getRegion()); + Assert.notBlank(config.getBucketName()); + Assert.notBlank(config.getSecretId()); + Assert.notBlank(config.getSecretKey()); + + UploadClient uploadClient = new CosUploadClient(config); + + UploadDto dto = uploadClient.upload(is, locations, fileName); + + return createSecurityRecord(dto); + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + String configStr = sysConfService.findRequiredByKey("security-upload.cos.config"); + CosUploadConfig config = JsonUtil.parseObject(configStr, CosUploadConfig.class); + + UploadClient uploadClient = new CosUploadClient(config); + + return uploadClient.generatePresignedUrl(objectName, expiration); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosUploadHandler.java new file mode 100644 index 0000000..796d959 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/CosUploadHandler.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.CosUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.CosUploadClient; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class CosUploadHandler implements UploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "COS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("upload.cos.config"); + CosUploadConfig config = JsonUtil.parseObject(configStr, CosUploadConfig.class); + + Assert.notBlank(config.getEndpoint()); + Assert.notBlank(config.getRegion()); + Assert.notBlank(config.getBucketName()); + Assert.notBlank(config.getSecretId()); + Assert.notBlank(config.getSecretKey()); + + UploadClient uploadClient = new CosUploadClient(config); + + return uploadClient.upload(is, locations, fileName); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalSecurityUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalSecurityUploadHandler.java new file mode 100644 index 0000000..cbd1e14 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalSecurityUploadHandler.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.config.properties.SecurityUploadProperties; +import com.lframework.starter.web.config.properties.UploadProperties; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.LocalUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.LocalUploadClient; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class LocalSecurityUploadHandler implements SecurityUploadHandler { + + @Autowired + private UploadProperties uploadProperties; + + @Autowired + private SecurityUploadProperties securityUploadProperties; + + @Override + public String getType() { + return "LOCAL"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + + LocalUploadConfig config = new LocalUploadConfig(); + config.setDomain(securityUploadProperties.getDomain()); + config.setUrl(uploadProperties.getUrl()); + config.setLocation(securityUploadProperties.getLocation()); + UploadClient uploadClient = new LocalUploadClient(config); + + UploadDto dto = uploadClient.upload(is, locations, fileName); + + return createSecurityRecord(dto); + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + LocalUploadConfig config = new LocalUploadConfig(); + config.setDomain(securityUploadProperties.getDomain()); + config.setUrl(uploadProperties.getUrl()); + config.setLocation(securityUploadProperties.getLocation()); + UploadClient uploadClient = new LocalUploadClient(config); + + return uploadClient.generatePresignedUrl(objectName, expiration); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalUploadHandler.java new file mode 100644 index 0000000..7b73a0b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/LocalUploadHandler.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.config.properties.UploadProperties; +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.LocalUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.LocalUploadClient; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class LocalUploadHandler implements UploadHandler { + + @Autowired + private UploadProperties uploadProperties; + + @Override + public String getType() { + return "LOCAL"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + + LocalUploadConfig config = new LocalUploadConfig(); + config.setDomain(uploadProperties.getDomain()); + config.setUrl(uploadProperties.getUrl()); + config.setLocation(uploadProperties.getLocation()); + UploadClient uploadClient = new LocalUploadClient(config); + + return uploadClient.upload(is, locations, fileName); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsSecurityUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsSecurityUploadHandler.java new file mode 100644 index 0000000..4e621bc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsSecurityUploadHandler.java @@ -0,0 +1,47 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.ObsUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.ObsUploadClient; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class ObsSecurityUploadHandler implements SecurityUploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "OBS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("security-upload.obs.config"); + ObsUploadConfig config = JsonUtil.parseObject(configStr, ObsUploadConfig.class); + + UploadClient uploadClient = new ObsUploadClient(config); + UploadDto dto = uploadClient.upload(is, locations, fileName); + + return createSecurityRecord(dto); + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + String configStr = sysConfService.findRequiredByKey("security-upload.obs.config"); + ObsUploadConfig config = JsonUtil.parseObject(configStr, ObsUploadConfig.class); + + UploadClient uploadClient = new ObsUploadClient(config); + + return uploadClient.generatePresignedUrl(objectName, expiration); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsUploadHandler.java new file mode 100644 index 0000000..92bb715 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/ObsUploadHandler.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.ObsUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.ObsUploadClient; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class ObsUploadHandler implements UploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "OBS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("upload.obs.config"); + ObsUploadConfig config = JsonUtil.parseObject(configStr, ObsUploadConfig.class); + + UploadClient uploadClient = new ObsUploadClient(config); + return uploadClient.upload(is, locations, fileName); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssSecurityUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssSecurityUploadHandler.java new file mode 100644 index 0000000..043807b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssSecurityUploadHandler.java @@ -0,0 +1,46 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.OssUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.OssUploadClient; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +public class OssSecurityUploadHandler implements SecurityUploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "OSS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("security-upload.oss.config"); + OssUploadConfig config = JsonUtil.parseObject(configStr, OssUploadConfig.class); + + UploadClient uploadClient = new OssUploadClient(config); + + UploadDto dto = uploadClient.upload(is, locations, fileName); + + return createSecurityRecord(dto); + } + + @Override + public String generatePresignedUrl(String objectName, long expiration) { + String configStr = sysConfService.findRequiredByKey("security-upload.oss.config"); + OssUploadConfig config = JsonUtil.parseObject(configStr, OssUploadConfig.class); + + UploadClient uploadClient = new OssUploadClient(config); + + return uploadClient.generatePresignedUrl(objectName, expiration); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssUploadHandler.java new file mode 100644 index 0000000..a3071f3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/upload/handler/impl/OssUploadHandler.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.upload.handler.impl; + +import com.lframework.starter.web.core.components.upload.client.UploadClient; +import com.lframework.starter.web.core.components.upload.client.config.OssUploadConfig; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.client.impl.OssUploadClient; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.service.SysConfService; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.InputStream; +import java.util.List; + +public class OssUploadHandler implements UploadHandler { + + @Autowired + private SysConfService sysConfService; + + @Override + public String getType() { + return "OSS"; + } + + @Override + public UploadDto upload(InputStream is, List locations, String fileName) { + String configStr = sysConfService.findRequiredByKey("upload.oss.config"); + OssUploadConfig config = JsonUtil.parseObject(configStr, OssUploadConfig.class); + + UploadClient uploadClient = new OssUploadClient(config); + + return uploadClient.upload(is, locations, fileName); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/CodeValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/CodeValidator.java new file mode 100644 index 0000000..11bef8d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/CodeValidator.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * 编号校验 如果参数是null或empty 则通过校验 + * + * @author zmj + */ +public class CodeValidator implements ConstraintValidator { + + @Override + public boolean isValid(CharSequence charSequence, + ConstraintValidatorContext constraintValidatorContext) { + + return StringUtil.isEmpty(charSequence) || RegUtil.isMatch(PatternPool.PATTERN_CODE, + charSequence.toString()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/EnumValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/EnumValidator.java new file mode 100644 index 0000000..f4b4803 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/EnumValidator.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.enums.BaseEnum; +import com.lframework.starter.web.core.utils.EnumUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +import java.io.Serializable; + +/** + * 枚举校验 如果参数是null 则通过校验 + * + * @author zmj + */ +public class EnumValidator implements ConstraintValidator { + + private Class> enumsClass; + + @Override + public void initialize(IsEnum constraintAnnotation) { + + this.enumsClass = constraintAnnotation.enumClass(); + } + + @Override + public boolean isValid(Serializable value, ConstraintValidatorContext context) { + + return ObjectUtil.isNull(value) || ObjectUtil.isNotNull(EnumUtil.getByCode(enumsClass, value)) + || ( + value instanceof CharSequence && StringUtil.isEmpty((CharSequence) value)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsCode.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsCode.java new file mode 100644 index 0000000..fa5c931 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsCode.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * 编号类型 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = CodeValidator.class) +public @interface IsCode { + + Class[] groups() default {}; + + String message() default "编号必须由字母、数字、“-_.”组成,长度不能超过20位"; + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsEnum.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsEnum.java new file mode 100644 index 0000000..f1c19f7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsEnum.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.web.core.enums.BaseEnum; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.io.Serializable; +import java.lang.annotation.*; + +/** + * 校验枚举类型 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = EnumValidator.class) +public @interface IsEnum { + + String message(); + + Class[] groups() default {}; + + Class[] payload() default {}; + + Class> enumClass(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJson.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJson.java new file mode 100644 index 0000000..1a39178 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJson.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * JSON类型 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = JsonValidator.class) +public @interface IsJson { + + Class[] groups() default {}; + + String message(); + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonArray.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonArray.java new file mode 100644 index 0000000..698bdcd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonArray.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * JSONArray类型 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = JsonArrayValidator.class) +public @interface IsJsonArray { + + Class[] groups() default {}; + + String message(); + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonObject.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonObject.java new file mode 100644 index 0000000..1961aec --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsJsonObject.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * JSONObject类型 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = JsonObjectValidator.class) +public @interface IsJsonObject { + + Class[] groups() default {}; + + String message(); + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsNumberPrecision.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsNumberPrecision.java new file mode 100644 index 0000000..ff78ecc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/IsNumberPrecision.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * 校验小数位数 + * + * @author zmj + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = NumberPrecisionValidator.class) +public @interface IsNumberPrecision { + + String message(); + + Class[] groups() default {}; + + Class[] payload() default {}; + + int value(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonArrayValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonArrayValidator.java new file mode 100644 index 0000000..c498143 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonArrayValidator.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.core.components.validation; + +import cn.hutool.json.JSONUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * JSONArray校验 如果参数是null 则通过校验 + * + * @author zmj + */ +public class JsonArrayValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + + return value == null || JSONUtil.isJsonArray(value); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonObjectValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonObjectValidator.java new file mode 100644 index 0000000..a1f214a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonObjectValidator.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.core.components.validation; + +import cn.hutool.json.JSONUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * JSONObject校验 如果参数是null 则通过校验 + * + * @author zmj + */ +public class JsonObjectValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + + return value == null || JSONUtil.isJsonObj(value); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonValidator.java new file mode 100644 index 0000000..ea959c8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/JsonValidator.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.core.components.validation; + +import cn.hutool.json.JSONUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * JSON校验 如果参数是null 则通过校验 + * + * @author zmj + */ +public class JsonValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + + return value == null || JSONUtil.isJson(value); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/NumberPrecisionValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/NumberPrecisionValidator.java new file mode 100644 index 0000000..a091ab0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/NumberPrecisionValidator.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.common.utils.NumberUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * 小数位数校验 如果参数是null或不是Number,则不进行校验 + * + * @author zmj + */ +public class NumberPrecisionValidator implements ConstraintValidator { + + private int precision; + + @Override + public void initialize(IsNumberPrecision constraintAnnotation) { + + this.precision = constraintAnnotation.value(); + } + + @Override + public boolean isValid(Object charSequence, + ConstraintValidatorContext constraintValidatorContext) { + if (charSequence == null) { + return true; + } + if (charSequence instanceof Number) { + return NumberUtil.isNumberPrecision((Number) charSequence, this.precision); + } + + return true; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/Pattern.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/Pattern.java new file mode 100644 index 0000000..9ddcc92 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/Pattern.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = PatternValidator.class) +public @interface Pattern { + + /** + * 正则表达式 + * + * @return + */ + String regexp(); + + Class[] groups() default {}; + + String message(); + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/PatternValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/PatternValidator.java new file mode 100644 index 0000000..8a3b223 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/PatternValidator.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * 正则表达式校验 如果参数是null or empty 则通过校验 + * + * @author zmj + */ +public class PatternValidator implements ConstraintValidator { + + /** + * 正则表达式 + */ + private String regExp; + + @Override + public void initialize(Pattern constraintAnnotation) { + + this.regExp = constraintAnnotation.regexp(); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + + return value == null || (value instanceof CharSequence && StringUtil.isEmpty( + (CharSequence) value)) + || RegUtil.isMatch(java.util.regex.Pattern.compile(this.regExp), + StringUtil.toString(value)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/TypeMismatch.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/TypeMismatch.java new file mode 100644 index 0000000..b9752f7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/TypeMismatch.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.core.components.validation; + +import java.lang.annotation.*; + +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TypeMismatch { + + String message() default "数据格式有误!"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrl.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrl.java new file mode 100644 index 0000000..21e1dab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrl.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.core.components.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = UploadUrlValidator.class) +public @interface UploadUrl { + + Class[] groups() default {}; + + String message(); + + Class[] payload() default {}; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrlValidator.java b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrlValidator.java new file mode 100644 index 0000000..67411ba --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/components/validation/UploadUrlValidator.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.components.validation; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * 上传文件url校验 如果参数是null 则通过校验 + * + * @author zmj + */ +public class UploadUrlValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + + return StringUtil.isEmpty(value) || RegUtil.isMatch(PatternPool.PATTERN_HTTP_URL, value); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/constants/MyBatisStringPool.java b/web-starter/src/main/java/com/lframework/starter/web/core/constants/MyBatisStringPool.java new file mode 100644 index 0000000..33b83f1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/constants/MyBatisStringPool.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.core.constants; + +/** + * Mybatis常量 + * + * @author zmj + */ +public interface MyBatisStringPool { + + /** + * 创建人 + */ + String COLUMN_CREATE_BY = "createBy"; + + /** + * 创建人ID + */ + String COLUMN_CREATE_BY_ID = "createById"; + + /** + * 创建时间 + */ + String COLUMN_CREATE_TIME = "createTime"; + + /** + * 修改人 + */ + String COLUMN_UPDATE_BY = "updateBy"; + + /** + * 修改人ID + */ + String COLUMN_UPDATE_BY_ID = "updateById"; + + /** + * 修改时间 + */ + String COLUMN_UPDATE_TIME = "updateTime"; + + /** + * 切换当前租户数据源的Key + */ + String DS_KEY_CUR_TENANT = "#curTenant"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/constants/MybatisConstants.java b/web-starter/src/main/java/com/lframework/starter/web/core/constants/MybatisConstants.java new file mode 100644 index 0000000..5349e6e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/constants/MybatisConstants.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.core.constants; + +public interface MybatisConstants { + + /** + * 默认当前页码 + */ + int DEFAULT_PAGE_INDEX = 1; + + /** + * 默认每页条数 + */ + int DEFAULT_PAGE_SIZE = 20; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/constants/SqlMethodConstants.java b/web-starter/src/main/java/com/lframework/starter/web/core/constants/SqlMethodConstants.java new file mode 100644 index 0000000..927302c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/constants/SqlMethodConstants.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.core.constants; + +public interface SqlMethodConstants { + + /** + * 根据ID更新所有字段 + */ + String UPDATE_ALL_COLUMN_BY_ID = "updateAllColumnById"; + + /** + * 更新所有字段 + */ + String UPDATE_ALL_COLUMN = "updateAllColumn"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/controller/BaseController.java b/web-starter/src/main/java/com/lframework/starter/web/core/controller/BaseController.java new file mode 100644 index 0000000..31c41c9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/controller/BaseController.java @@ -0,0 +1,75 @@ +package com.lframework.starter.web.core.controller; + +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.constants.MybatisConstants; +import com.lframework.starter.web.core.vo.PageVo; + +/** + * BaseController + * + * @author zmj + */ +public abstract class BaseController { + + /** + * 获取当前页码 + * + * @param vo + * @return + */ + public int getPageIndex(PageVo vo) { + + if (ObjectUtil.isNull(vo) || ObjectUtil.isNull(vo.getPageIndex()) || vo.getPageIndex() <= 0) { + return MybatisConstants.DEFAULT_PAGE_INDEX; + } + + return vo.getPageIndex(); + } + + /** + * 获取每页条数 + * + * @param vo + * @return + */ + public int getPageSize(PageVo vo) { + + if (ObjectUtil.isNull(vo) || ObjectUtil.isNull(vo.getPageSize()) || vo.getPageSize() <= 0) { + return MybatisConstants.DEFAULT_PAGE_SIZE; + } + + return vo.getPageSize(); + } + + /** + * 获取当前页码 + * + * @return + */ + public int getPageIndex() { + + return getPageIndex(null); + } + + /** + * 获取每页条数 + * + * @return + */ + public int getPageSize() { + + return getPageSize(null); + } + + /** + * 获取当前登录用户信息 + * + * @return + */ + public AbstractUserDetails getCurrentUser() { + + return SecurityUtil.getCurrentUser(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/controller/DefaultBaseController.java b/web-starter/src/main/java/com/lframework/starter/web/core/controller/DefaultBaseController.java new file mode 100644 index 0000000..9513e02 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/controller/DefaultBaseController.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.controller; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.vo.openapi.OpenApiReqVo; + +/** + * 具有Security能力的BaseController + * + * @author zmj + */ +public abstract class DefaultBaseController extends BaseController { + + public T getOpenApiVo(OpenApiReqVo vo, Class clazz) { + if (StringUtil.isBlank(vo.getParams())) { + return null; + } + return JsonUtil.parseObject(vo.getParams(), clazz); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/dto/BaseDto.java b/web-starter/src/main/java/com/lframework/starter/web/core/dto/BaseDto.java new file mode 100644 index 0000000..6e77ce9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/dto/BaseDto.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.core.dto; + +/** + * Dto基类 + * + * @author zmj + */ +public interface BaseDto { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCaptchaDto.java b/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCaptchaDto.java new file mode 100644 index 0000000..160c406 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCaptchaDto.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.core.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 生成验证码Dto + * + * @author zmj + */ +@Data +public class GenerateCaptchaDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 流水号 + */ + @Schema(description = "流水号") + private String sn; + + /** + * 图片文件Base64 + */ + @Schema(description = "图片文件Base64") + private String image; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCodeDto.java b/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCodeDto.java new file mode 100644 index 0000000..c7a052a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/dto/GenerateCodeDto.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.core.dto; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class GenerateCodeDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "GenerateCodeDto"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Integer id; + + /** + * 规则配置 + */ + private String configStr; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/dto/VoidDto.java b/web-starter/src/main/java/com/lframework/starter/web/core/dto/VoidDto.java new file mode 100644 index 0000000..d4fcb14 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/dto/VoidDto.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.core.dto; + +import lombok.Data; + +@Data +public final class VoidDto implements BaseDto { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/entity/BaseEntity.java b/web-starter/src/main/java/com/lframework/starter/web/core/entity/BaseEntity.java new file mode 100644 index 0000000..fd9d7e5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/entity/BaseEntity.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.core.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 直接使用BaseEntity insert/update时 成员变量会自动赋值(如果有值,不会覆盖) + * + * @author zmj + */ +@Data +public abstract class BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/enums/BaseEnum.java b/web-starter/src/main/java/com/lframework/starter/web/core/enums/BaseEnum.java new file mode 100644 index 0000000..798daab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/enums/BaseEnum.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.core.enums; + +import java.io.Serializable; + +/** + * Enum基类 + * + * @param + * @author zmj + */ +public interface BaseEnum extends Serializable { + + /** + * 获取枚举值 + * + * @return + */ + T getCode(); + + /** + * 获取描述 + * + * @return + */ + String getDesc(); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/ClearTenantEvent.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/ClearTenantEvent.java new file mode 100644 index 0000000..78a962b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/ClearTenantEvent.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.core.event; + +import org.springframework.context.ApplicationEvent; + +public class ClearTenantEvent extends ApplicationEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ClearTenantEvent(Object source) { + super(source); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEvent.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEvent.java new file mode 100644 index 0000000..8e5ef39 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEvent.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.core.event; + +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +/** + * 数据变动事件 + * + * @param + */ +public abstract class DataChangeEvent extends ApplicationEvent { + + @Getter + private T entity; + + @Getter + private DataChangeType type; + + public DataChangeEvent(Object source, T entity, DataChangeType type) { + super(source); + this.entity = entity; + this.type = type; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEventBuilder.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEventBuilder.java new file mode 100644 index 0000000..ed632e5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeEventBuilder.java @@ -0,0 +1,66 @@ +package com.lframework.starter.web.core.event; + +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.core.utils.ApplicationUtil; + +public class DataChangeEventBuilder { + + public static > void publishCreate( + Object source, + Class clazz, T entity) { + DataChangeEvent event = newInstance(source, clazz, entity, DataChangeType.CREATE); + ApplicationUtil.publishEvent(event); + } + + public static > R create( + Object source, + Class clazz, T entity) { + return newInstance(source, clazz, entity, DataChangeType.CREATE); + } + + public static > void publishUpdate( + Object source, + Class clazz, T entity) { + DataChangeEvent event = newInstance(source, clazz, entity, DataChangeType.UPDATE); + ApplicationUtil.publishEvent(event); + } + + public static > R update( + Object source, + Class clazz, T entity) { + return newInstance(source, clazz, entity, DataChangeType.UPDATE); + } + + public static > void publishLogicDelete( + Object source, + Class clazz, T entity) { + DataChangeEvent event = newInstance(source, clazz, entity, DataChangeType.LOGIC_DELETE); + ApplicationUtil.publishEvent(event); + } + + public static > R logicDelete( + Object source, + Class clazz, T entity) { + return newInstance(source, clazz, entity, DataChangeType.LOGIC_DELETE); + } + + public static > void publishDelete( + Object source, + Class clazz, T entity) { + DataChangeEvent event = newInstance(source, clazz, entity, DataChangeType.DELETE); + ApplicationUtil.publishEvent(event); + } + + public static > R delete( + Object source, + Class clazz, T entity) { + return newInstance(source, clazz, entity, DataChangeType.DELETE); + } + + private static > R newInstance( + Object source, + Class clazz, T entity, DataChangeType type) { + return ReflectUtil.newInstance(clazz, source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeType.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeType.java new file mode 100644 index 0000000..b99b309 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/DataChangeType.java @@ -0,0 +1,5 @@ +package com.lframework.starter.web.core.event; + +public enum DataChangeType { + CREATE, UPDATE, LOGIC_DELETE, DELETE +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/ReloadTenantEvent.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/ReloadTenantEvent.java new file mode 100644 index 0000000..6b8c039 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/ReloadTenantEvent.java @@ -0,0 +1,70 @@ +package com.lframework.starter.web.core.event; + +import org.springframework.context.ApplicationEvent; + +public class ReloadTenantEvent extends ApplicationEvent { + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * JDBC URL + */ + private String jdbcUrl; + + /** + * JDBC username + */ + private String jdbcUsername; + + /** + * JDBC password + */ + private String jdbcPassword; + + /** + * 驱动 + */ + private String driver = "com.mysql.cj.jdbc.Driver"; + + public ReloadTenantEvent(Object source, Integer tenantId, String jdbcUrl, String jdbcUsername, + String jdbcPassword) { + super(source); + this.tenantId = tenantId; + this.jdbcUrl = jdbcUrl; + this.jdbcUsername = jdbcUsername; + this.jdbcPassword = jdbcPassword; + } + + public ReloadTenantEvent(Object source, Integer tenantId, String jdbcUrl, String jdbcUsername, + String jdbcPassword, String driver) { + super(source); + this.tenantId = tenantId; + this.jdbcUrl = jdbcUrl; + this.jdbcUsername = jdbcUsername; + this.jdbcPassword = jdbcPassword; + this.driver = driver; + } + + public Integer getTenantId() { + return tenantId; + } + + public String getJdbcUrl() { + return jdbcUrl; + } + + public String getJdbcUsername() { + return jdbcUsername; + } + + public String getJdbcPassword() { + return jdbcPassword; + } + + public String getDriver() { + return driver; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/event/SetTenantEvent.java b/web-starter/src/main/java/com/lframework/starter/web/core/event/SetTenantEvent.java new file mode 100644 index 0000000..46edbac --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/event/SetTenantEvent.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.core.event; + +import org.springframework.context.ApplicationEvent; + +public class SetTenantEvent extends ApplicationEvent { + + /** + * 租户ID + */ + private Integer tenantId; + + public SetTenantEvent(Object source, Integer tenantId) { + super(source); + this.tenantId = tenantId; + } + + public Integer getTenantId() { + return tenantId; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/handlers/DefaultBaseEntityFillHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/DefaultBaseEntityFillHandler.java new file mode 100644 index 0000000..d2f80b4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/DefaultBaseEntityFillHandler.java @@ -0,0 +1,95 @@ +package com.lframework.starter.web.core.handlers; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.config.properties.DefaultSettingProperties; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.constants.MyBatisStringPool; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.function.Supplier; + +/** + * BaseEntity自动填充处理器 + * + * @author zmj + */ +@Slf4j +public class DefaultBaseEntityFillHandler implements MetaObjectHandler { + + @Autowired + private DefaultSettingProperties defaultSettingProperties; + + @Override + public void insertFill(MetaObject metaObject) { + + AbstractUserDetails user = SecurityUtil.getCurrentUser(); + if (ObjectUtil.isNotNull(user)) { + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_CREATE_BY, String.class, + user.getName()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY, String.class, + user.getName()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_CREATE_BY_ID, String.class, + user.getId()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY_ID, String.class, + user.getId()); + } else { + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_CREATE_BY, String.class, + defaultSettingProperties.getDefaultUserName()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY, String.class, + defaultSettingProperties.getDefaultUserName()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_CREATE_BY_ID, String.class, + defaultSettingProperties.getDefaultUserId()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY_ID, String.class, + defaultSettingProperties.getDefaultUserId()); + } + + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_CREATE_TIME, LocalDateTime.class, + LocalDateTime.now()); + this.strictInsertFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_TIME, LocalDateTime.class, + LocalDateTime.now()); + } + + @Override + public void updateFill(MetaObject metaObject) { + + AbstractUserDetails user = SecurityUtil.getCurrentUser(); + if (ObjectUtil.isNotNull(user)) { + this.strictUpdateFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY, String.class, + user.getName()); + this.strictUpdateFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY_ID, String.class, + user.getId()); + } else { + this.strictUpdateFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY, String.class, + defaultSettingProperties.getDefaultUserName()); + this.strictUpdateFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_BY_ID, String.class, + defaultSettingProperties.getDefaultUserName()); + } + + this.strictUpdateFill(metaObject, MyBatisStringPool.COLUMN_UPDATE_TIME, LocalDateTime.class, + LocalDateTime.now()); + } + + @Override + public MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, + Supplier fieldVal) { + if (MyBatisStringPool.COLUMN_UPDATE_BY.equals(fieldName) + || MyBatisStringPool.COLUMN_UPDATE_BY_ID.equals(fieldName) + || MyBatisStringPool.COLUMN_UPDATE_TIME.equals(fieldName)) { + // update时,无论当前是否有值什么情况 这三个值都会覆盖 + Object obj = fieldVal.get(); + if (Objects.nonNull(obj)) { + metaObject.setValue(fieldName, obj); + } + } else { + return MetaObjectHandler.super.strictFillStrategy(metaObject, fieldName, fieldVal); + } + + return this; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionConverter.java new file mode 100644 index 0000000..5193777 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionConverter.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.core.handlers.exception; + +import com.lframework.starter.common.exceptions.BaseException; + +public interface WebExceptionConverter { + + /** + * 最高优先级,用于处理没有子类的异常 + */ + int FIRST_ORDER = Integer.MIN_VALUE; + + /** + * 次高优先级,用于处理系统内定义的异常,如:ClientException、SysException。 + */ + int SECOND_ORDER = FIRST_ORDER + 100; + + /** + * 第三优先级,用于处理系统之外的框架定义的并且需要特定处理的异常,如:BindException。 + */ + int THIRD_ORDER = SECOND_ORDER + 100; + /** + * 最低优先级,用于处理范围最大的异常,如:Exception。 + *

+ * 当本层都没有处理的异常,会统一处理,如:Throwable。 + */ + int LAST_ORDER = Integer.MAX_VALUE; + + /** + * 是否匹配 + * + * @param e + * @return + */ + boolean isMatch(Throwable e); + + /** + * 转换异常 + * + * @param e + * @return + */ + BaseException convert(Throwable e); + + /** + * 优先级 值越小越靠前 + * + * @return + */ + default int getOrder() { + return FIRST_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionHandler.java b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionHandler.java new file mode 100644 index 0000000..6315f2d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/handlers/exception/WebExceptionHandler.java @@ -0,0 +1,122 @@ +package com.lframework.starter.web.core.handlers.exception; + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.components.resp.Response; +import com.lframework.starter.web.core.components.resp.ResponseErrorBuilder; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.ResponseUtil; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.HandlerMethod; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 异常处理器 + * + * @author zmj + */ +@Slf4j +@RestControllerAdvice +public class WebExceptionHandler { + + /** + * 处理Throwable + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(Throwable.class) + public Response throwableHandle(Throwable e, HttpServletRequest request) { + + Object bestMatchingHandler = request.getAttribute( + "org.springframework.web.servlet.HandlerMapping.bestMatchingHandler"); + HandlerMethod method = bestMatchingHandler instanceof HandlerMethod + ? (HandlerMethod) bestMatchingHandler + : createFallbackHandlerMethod(); + + this.logException(e, method); + + Collection converters = ApplicationUtil.getBeansOfType( + WebExceptionConverter.class).values(); + + BaseException ex = null; + converters = converters.stream().sorted(Comparator.comparingInt(WebExceptionConverter::getOrder)).collect( + Collectors.toList()); + + for (WebExceptionConverter converter : converters) { + if (converter.isMatch(e)) { + log.debug("WebExceptionConverter = {}", converter.getClass().getName()); + ex = converter.convert(e); + break; + } + } + if (ex == null) { + ex = new DefaultSysException("无法匹配WebExceptionConverter"); + } + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + protected void logException(Throwable e, HandlerMethod method) { + + if (e instanceof ClientException) { + if (log.isDebugEnabled()) { + String className = method.getBeanType().getName(); + String methodName = method.getMethod().getName(); + log.debug("className={}, methodName={}, 有异常产生", className, methodName, e); + } + } else { + String className = method.getBeanType().getName(); + String methodName = method.getMethod().getName(); + log.error("className={}, methodName={}, 有异常产生", className, methodName, e); + } + } + + protected void setResponseCode(BaseException e) { + + ResponseUtil.getResponse().setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + } + + private HandlerMethod createFallbackHandlerMethod() { + try { + Method m = WebExceptionHandler.class.getDeclaredMethod("getBuilder", Object.class); + return new HandlerMethod(this, m); + } catch (NoSuchMethodException ex) { + throw new IllegalStateException(ex); + } + } + + protected ResponseErrorBuilder getBuilder(Object bean) { + + Map builders = ApplicationUtil.getBeansOfType( + ResponseErrorBuilder.class); + ResponseErrorBuilder builder = null; + for (ResponseErrorBuilder value : builders.values()) { + if (value.isDefault()) { + builder = value; + break; + } + } + + for (ResponseErrorBuilder value : builders.values()) { + if (value.isMatch(bean)) { + builder = value; + break; + } + } + + return builder; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/impl/BaseMpServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/core/impl/BaseMpServiceImpl.java new file mode 100644 index 0000000..ad646fa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/impl/BaseMpServiceImpl.java @@ -0,0 +1,135 @@ +package com.lframework.starter.web.core.impl; + +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.enums.SqlMethod; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.*; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.web.core.constants.SqlMethodConstants; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.core.service.BaseMpService; +import org.apache.ibatis.binding.MapperMethod; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Objects; + +public abstract class BaseMpServiceImpl, T> extends ServiceImpl + implements BaseMpService { + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean update(Wrapper updateWrapper) { + T entity = null; + try { + if (updateWrapper instanceof AbstractWrapper) { + entity = (T) ((AbstractWrapper) updateWrapper).getEntityClass().newInstance(); + // 将所有的值设置为null + Field[] fields = ReflectUtil.getFields(entity.getClass()); + if (ArrayUtil.isNotEmpty(fields)) { + for (Field field : fields) { + if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + continue; + } + ReflectUtil.setFieldValue(entity, field, null); + } + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + + return super.update(entity, updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean saveOrUpdateAllColumnBatch(Collection entityList, int batchSize) { +// TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); + TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass()); + Assert.notNull(tableInfo, + "error: can not execute. because can not find cache of TableInfo for entity!"); + String keyProperty = tableInfo.getKeyProperty(); + Assert.notEmpty(keyProperty, + "error: can not execute. because can not find column for id from entity!"); + return SqlHelper.saveOrUpdateBatch( + getEntityClass(), + getMapperClass(), + this.log, + entityList, + batchSize, + (sqlSession, entity) -> { + Object idVal = ReflectionKit.getFieldValue(entity, keyProperty); + return StringUtils.checkValNull(idVal) + || CollectionUtils.isEmpty( + sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)); + }, + (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(getSqlStatement(SqlMethodConstants.UPDATE_ALL_COLUMN_BY_ID), param); + } + ); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean updateAllColumnBatchById(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethodConstants.UPDATE_ALL_COLUMN_BY_ID); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(sqlStatement, param); + }); + } + + @Override + public BaseMapper getBaseMpMapper() { + return baseMapper; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean saveOrUpdateAllColumn(T entity) { + if (null != entity) { + + TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass()); + Assert.notNull(tableInfo, + "error: can not execute. because can not find cache of TableInfo for entity!"); + String keyProperty = tableInfo.getKeyProperty(); + Assert.notEmpty(keyProperty, + "error: can not execute. because can not find column for id from entity!"); + Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty()); + return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) + ? save(entity) : updateAllColumnById(entity); + } + return false; + } + + /** + * 获取mapperStatementId + * + * @param sqlMethod 方法名 + * @return 命名id + * @since 3.4.0 + */ + protected String getSqlStatement(String sqlMethod) { + return getMapperClass().getName() + StringPool.DOT + sqlMethod; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean updateAllColumn(T entity, Wrapper updateWrapper) { + return SqlHelper.retBool(getBaseMapper().updateAllColumn(entity, updateWrapper)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/injectors/MybatisPlusUpdateAllColumnInjector.java b/web-starter/src/main/java/com/lframework/starter/web/core/injectors/MybatisPlusUpdateAllColumnInjector.java new file mode 100644 index 0000000..03d7440 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/injectors/MybatisPlusUpdateAllColumnInjector.java @@ -0,0 +1,112 @@ +package com.lframework.starter.web.core.injectors;//package com.lframework.starter.web.core.injectors; +// +//import static java.util.stream.Collectors.joining; +// +//import com.baomidou.mybatisplus.core.enums.SqlMethod; +//import com.baomidou.mybatisplus.core.injector.AbstractMethod; +//import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +//import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +//import com.baomidou.mybatisplus.core.metadata.TableInfo; +//import com.baomidou.mybatisplus.core.toolkit.Constants; +//import com.baomidou.mybatisplus.core.toolkit.StringPool; +//import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; +//import com.lframework.starter.web.core.constants.SqlMethodConstants; +//import java.util.List; +//import java.util.Objects; +//import java.util.function.Predicate; +//import lombok.Setter; +//import lombok.experimental.Accessors; +//import org.apache.ibatis.mapping.MappedStatement; +//import org.apache.ibatis.mapping.SqlSource; +// +//public class MybatisPlusUpdateAllColumnInjector extends DefaultSqlInjector { +// +// @Override +// public List getMethodList(Class mapperClass) { +// List methods = super.getMethodList(mapperClass); +// methods.add(new UpdateAllColumnById()); +// methods.add(new UpdateAllColumn()); +// return methods; +// } +// +// /** +// * 自定义更新所有字段的方法 +// */ +// static class UpdateAllColumnById extends AbstractMethod { +// +// /** +// * 字段筛选条件 +// */ +// @Setter +// @Accessors(chain = true) +// private Predicate predicate; +// +// @Override +// public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, +// TableInfo tableInfo) { +// SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID; +// final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true); +// String sqlSet = this.filterTableFieldInfo(tableInfo.getFieldList(), getPredicate(), +// i -> i.getSqlSet(true, Constants.ENTITY_DOT), StringPool.NEWLINE); +// sqlSet = SqlScriptUtils.convertSet(sqlSet); +// String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, +// tableInfo.getKeyColumn(), Constants.ENTITY_DOT + tableInfo.getKeyProperty(), additional); +// SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); +// return addUpdateMappedStatement(mapperClass, modelClass, +// SqlMethodConstants.UPDATE_ALL_COLUMN_BY_ID, sqlSource); +// } +// +// private Predicate getPredicate() { +// Predicate noLogic = t -> !t.isLogicDelete(); +// if (predicate != null) { +// return noLogic.and(predicate); +// } +// return noLogic; +// } +// } +// +// /** +// * 自定义更新所有字段的方法 +// */ +// static class UpdateAllColumn extends AbstractMethod { +// +// @Override +// public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, +// TableInfo tableInfo) { +// SqlMethod sqlMethod = SqlMethod.UPDATE; +// String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), +// sqlSet(true, true, tableInfo, true, Constants.ENTITY, Constants.ENTITY_DOT), +// sqlWhereEntityWrapper(true, tableInfo), sqlComment()); +// SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); +// return this.addUpdateMappedStatement(mapperClass, modelClass, +// SqlMethodConstants.UPDATE_ALL_COLUMN, sqlSource); +// } +// +// protected String sqlSet(boolean logic, boolean ew, TableInfo table, boolean judgeAliasNull, +// final String alias, +// final String prefix) { +// final String newPrefix = prefix == null ? StringPool.EMPTY : prefix; +// String sqlScript = table.getFieldList().stream() +// .filter(i -> { +// if (logic) { +// return !(table.isWithLogicDelete() && i.isLogicDelete()); +// } +// return true; +// }).map(i -> i.getSqlSet(true, newPrefix)).filter(Objects::nonNull) +// .collect(joining(StringPool.NEWLINE)); +// if (judgeAliasNull) { +// sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", alias), true); +// } +// if (ew) { +// sqlScript += StringPool.NEWLINE; +// sqlScript += SqlScriptUtils.convertIf( +// SqlScriptUtils.unSafeParam(Constants.U_WRAPPER_SQL_SET), +// String.format("%s != null and %s != null", Constants.WRAPPER, +// Constants.U_WRAPPER_SQL_SET), false); +// } +// sqlScript = SqlScriptUtils.convertSet(sqlScript); +// return sqlScript; +// } +// } +//} +// diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/CustomSortInterceptor.java b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/CustomSortInterceptor.java new file mode 100644 index 0000000..a4c5d4b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/CustomSortInterceptor.java @@ -0,0 +1,133 @@ +package com.lframework.starter.web.core.interceptors; + +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.vo.SortPageVo; +import lombok.extern.slf4j.Slf4j; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParser; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.parser.ParseException; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Slf4j +public class CustomSortInterceptor extends JsqlParserSupport implements InnerInterceptor { + + @Override + public void beforeQuery( + Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, + ResultHandler resultHandler, BoundSql boundSql) throws SQLException { + if (parameter instanceof Map) { + Map map = (Map) parameter; + List sortPageVos = map.values().stream() + .filter(t -> t instanceof SortPageVo).map(t -> (SortPageVo) t) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(sortPageVos)) { + return; + } + Map sortMap = this.convertSortMap(ms.getId()); + if (CollectionUtil.isEmpty(sortMap)) { + return; + } + + StringBuilder sqlBuilder = new StringBuilder("ORDER BY "); + + List orderBySqlElements = sortPageVos.stream() + .filter(t -> sortMap.containsKey(t.getSortField())).map( + t -> sortMap.get(t.getSortField()) + " " + ( + "asc".equalsIgnoreCase(t.getSortOrder()) ? "ASC" : "DESC")).distinct() + .collect( + Collectors.toList()); + + if (CollectionUtil.isEmpty(orderBySqlElements)) { + return; + } + + // order by code asc, name desc + String sqlProvider = sqlBuilder.append(StringUtil.join(",", orderBySqlElements)) + .toString(); + + CCJSqlParser parser = CCJSqlParserUtil.newParser(sqlProvider); + + PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); + + String sql = mpBs.sql(); + try { + Statement statement = CCJSqlParserUtil.parse(sql); + PlainSelect plainSelect = (PlainSelect) ((Select) statement).getSelectBody(); + plainSelect.setOrderByElements(parser.OrderByElements()); + mpBs.sql(statement.toString()); + } catch (JSQLParserException | ParseException e) { + log.error("Failed to process, Error SQL: {}", sql); + log.error(e.getMessage(), e); + } + } + } + + private Map convertSortMap(String statementId) { + // 获取Mapper执行方法上的注解 + Method mapperMethod = null; + try { + mapperMethod = this.findMapperMethod(this.convertMsId(statementId)); + } catch (ClassNotFoundException e) { + return null; + } + if (mapperMethod == null) { + return null; + } + Sorts sorts = mapperMethod.getAnnotation(Sorts.class); + + if (sorts != null) { + Sort[] sortList = sorts.value(); + Map sortKeyMap = new HashMap<>(sortList.length); + for (Sort sort : sortList) { + if (sort.autoParse()) { + sortKeyMap.put(sort.value(), (StringUtil.isEmpty(sort.alias()) ? "" : (sort.alias() + ".")) + StringUtil.toUnderlineCase(sort.value())); + } else { + sortKeyMap.put(sort.value(), StringUtil.isEmpty(sort.alias()) ? "" : sort.alias()); + } + } + + return sortKeyMap; + } + + return null; + } + + private String convertMsId(String id) { + return id; + } + + private Method findMapperMethod(String statementId) + throws ClassNotFoundException { + int lastDotIndex = statementId.lastIndexOf("."); + String className = statementId.substring(0, lastDotIndex); + String methodName = statementId.substring(lastDotIndex + 1); + + Class mapperInterface = Class.forName(className); + return Arrays.stream(mapperInterface.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .findFirst() + .orElse(null); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/LoginInterceptor.java b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/LoginInterceptor.java new file mode 100644 index 0000000..ba126b0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/LoginInterceptor.java @@ -0,0 +1,70 @@ +package com.lframework.starter.web.core.interceptors; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.annotation.AnnotationUtil; +import com.lframework.starter.common.exceptions.impl.AuthExpiredException; +import com.lframework.starter.web.core.annotations.openapi.OpenApi; +import com.lframework.starter.web.core.components.security.PermitAllService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +@Slf4j +public class LoginInterceptor implements HandlerInterceptor { + + private PermitAllService permitAllService; + + public LoginInterceptor(PermitAllService permitAllService) { + + this.permitAllService = permitAllService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + if ("/error".equals(request.getRequestURI())) { + return true; + } + + if (permitAllService.isMatch(request)) { + log.debug("uri={},无需登录验证", request.getRequestURI()); + return true; + } + + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + OpenApi openApi = null; + if (handlerMethod.hasMethodAnnotation(OpenApi.class)) { + openApi = handlerMethod.getMethodAnnotation(OpenApi.class); + } else if (AnnotationUtil.hasAnnotation(handlerMethod.getBeanType(), OpenApi.class)) { + openApi = AnnotationUtil.getAnnotation(handlerMethod.getBeanType(), OpenApi.class); + } + if (openApi != null) { + log.debug("uri={},无需登录验证", request.getRequestURI()); + permitAllService.addMatch(request); + return true; + } + } + + String requestToken = request.getHeader("X-Auth-Token"); + Object loginId = null; + try { + loginId = StpUtil.getLoginIdDefaultNull(); + } catch (Exception ignore) { + // ignore + } + log.info("LoginInterceptor check, uri={}, token={}, loginId={}", request.getRequestURI(), + requestToken, loginId); + + try { + StpUtil.checkLogin(); + } catch (Exception e) { + throw new AuthExpiredException(); + } + + return true; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/TenantInterceptorImpl.java b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/TenantInterceptorImpl.java new file mode 100644 index 0000000..bb90e27 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/interceptors/TenantInterceptorImpl.java @@ -0,0 +1,71 @@ +package com.lframework.starter.web.core.interceptors; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.components.tenant.TenantInterceptor; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.service.TenantService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Slf4j +@AllArgsConstructor +public class TenantInterceptorImpl implements TenantInterceptor { + + private TenantService tenantService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + // 获取租户ID有三种途径 + // 1、读取header中的X-Tenant-Id + // 2、根据域名获取租户ID + // 3、根据登录信息获取租户ID + // 优先级:3 > 2 > 1 + + // 从登录信息中获取 + Integer tenantId = SecurityUtil.getCurrentTenantId(); + if (tenantId != null) { + TenantContextHolder.setTenantId(tenantId); + return true; + } + + // 根据域名获取 + String serverName = request.getServerName(); + List tenantList = tenantService.findAll(); + if (CollectionUtil.isNotEmpty(tenantList)) { + for (Tenant tenant : tenantList) { + if (serverName.equals(tenant.getServerName())) { + TenantContextHolder.setTenantId(tenant.getId()); + return true; + } + } + } + + // 读取header中的X-Tenant-Id + String tenantIdStr = request.getHeader("X-Tenant-Id"); + if (RegUtil.isMatch(PatternPool.PATTERN_IS_INTEGER, tenantIdStr)) { + Integer targetTenantId = Integer.valueOf(tenantIdStr); + if (tenantList.stream().anyMatch(t -> t.getId().equals(targetTenantId))) { + TenantContextHolder.setTenantId(targetTenantId); + return true; + } + } + + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, + Object handler, Exception ex) throws Exception { + TenantContextHolder.clearTenantId(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/listeners/TenantListener.java b/web-starter/src/main/java/com/lframework/starter/web/core/listeners/TenantListener.java new file mode 100644 index 0000000..0fbc61c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/listeners/TenantListener.java @@ -0,0 +1,59 @@ +package com.lframework.starter.web.core.listeners; + +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; +import com.lframework.starter.web.core.event.ClearTenantEvent; +import com.lframework.starter.web.core.event.ReloadTenantEvent; +import com.lframework.starter.web.core.event.SetTenantEvent; +import com.lframework.starter.web.core.utils.DataSourceUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; + +import javax.sql.DataSource; + +public class TenantListener { + + public static class ReloadTenantListener implements ApplicationListener, + Ordered { + + @Autowired + private DynamicDataSourceProperties dynamicDataSourceProperties; + + @Autowired + private DataSource dataSource; + + @Override + public void onApplicationEvent(ReloadTenantEvent event) { + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource() + .get("master"); + DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource; + ds.addDataSource(String.valueOf(event.getTenantId()), + DataSourceUtil.createDataSource(dataSourceProperty, event.getJdbcUrl(), + event.getJdbcUsername(), event.getJdbcPassword(), event.getDriver())); + } + + @Override + public int getOrder() { + return Integer.MIN_VALUE; + } + } + + public static class SetTenantListener implements ApplicationListener { + + @Override + public void onApplicationEvent(SetTenantEvent event) { + DynamicDataSourceContextHolder.push(String.valueOf(event.getTenantId())); + } + } + + public static class ClearTenantListener implements ApplicationListener { + + @Override + public void onApplicationEvent(ClearTenantEvent event) { + DynamicDataSourceContextHolder.clear(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/mapper/BaseMapper.java b/web-starter/src/main/java/com/lframework/starter/web/core/mapper/BaseMapper.java new file mode 100644 index 0000000..5c1d116 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/mapper/BaseMapper.java @@ -0,0 +1,72 @@ +package com.lframework.starter.web.core.mapper; + +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import org.apache.ibatis.annotations.Param; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * BaseMapper 所有Mapper的基类 + * + * @param + * @author zmj + */ +public interface BaseMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + Logger LOGGER = LoggerFactory.getLogger(BaseMapper.class); + + /** + * 根据 whereEntity 条件,更新记录 + * + * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) + * @return + */ + default int update(Wrapper updateWrapper) { + T entity = null; + try { + if (updateWrapper instanceof AbstractWrapper) { + entity = (T) ((AbstractWrapper) updateWrapper).getEntityClass().newInstance(); + // 将所有的值设置为null + Field[] fields = ReflectUtil.getFields(entity.getClass()); + if (ArrayUtil.isNotEmpty(fields)) { + for (Field field : fields) { + if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + continue; + } + ReflectUtil.setFieldValue(entity, field, null); + } + } + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + + return update(entity, updateWrapper); + } + + /** + * 根据ID更新所有字段 此方法不会忽略null值字段 + * + * @param entity + * @return + */ + int updateAllColumnById(@Param(Constants.ENTITY) T entity); + + /** + * 根据 whereEntity 条件,更新记录 此方法不会忽略null值字段 + * + * @param entity + * @return + */ + int updateAllColumn(@Param(Constants.ENTITY) T entity, + @Param(Constants.WRAPPER) Wrapper updateWrapper); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseMpService.java b/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseMpService.java new file mode 100644 index 0000000..d1aab65 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseMpService.java @@ -0,0 +1,140 @@ +package com.lframework.starter.web.core.service; + +import cn.hutool.core.bean.copier.CopyOptions; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.lframework.starter.common.utils.BeanUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.constants.MyBatisStringPool; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.Collection; + +/** + * Service基类 + * + * @author zmj + */ +public interface BaseMpService extends IService { + + default S getThis(Class clazz) { + + return ApplicationUtil.getBean(clazz); + } + + /** + * 清除缓存 仅适用于key是常量值的缓存 + */ + default void cleanCaches() { + BaseMpService thisService = getThis(getClass()); + thisService.cleanCacheByKey(null); + } + + /** + * 根据Key清除缓存 + * + * @param key + */ + default void cleanCacheByKey(Serializable key) { + + } + + /** + * 批量根据Key清除缓存 + * + * @param keys + */ + default void cleanCacheByKeys(Collection keys) { + BaseMpService thisService = getThis(getClass()); + if (CollectionUtil.isNotEmpty(keys)) { + keys.forEach(thisService::cleanCacheByKey); + } + } + + // 这里只有复制新增记录的内置字段,因为修改记录的内置字段无论何时都会被覆盖 + + /** + * 复制新增记录内置字段 + * + * @param source + * @param target + */ + default void copyCreateColumns(T source, T target) { + CopyOptions options = CopyOptions.create() + .setPropertiesFilter((k, v) -> MyBatisStringPool.COLUMN_CREATE_BY.equals(k.getName()) + || MyBatisStringPool.COLUMN_CREATE_BY_ID.equals(k.getName()) + || MyBatisStringPool.COLUMN_CREATE_TIME.equals(k.getName())); + BeanUtil.copyProperties(source, target, options); + } + + /** + * 批量修改插入 + * + * @param entityList 实体对象集合 + */ + @Transactional(rollbackFor = Exception.class) + default boolean saveOrUpdateAllColumnBatch(Collection entityList) { + return saveOrUpdateAllColumnBatch(entityList, IService.DEFAULT_BATCH_SIZE); + } + + /** + * 批量修改插入 + * + * @param entityList 实体对象集合 + * @param batchSize 每次的数量 + */ + boolean saveOrUpdateAllColumnBatch(Collection entityList, int batchSize); + + /** + * 根据ID 批量更新 + * + * @param entityList 实体对象集合 + */ + @Transactional(rollbackFor = Exception.class) + default boolean updateAllColumnBatchById(Collection entityList) { + return updateAllColumnBatchById(entityList, IService.DEFAULT_BATCH_SIZE); + } + + /** + * 根据ID 批量更新 + * + * @param entityList 实体对象集合 + * @param batchSize 更新批次数量 + */ + boolean updateAllColumnBatchById(Collection entityList, int batchSize); + + /** + * TableId 注解存在更新记录,否插入一条记录 + * + * @param entity 实体对象 + */ + boolean saveOrUpdateAllColumn(T entity); + + /** + * 根据 ID 选择修改 + * + * @param entity 实体对象 + */ + default boolean updateAllColumnById(T entity) { + return SqlHelper.retBool(getBaseMpMapper().updateAllColumnById(entity)); + } + + /** + * 获取对应 entity 的 BaseMapper + * + * @return BaseMapper + */ + BaseMapper getBaseMpMapper(); + + /** + * 根据 whereEntity 条件,更新记录 + * + * @param entity 实体对象 + * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper} + */ + boolean updateAllColumn(T entity, Wrapper updateWrapper); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseService.java b/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseService.java new file mode 100644 index 0000000..201b4c6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/service/BaseService.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.core.service; + +import java.io.Serializable; + +public interface BaseService { + + /** + * 根据Key清除缓存 + * + * @param key + */ + default void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/ApplicationUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ApplicationUtil.java new file mode 100644 index 0000000..26d037f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ApplicationUtil.java @@ -0,0 +1,177 @@ +package com.lframework.starter.web.core.utils; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.Validator; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.core.env.Environment; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * Spring应用上下文工具类 + * 提供Spring应用上下文访问功能,支持Bean获取、属性获取、事件发布等 + * 包括Bean管理、配置属性访问、应用事件发布等功能 + * + * @author lframework@163.com + */ +public class ApplicationUtil implements ApplicationContextAware { + + private static ApplicationContext APPLICATION_CONTEXT; + + /** + * 安全获取Bean(按名称) + * 获取指定名称的Bean,如果不存在则返回null + * + * @param beanName Bean名称,不能为null + * @return Bean实例,如果不存在则返回null + */ + public static Object safeGetBean(String beanName) { + + try { + return APPLICATION_CONTEXT.getBean(beanName); + } catch (NoSuchBeanDefinitionException e) { + return null; + } + } + + /** + * 安全获取Bean(按类型) + * 获取指定类型的Bean,如果不存在则返回null + * + * @param clazz Bean类型,不能为null + * @param Bean类型 + * @return Bean实例,如果不存在则返回null + */ + public static T safeGetBean(Class clazz) { + + try { + return APPLICATION_CONTEXT.getBean(clazz); + } catch (NoSuchBeanDefinitionException e) { + return null; + } + } + + /** + * 获取Bean(按名称) + * 获取指定名称的Bean,如果不存在则抛出异常 + * + * @param beanName Bean名称,不能为null + * @return Bean实例 + * @throws NoSuchBeanDefinitionException 当Bean不存在时抛出 + */ + public static Object getBean(String beanName) { + + return APPLICATION_CONTEXT.getBean(beanName); + } + + /** + * 获取Bean(按类型) + * 获取指定类型的Bean,如果不存在则抛出异常 + * + * @param clazz Bean类型,不能为null + * @param Bean类型 + * @return Bean实例 + * @throws NoSuchBeanDefinitionException 当Bean不存在时抛出 + */ + public static T getBean(Class clazz) { + + return APPLICATION_CONTEXT.getBean(clazz); + } + + /** + * 获取指定类型的所有Bean + * 获取指定类型的所有Bean实例,以Map形式返回 + * + * @param clazz Bean类型,不能为null + * @param Bean类型 + * @return Bean名称到实例的映射,如果获取失败则返回空Map + */ + public static Map getBeansOfType(Class clazz) { + + try { + return APPLICATION_CONTEXT.getBeansOfType(clazz); + } catch (BeansException e) { + return Collections.EMPTY_MAP; + } + } + + /** + * 发布应用事件 + * 发布Spring应用事件,触发相关监听器 + * + * @param event 要发布的事件,不能为null + */ + public static void publishEvent(ApplicationEvent event) { + + APPLICATION_CONTEXT.publishEvent(event); + } + + /** + * 获取配置属性 + * 获取指定键的配置属性值 + * + * @param key 属性键,不能为null + * @return 属性值,如果不存在则返回null + */ + public static String getProperty(String key) { + + return APPLICATION_CONTEXT.getEnvironment().getProperty(key); + } + + /** + * 获取必需的配置属性 + * 获取指定键的配置属性值,如果不存在则抛出异常 + * + * @param key 属性键,不能为null + * @return 属性值 + * @throws IllegalStateException 当属性不存在时抛出 + */ + public static String getRequiredProperty(String key) { + + return APPLICATION_CONTEXT.getEnvironment().getRequiredProperty(key); + } + + /** + * 解析占位符 + * 解析字符串中的占位符为实际值 + * + * @param s 包含占位符的字符串,不能为null + * @return 解析后的字符串 + */ + public static String resolvePlaceholders(String s) { + + return APPLICATION_CONTEXT.getEnvironment().resolvePlaceholders(s); + } + + /** + * 验证对象 + * 使用JSR-303验证注解验证对象 + * + * @param obj 要验证的对象,不能为null + * @throws ConstraintViolationException 当验证失败时抛出 + */ + public static void validate(Object obj) { + Validator validator = getBean(Validator.class); + Set> errors = validator.validate(obj); + if (errors != null && errors.size() > 0) { + throw new ConstraintViolationException("参数校验失败!", errors); + } + } + + public static Environment getEnv() { + return APPLICATION_CONTEXT.getEnvironment(); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + + APPLICATION_CONTEXT = applicationContext; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/BoUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/BoUtil.java new file mode 100644 index 0000000..273678b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/BoUtil.java @@ -0,0 +1,146 @@ +package com.lframework.starter.web.core.utils; + +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.EnumUtil; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.BeanUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.web.core.annotations.constants.EncryType; +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.annotations.convert.IgnoreConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.enums.BaseEnum; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 业务对象转换工具类 + * 提供DTO到BO的转换功能,支持字段忽略、枚举转换、加密转换等 + * 包括对象属性复制、字段转换、注解处理等功能 + * + * @author lframework@163.com + */ +public class BoUtil { + + private static final Map, CopyOptions> OPTIONS; + + static { + OPTIONS = new HashMap<>(); + } + + public static B convert(T source, B target, + SFunction... columns) { + + if (source == null) { + return null; + } + + if (target == null) { + return null; + } + + BeanUtil.copyProperties(source, target, buildCopyOptions(source, target, columns)); + + return target; + } + + private static CopyOptions buildCopyOptions(T source, + B target, + SFunction... columns) { + if (OPTIONS.containsKey(target.getClass())) { + return OPTIONS.get(target.getClass()); + } + + synchronized (BoUtil.class) { + if (OPTIONS.containsKey(target.getClass())) { + return OPTIONS.get(target.getClass()); + } + + List columnNames = new ArrayList<>(); + if (!ArrayUtil.isEmpty(columns)) { + for (int i = 0; i < columns.length; i++) { + columnNames.add(ReflectUtil.getFieldName(columns[i])); + } + } + + Map enumFieldNames = new HashMap<>(); + Map> enumNameMap = new HashMap<>(); + Map encryptFieldNames = new HashMap<>(); + Class clazz = target.getClass(); + Field[] fields = ReflectUtil.getFields(clazz); + if (ArrayUtil.isNotEmpty(fields)) { + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + IgnoreConvert ignore = field.getAnnotation(IgnoreConvert.class); + if (ignore != null) { + columnNames.add(field.getName()); + // 如果忽略了,后面的检查就不需要了 + continue; + } + + EnumConvert enumConvert = field.getAnnotation(EnumConvert.class); + if (enumConvert != null) { + String fieldName = field.getName(); + Field srcField = ReflectUtil.getField(source.getClass(), fieldName); + if (srcField != null) { + if (ClassUtil.isAssignable(Enum.class, srcField.getType()) && ClassUtil + .isAssignable(BaseEnum.class, srcField.getType())) { + List codes = EnumUtil + .getFieldValues((Class>) srcField.getType(), "code"); + + List enumNames = EnumUtil.getNames((Class>) srcField.getType()); + enumNameMap.put(field.getName(), enumNames); + + enumFieldNames.put(field.getName(), ArrayUtil.toArray(codes, Object.class)); + } + } + } + EncryptConvert encryptConvert = field.getAnnotation(EncryptConvert.class); + if (encryptConvert != null) { + EncryType encryType = encryptConvert.type(); + String fieldName = field.getName(); + encryptFieldNames.put(fieldName, encryType); + } + } + } + + CopyOptions copyOptions = CopyOptions.create() + .setIgnoreProperties(ArrayUtil.toArray(columnNames, String.class)) + .setFieldValueEditor((s, v) -> { + + if (enumFieldNames.containsKey(s)) { + if (v != null) { + if (v instanceof CharSequence) { + // 枚举值是字符串时 + return enumFieldNames.get(s)[enumNameMap.get(s).indexOf(v)]; + } else { + // 这里只能当做是数字,enumConvert只支持两种形式 + return enumFieldNames.get(s)[Integer.parseInt(String.valueOf(v))]; + } + } + } + + if (encryptFieldNames.containsKey(s)) { + if (v instanceof CharSequence) { + return FieldEncryptUtil.encrypt((CharSequence) v, encryptFieldNames.get(s)); + } + } + + return v; + }); + + OPTIONS.put(target.getClass(), copyOptions); + + return copyOptions; + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/CacheUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/CacheUtil.java new file mode 100644 index 0000000..56eac7c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/CacheUtil.java @@ -0,0 +1,72 @@ +package com.lframework.starter.web.core.utils; + +import org.springframework.cache.CacheManager; + +/** + * 缓存工具类 + * 基于SpringCache提供缓存操作功能,支持缓存的增删改查 + * 包括缓存获取、存储、删除等基本操作 + * + * @author lframework@163.com + */ +public class CacheUtil { + + private static CacheManager cacheManager = ApplicationUtil.getBean(CacheManager.class); + + /** + * 获取缓存值 + * 从指定缓存中获取指定键的值 + * + * @param cacheName 缓存名称,不能为null + * @param key 缓存键,不能为null + * @param clazz 值类型,不能为null + * @param 值类型 + * @return 缓存值,如果不存在则返回null + */ + public static T get(String cacheName, Object key, Class clazz) { + + return cacheManager.getCache(cacheName).get(key, clazz); + } + + /** + * 存储缓存值 + * 将键值对存储到指定缓存中 + * + * @param cacheName 缓存名称,不能为null + * @param key 缓存键,不能为null + * @param value 缓存值,可以为null + */ + public static void put(String cacheName, Object key, Object value) { + + cacheManager.getCache(cacheName).put(key, value); + } + + /** + * 存储非空缓存值 + * 只有当值不为空时才存储到缓存中 + * + * @param cacheName 缓存名称,不能为null + * @param key 缓存键,不能为null + * @param value 缓存值,如果为空则不存储 + */ + public static void putIfNotEmpty(String cacheName, Object key, Object value) { + + if (ValidateUtil.isEmpty(value)) { + return; + } + + put(cacheName, key, value); + } + + /** + * 删除缓存值 + * 从指定缓存中删除指定键的值 + * + * @param cacheName 缓存名称,不能为null + * @param key 缓存键,不能为null + */ + public static void evict(String cacheName, Object key) { + + cacheManager.getCache(cacheName).evict(key); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/CronUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/CronUtil.java new file mode 100644 index 0000000..e02b8ec --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/CronUtil.java @@ -0,0 +1,83 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.quartz.CronExpression; + +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * Cron表达式工具类 + * 提供Cron表达式生成和匹配功能,支持时间到Cron表达式的转换 + * 包括日期时间Cron生成、Cron表达式匹配验证等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class CronUtil { + + /** + * 根据日期时间生成Cron表达式 + * 生成指定日期时间的一次性执行Cron表达式 + * + * @param dateTime 指定的日期时间,不能为null + * @return Cron表达式字符串 + */ + public static String getDateTimeCron(LocalDateTime dateTime) { + + return dateTime.getSecond() + " " + dateTime.getMinute() + " " + dateTime.getHour() + " " + + dateTime.getDayOfMonth() + " " + dateTime.getMonthValue() + " ? " + dateTime.getYear(); + } + + /** + * 根据日期生成Cron表达式(当天00:00:00) + * 生成指定日期当天凌晨执行的Cron表达式 + * + * @param date 指定的日期,不能为null + * @return Cron表达式字符串 + */ + public static String getDateCron(LocalDate date) { + + return "0 0 0 " + date.getDayOfMonth() + " " + date.getMonthValue() + " ? " + date.getYear(); + } + + /** + * 根据日期生成Cron表达式(当天23:59:59) + * 生成指定日期当天最后一秒执行的Cron表达式 + * + * @param date 指定的日期,不能为null + * @return Cron表达式字符串 + */ + public static String getDateMaxCron(LocalDate date) { + + return "59 59 23 " + date.getDayOfMonth() + " " + date.getMonthValue() + " ? " + date.getYear(); + } + + /** + * 验证Cron表达式是否匹配指定时间 + * 检查给定的Cron表达式是否在指定时间执行 + * + * @param cron Cron表达式,不能为null或空 + * @param dateTime 要验证的日期时间,不能为null + * @return true-匹配,false-不匹配或Cron表达式无效 + */ + public static Boolean match(String cron, LocalDateTime dateTime) { + if (StringUtil.isBlank(cron) || dateTime == null) { + return false; + + } + + CronExpression exp = null; + try { + exp = new CronExpression(cron); + } catch (ParseException e) { + log.error(e.getMessage(), e); + return false; + } + + return exp.isSatisfiedBy(DateUtil.toDate(dateTime)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/DataSourceUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/DataSourceUtil.java new file mode 100644 index 0000000..48e2925 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/DataSourceUtil.java @@ -0,0 +1,137 @@ +package com.lframework.starter.web.core.utils; + +import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.lframework.starter.common.utils.BeanUtil; +import com.lframework.starter.common.utils.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.support.JdbcUtils; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DriverManager; + +/** + * 数据源工具类 提供动态数据源创建和配置功能,支持多数据源管理 包括数据源属性创建、数据源实例创建等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class DataSourceUtil { + + /** + * 默认数据源驱动类 MySQL 8.0+ 的JDBC驱动类 + */ + public static final String DEFAULT_DATASOURCE_DRIVER = "com.mysql.cj.jdbc.Driver"; + + /** + * 创建数据源属性(使用默认驱动) 基于现有数据源属性创建新的数据源属性 + * + * @param sourceProperty 源数据源属性,不能为null + * @param url 数据库URL,不能为null + * @param username 用户名,不能为null + * @param password 密码,不能为null + * @return 新的数据源属性 + */ + public static DataSourceProperty createDataSourceProperty(DataSourceProperty sourceProperty, + String url, + String username, + String password) { + return createDataSourceProperty(sourceProperty, url, username, password, + DEFAULT_DATASOURCE_DRIVER); + } + + /** + * 创建数据源属性(指定驱动) 基于现有数据源属性创建新的数据源属性 + * + * @param sourceProperty 源数据源属性,不能为null + * @param url 数据库URL,不能为null + * @param username 用户名,不能为null + * @param password 密码,不能为null + * @param driver 驱动类名,不能为null + * @return 新的数据源属性 + */ + public static DataSourceProperty createDataSourceProperty(DataSourceProperty sourceProperty, + String url, + String username, + String password, String driver) { + String[] tmpArr = sourceProperty.getUrl().split("\\?"); + String urlParams = ""; + if (tmpArr.length == 2) { + urlParams = tmpArr[1]; + } + + DataSourceProperty property = new DataSourceProperty(); + BeanUtil.copyProperties(sourceProperty, property, "poolName", "type", "driverClassName", + "url", "password", "jndiName", "publicKey"); + property.setUsername(username); + property.setPassword(password); + if (StringUtil.isNotBlank(urlParams)) { + if (url.contains("?")) { + property.setUrl(url + (StringUtil.isNotBlank(urlParams) ? "&" + urlParams : "")); + } else { + property.setUrl(url + (StringUtil.isNotBlank(urlParams) ? "?" + urlParams : "")); + } + } else { + property.setUrl(url); + } + property.setDriverClassName(driver); + + return property; + } + + /** + * 创建数据源(使用默认驱动) 基于数据源属性创建数据源实例 + * + * @param sourceProperty 源数据源属性,不能为null + * @param url 数据库URL,不能为null + * @param username 用户名,不能为null + * @param password 密码,不能为null + * @return 数据源实例 + */ + public static DataSource createDataSource(DataSourceProperty sourceProperty, String url, + String username, + String password) { + + return createDataSource(sourceProperty, url, username, password, DEFAULT_DATASOURCE_DRIVER); + } + + /** + * 创建数据源(指定驱动) 基于数据源属性创建数据源实例 + * + * @param sourceProperty 源数据源属性,不能为null + * @param url 数据库URL,不能为null + * @param username 用户名,不能为null + * @param password 密码,不能为null + * @param driver 驱动类名,不能为null + * @return 数据源实例 + */ + public static DataSource createDataSource(DataSourceProperty sourceProperty, String url, + String username, + String password, String driver) { + + BasicDataSourceCreator basicDataSourceCreator = ApplicationUtil.getBean( + BasicDataSourceCreator.class); + + return basicDataSourceCreator.createDataSource( + createDataSourceProperty(sourceProperty, url, username, password, driver)); + } + + /** + * 验证数据源连接 + * + * @return + */ + public static boolean validConnection(String url, String username, String password) { + Connection conn = null; + try { + conn = DriverManager.getConnection(url, username, password); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + JdbcUtils.closeConnection(conn); + } + return false; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/EncryptUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/EncryptUtil.java new file mode 100644 index 0000000..b11629c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/EncryptUtil.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.core.utils; + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.symmetric.AES; +import cn.hutool.crypto.symmetric.SymmetricAlgorithm; +import com.lframework.starter.web.config.properties.SecretProperties; + +/** + * 加密工具类 + * 提供字符串加密解密功能,基于AES算法进行数据加密 + * 包括字符串加密、解密、密钥生成等功能 + * + * @author lframework@163.com + */ +public class EncryptUtil { + + /** + * 字符串加密(使用默认配置) + * 使用应用配置中的密钥进行AES加密 + * + * @param s 要加密的字符串,不能为null + * @return 加密后的十六进制字符串 + */ + public static String encrypt(String s) { + SecretProperties properties = ApplicationUtil.getBean(SecretProperties.class); + + return encrypt(s, properties); + } + + /** + * 字符串加密(指定配置) + * 使用指定的密钥配置进行AES加密 + * + * @param s 要加密的字符串,不能为null + * @param properties 密钥配置,不能为null + * @return 加密后的十六进制字符串 + */ + public static String encrypt(String s, SecretProperties properties) { + byte[] key = Base64.decode(properties.getKey()); + AES aes = SecureUtil.aes(key); + + return aes.encryptHex(s); + } + + /** + * 字符串解密(使用默认配置) + * 使用应用配置中的密钥进行AES解密 + * + * @param s 要解密的十六进制字符串,不能为null + * @return 解密后的原始字符串 + */ + public static String decrypt(String s) { + SecretProperties properties = ApplicationUtil.getBean(SecretProperties.class); + + return decrypt(s, properties); + } + + /** + * 字符串解密(指定配置) + * 使用指定的密钥配置进行AES解密 + * + * @param s 要解密的十六进制字符串,不能为null + * @param properties 密钥配置,不能为null + * @return 解密后的原始字符串 + */ + public static String decrypt(String s, SecretProperties properties) { + byte[] key = Base64.decode(properties.getKey()); + AES aes = SecureUtil.aes(key); + + return aes.decryptStr(s); + } + + /** + * 生成AES密钥 + * 生成Base64编码的AES密钥 + * + * @return Base64编码的AES密钥字符串 + */ + public static String generateKey() { + byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded(); + return Base64.encode(key); + } + + /*public static void main(String[] args) { + String s = "需要加密的明文密码"; + byte[] key = Base64.decode("秘钥,见配置文件jugg.secret.key"); + AES aes = SecureUtil.aes(key); + + System.out.println(aes.encryptHex(s)); + }*/ +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/EnumUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/EnumUtil.java new file mode 100644 index 0000000..2f3023b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/EnumUtil.java @@ -0,0 +1,169 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.enums.BaseEnum; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 枚举工具类 + * 提供枚举操作相关的工具方法,支持BaseEnum接口的枚举处理 + * 包括枚举值查找、描述获取、枚举列表获取等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class EnumUtil { + + private static final Map>, List>> ENUM_POOL; + + static { + ENUM_POOL = new ConcurrentHashMap<>(); + } + + /** + * 根据代码获取枚举描述 + * 通过枚举代码查找对应的描述信息 + * + * @param clazz 枚举类,不能为null + * @param code 枚举代码,不能为null + * @param 枚举类型 + * @return 枚举描述,如果未找到则返回null + */ + public static > String getDesc(Class clazz, + Serializable code) { + + List enumList = getEnumList(clazz); + + for (C c : enumList) { + if (c.getCode().equals(code)) { + return c.getDesc(); + } + } + + return null; + } + + /** + * 根据代码获取枚举实例 + * 通过枚举代码查找对应的枚举实例 + * + * @param clazz 枚举类,不能为null + * @param code 枚举代码,可以为null + * @param 枚举类型 + * @return 枚举实例,如果未找到则返回null + */ + public static > C getByCode(Class clazz, + Serializable code) { + + if (ObjectUtil.isNull(code)) { + return null; + } + + List enumList = getEnumList(clazz); + for (C c : enumList) { + if (c.getCode() == null) { + continue; + } + if (String.valueOf(c.getCode()).equals(String.valueOf(code))) { + return c; + } + } + + return null; + } + + /** + * 根据描述获取枚举实例 + * 通过枚举描述查找对应的枚举实例 + * + * @param clazz 枚举类,不能为null + * @param desc 枚举描述,不能为null或空 + * @param 枚举类型 + * @return 枚举实例,如果未找到则返回null + */ + public static > C getByDesc(Class clazz, + String desc) { + + if (StringUtil.isNullOrUndefined(desc)) { + return null; + } + + List enumList = getEnumList(clazz); + for (C c : enumList) { + if (c.getDesc().equals(desc)) { + return c; + } + } + + return null; + } + + /** + * 获取枚举的所有描述列表 + * 返回指定枚举类的所有描述信息 + * + * @param clazz 枚举类,不能为null + * @param 枚举类型 + * @return 描述列表 + */ + public static > List getDescs(Class clazz) { + List enumList = getEnumList(clazz); + return enumList.stream().map(t -> t.getDesc()).collect(Collectors.toList()); + } + + /** + * 获取枚举列表 + * 从缓存或反射获取枚举实例列表 + * + * @param clazz 枚举类,不能为null + * @param 枚举类型 + * @return 枚举实例列表 + * @throws DefaultSysException 当获取枚举失败时抛出 + */ + private static > List getEnumList(Class clazz) { + + if (!ENUM_POOL.containsKey(clazz)) { + try { + List enumList = new ArrayList<>(); + if (Enum.class.isAssignableFrom(clazz)) { + // 如果是Enum类型 + Method method = clazz.getMethod("values"); + + C[] enums = (C[]) method.invoke(clazz); + + if (ArrayUtil.isNotEmpty(enums)) { + enumList.addAll(Arrays.asList(enums)); + } + } else { + // 如果不是Enum类型,那么必须是Bean + Map enums = ApplicationUtil.getBeansOfType(clazz); + if (!CollectionUtil.isEmpty(enums)) { + enumList.addAll(enums.values()); + } + } + ENUM_POOL.put(clazz, enumList); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + List enumList = (List) ENUM_POOL.get(clazz); + + return enumList; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelImportUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelImportUtil.java new file mode 100644 index 0000000..1e3c154 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelImportUtil.java @@ -0,0 +1,142 @@ +package com.lframework.starter.web.core.utils; + +import cn.dev33.satoken.stp.StpUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.ExcelImportBo; + +/** + * Excel导入工具类 + * 提供Excel导入任务管理功能,包括任务创建、进度跟踪、状态更新等 + * 支持异步导入任务的进度监控和错误处理 + * + * @author lframework@163.com + */ +public class ExcelImportUtil { + + private static final String UPLOAD_TASK_KEY = "upload_task_{}"; + + /** + * 获取Excel导入任务 + * 从Session中获取指定ID的导入任务,如果不存在则创建新任务 + * + * @param taskId 任务ID,不能为null + * @return Excel导入任务对象 + */ + public static ExcelImportBo getTask(String taskId) { + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession() + .get(StringUtil.format(UPLOAD_TASK_KEY, taskId)); + if (task == null) { + task = new ExcelImportBo(); + task.setId(taskId); + } + + return task; + } + + /** + * 初始化Excel导入任务 + * 创建新的导入任务并存储到Session中 + * + * @param taskId 任务ID,不能为null + */ + public static void initUploadTask(String taskId) { + ExcelImportBo result = new ExcelImportBo(); + result.setId(taskId); + + StpUtil.getSession().set(StringUtil.format(UPLOAD_TASK_KEY, taskId), result); + } + + /** + * 设置导入进度 + * 更新指定任务的导入进度 + * + * @param id 任务ID,不能为null + * @param process 进度值(0-100),不能为null + */ + public static void setProcess(String id, Integer process) { + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession().get(key); + task.setProcess(process); + StpUtil.getSession().set(key, task); + } + + /** + * 设置成功进度 + * 更新指定任务的成功处理进度 + * + * @param id 任务ID,不能为null + * @param process 成功进度值(0-100),不能为null + */ + public static void setSuccessProcess(String id, Integer process) { + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession().get(key); + task.setSuccessProcess(process); + StpUtil.getSession().set(key, task); + } + + /** + * 添加提示信息 + * 为指定任务添加提示信息,最多保存15条 + * + * @param id 任务ID,不能为null + * @param msg 提示信息,可以为null或空 + * @return true-添加成功,false-提示信息数量已达上限 + */ + public static boolean addTipMsg(String id, String msg) { + if (StringUtil.isBlank(msg)) { + return true; + } + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession().get(key); + if (task.getTipMsgs().size() >= 15) { + return false; + } + task.getTipMsgs().add(msg); + StpUtil.getSession().set(key, task); + return true; + } + + /** + * 设置错误状态 + * 标记指定任务是否包含错误 + * + * @param id 任务ID,不能为null + * @param hasError 是否有错误,不能为null + */ + public static void setHasError(String id, Boolean hasError) { + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession() + .get(StringUtil.format(UPLOAD_TASK_KEY, id)); + task.setHasError(hasError); + StpUtil.getSession().set(key, task); + } + + /** + * 标记任务完成 + * 将指定任务标记为已完成状态 + * + * @param id 任务ID,不能为null + */ + public static void finished(String id) { + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession() + .get(StringUtil.format(UPLOAD_TASK_KEY, id)); + task.setFinished(Boolean.TRUE); + StpUtil.getSession().set(key, task); + } + + /** + * 设置任务数据 + * 为指定任务设置处理结果数据 + * + * @param id 任务ID,不能为null + * @param data 任务数据,可以为null + */ + public static void setData(String id, Object data) { + String key = StringUtil.format(UPLOAD_TASK_KEY, id); + ExcelImportBo task = (ExcelImportBo) StpUtil.getSession() + .get(StringUtil.format(UPLOAD_TASK_KEY, id)); + task.setData(data); + StpUtil.getSession().set(key, task); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelUtil.java new file mode 100644 index 0000000..b5bb466 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ExcelUtil.java @@ -0,0 +1,246 @@ +package com.lframework.starter.web.core.utils; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.handler.WriteHandler; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.lframework.starter.web.core.annotations.excel.ExcelRequired; +import com.lframework.starter.web.core.components.excel.RequiredFieldStyleHandler; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * Excel工具类 + * 提供Excel文件导入导出功能,基于EasyExcel实现 + * 包括Excel读取、写入、样式设置、数据验证等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class ExcelUtil { + + private static final WriteHandler DEFAULT_COLUMN_WIDTH = + new LongestMatchColumnWidthStyleStrategy(); + + // ======================= 读取 ======================= + + public static ExcelReaderBuilder read(MultipartFile file, Class clazz, + ReadListener listener) { + try { + return EasyExcel.read(file.getInputStream(), clazz, listener); + } catch (IOException e) { + throw new RuntimeException("Excel读取失败", e); + } + } + + // ======================= 导出(Response) ======================= + + public static void exportXlsx(String fileName, + String sheetName, + Class clazz) { + + exportXlsx(fileName, sheetName, clazz, Collections.emptyList(), null); + } + + public static void exportXlsx(String fileName, + String sheetName, + Class clazz, + List data, + List handlers) { + + HttpServletResponse response = ResponseUtil.getResponse(); + + try (OutputStream os = buildResponse(response, fileName)) { + doWrite(os, sheetName, clazz, data, handlers); + } catch (IOException e) { + throw new RuntimeException("Excel导出失败", e); + } + } + + private static OutputStream buildResponse(HttpServletResponse response, + String fileName) throws IOException { + + String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"); + + response.setContentType( + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + + response.setHeader("Content-Disposition", + "attachment;filename*=utf-8''" + encodedFileName + ".xlsx"); + + response.setHeader("Cache-Control", "no-store, no-cache"); + response.setHeader("Pragma", "no-cache"); + + return response.getOutputStream(); + } + + private static void doWrite(OutputStream os, + String sheetName, + Class clazz, + List data, + List handlers) { + + ExcelWriterBuilder builder = EasyExcel.write(os, clazz); + + + List allHandlers = buildHandlers(handlers, clazz); + allHandlers.forEach(builder::registerWriteHandler); + + builder.sheet(sheetName).doWrite(data); + } + + // ======================= 导出(File) ======================= + + public static void exportXlsx(File file, + String sheetName, + Class clazz, + List data, + List handlers) { + + try (OutputStream os = new FileOutputStream(file)) { + write(os, sheetName, clazz, data, handlers, ExcelTypeEnum.XLSX); + } catch (Exception e) { + throw new RuntimeException("Excel导出失败", e); + } + } + + // ======================= 核心写方法 ======================= + + private static void write(OutputStream os, + String sheetName, + Class clazz, + List data, + List handlers, + ExcelTypeEnum type) { + + ExcelWriterBuilder builder = EasyExcel.write(os, clazz) + .excelType(type); + + // 注册样式 + buildHandlers(handlers, clazz).forEach(builder::registerWriteHandler); + + ExcelWriter writer = builder.build(); + WriteSheet sheet = EasyExcel.writerSheet(sheetName).build(); + + writer.write(data, sheet); + writer.finish(); + } + + // ======================= 分段写(核心) ======================= + + public static ExcelWriter createWriter(OutputStream os, + Class clazz, + List handlers, + ExcelTypeEnum type) { + + ExcelWriterBuilder builder = EasyExcel.write(os, clazz) + .excelType(type); + + buildHandlers(handlers, clazz).forEach(builder::registerWriteHandler); + + return builder.build(); + } + + public static WriteSheet createSheet(String sheetName) { + return EasyExcel.writerSheet(sheetName).build(); + } + + // ======================= 样式处理 ======================= + + private static List buildHandlers(List custom, + Class headClass) { + + List list = new ArrayList<>(); + + // 默认样式 + list.addAll(defaultStyle(getRequiredFields(headClass))); + + if (custom != null) { + list.addAll(custom); + } + + // 自动列宽 + if (list.stream().noneMatch(t -> t instanceof AbstractColumnWidthStyleStrategy)) { + list.add(DEFAULT_COLUMN_WIDTH); + } + + return list; + } + + private static List defaultStyle(Set requiredFields) { + + List list = new ArrayList<>(); + + WriteCellStyle content = new WriteCellStyle(); + content.setBorderBottom(BorderStyle.THIN); + content.setBorderTop(BorderStyle.THIN); + content.setBorderLeft(BorderStyle.THIN); + content.setBorderRight(BorderStyle.THIN); + + WriteFont font = new WriteFont(); + font.setFontHeightInPoints((short) 11); + content.setWriteFont(font); + +// list.add(new ExcelHorizontalCellStyleStrategy( +// headStyle(false), +// headStyle(true), +// content, +// requiredFields +// )); + + list.add(new RequiredFieldStyleHandler(requiredFields)); + + return list; + } + + private static WriteCellStyle headStyle(boolean required) { + WriteCellStyle style = new WriteCellStyle(); + style.setHorizontalAlignment(HorizontalAlignment.LEFT); + + WriteFont font = new WriteFont(); + font.setBold(true); + + if (required) { + font.setColor(Font.COLOR_RED); + } + + style.setWriteFont(font); + return style; + } + + private static Set getRequiredFields(Class clazz) { + if (clazz == null) return null; + + Set set = new HashSet<>(); + + for (Field f : clazz.getDeclaredFields()) { + if (f.getAnnotation(ExcelRequired.class) != null) { + set.add(f.getName()); + } + } + return set; + } +} \ No newline at end of file diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/FieldEncryptUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/FieldEncryptUtil.java new file mode 100644 index 0000000..f06a376 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/FieldEncryptUtil.java @@ -0,0 +1,91 @@ +package com.lframework.starter.web.core.utils; + +import cn.hutool.core.util.DesensitizedUtil; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.constants.EncryType; + +/** + * 字段脱敏工具类 + * 提供各种类型字段的脱敏处理功能,支持多种脱敏策略 + * 包括密码、邮箱、姓名、身份证、手机号等敏感信息的脱敏 + * + * @author lframework@163.com + */ +public class FieldEncryptUtil { + + /** + * 根据脱敏类型对字符串进行脱敏处理 + * 支持多种预定义的脱敏策略 + * + * @param str 要脱敏的字符串,可以为null + * @param type 脱敏类型,不能为null + * @return 脱敏后的字符串 + */ + public static String encrypt(CharSequence str, EncryType type) { + String s = str == null ? null : str.toString(); + switch (type) { + case AUTO: { + return autoEncrypt(str); + } + case PASSWORD: { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 6; i++) { + builder.append(StringPool.ENCRYPT_STR); + } + + return builder.toString(); + } + case EMAIL: { + return DesensitizedUtil.email(s); + } + case CHINESE_NAME: { + return DesensitizedUtil.chineseName(s); + } + case ID_CARD: { + return DesensitizedUtil.idCardNum(s, 4, 4); + } + case FIXED_PHONE: { + return DesensitizedUtil.fixedPhone(s); + } + case MOBILE_PHONE: { + return DesensitizedUtil.mobilePhone(s); + } + case CAR_LICENSE: { + return DesensitizedUtil.carLicense(s); + } + case BANK_CARD: { + return DesensitizedUtil.bankCard(s); + } + } + + return StringPool.ENCRYPT_STR; + } + + /** + * 自动脱敏处理 + * 根据字符串长度自动选择合适的脱敏策略 + * + * @param str 要脱敏的字符串,可以为null + * @return 脱敏后的字符串 + */ + public static String autoEncrypt(CharSequence str) { + if (StringUtil.isEmpty(str)) { + return StringPool.ENCRYPT_STR; + } + + int len = str.length(); + int sub = len >> 1; + if (sub <= 0) { + return StringPool.ENCRYPT_STR; + } + + int sub2 = sub >> 1; + if (sub2 <= 0) { + // 字符串的length要么是2 要么是3 + return StringUtil.hide(str, 1, 2); + } + + return StringUtil.hide(str, sub - sub2, sub - sub2 + sub); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/GroovyUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/GroovyUtil.java new file mode 100644 index 0000000..67ff693 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/GroovyUtil.java @@ -0,0 +1,105 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.web.inner.service.GroovySupportService; +import groovy.lang.Binding; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import org.codehaus.groovy.control.CompilerConfiguration; + +import java.util.Map; + +/** + * Groovy脚本工具类 + * 提供Groovy脚本执行功能,支持动态脚本解析和执行 + * 包括脚本执行、变量绑定、脚本类加载等功能 + * + * @author lframework@163.com + * @since 2022/8/20 + */ +public class GroovyUtil { + + private static GroovyShell SHELL; + + /** + * 获取GroovyShell实例 + * 单例模式获取配置好的GroovyShell实例 + * + * @return GroovyShell实例 + */ + private static GroovyShell getShell() { + if (SHELL == null) { + synchronized (GroovyUtil.class) { + if (SHELL != null) { + return SHELL; + } + + Binding binding = new Binding(); + + Map beans = ApplicationUtil.getBeansOfType(GroovySupportService.class); + beans.forEach(binding::setVariable); + + GroovyClassLoader groovyClassLoader = new GroovyClassLoader( + GroovyScript.class.getClassLoader()); + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setSourceEncoding("utf-8"); + compilerConfiguration.setScriptBaseClass(GroovyScript.class.getName()); + + SHELL = new GroovyShell(groovyClassLoader, binding, compilerConfiguration); + } + } + + return SHELL; + } + + /** + * 执行Groovy脚本 + * 执行指定的Groovy脚本代码并返回结果 + * + * @param script 要执行的Groovy脚本代码,不能为null + * @return 脚本执行结果 + */ + public static Object excuteScript(String script) { + + GroovyScript groovyScript = new GroovyScript(script); + return groovyScript.run(); + } + + /** + * Groovy脚本执行类 + * 封装Groovy脚本的执行逻辑 + */ + public static class GroovyScript extends Script { + + /** + * 脚本代码 + */ + private String script; + + /** + * 默认构造函数 + */ + public GroovyScript() { + } + + /** + * 带脚本代码的构造函数 + * + * @param script 脚本代码,不能为null + */ + public GroovyScript(String script) { + this.script = script; + } + + /** + * 执行脚本 + * + * @return 脚本执行结果 + */ + @Override + public Object run() { + GroovyShell shell = getShell(); + return shell.evaluate(script); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/HttpUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/HttpUtil.java new file mode 100644 index 0000000..c0b0afd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/HttpUtil.java @@ -0,0 +1,971 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.common.utils.XmlUtil; +import lombok.Cleanup; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * HTTP工具类 + * 基于Apache HttpClient 4.5版本提供HTTP请求功能 + * 包括GET、POST请求、SSL支持、连接池管理等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class HttpUtil { + + /** + * 默认字符编码 + */ + public static final String CHARSET = "UTF-8"; + + /** + * 从连接池获取连接的超时时间(毫秒) + */ + private static final int DEFAULT_CONNECTION_REQUST_TIME_OUT = 3000; + + /** + * 客户端和服务器建立连接的超时时间(毫秒) + */ + private static final int DEFAULT_CONNECT_TIME_OUT = 3000; + + /** + * 客户端从服务器读取数据的超时时间(毫秒) + */ + private static final int DEFAULT_SOCKET_TIME_OUT = 30000; + + /** + * 执行GET请求(使用默认参数) + * 使用默认超时时间和字符编码执行GET请求 + * + * @param url 请求URL,不能为null + * @return 响应内容字符串 + * @throws IOException 当请求失败时抛出 + */ + public static String doGet(String url) throws IOException { + + return doGet(url, null, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + /** + * 执行GET请求(带参数) + * 使用默认超时时间和字符编码执行带参数的GET请求 + * + * @param url 请求URL,不能为null + * @param params 请求参数,可以为null + * @return 响应内容字符串 + * @throws IOException 当请求失败时抛出 + */ + public static String doGet(String url, Map params) throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + /** + * 执行GET请求(指定Socket超时时间) + * 使用指定的Socket超时时间执行GET请求 + * + * @param url 请求URL,不能为null + * @param params 请求参数,可以为null + * @param socketTimeout Socket超时时间(毫秒) + * @return 响应内容字符串 + * @throws IOException 当请求失败时抛出 + */ + public static String doGet(String url, Map params, int socketTimeout) + throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + /** + * 执行GET请求(指定连接和Socket超时时间) + * 使用指定的连接和Socket超时时间执行GET请求 + * + * @param url 请求URL,不能为null + * @param params 请求参数,可以为null + * @param connectionTimeout 连接超时时间(毫秒) + * @param socketTimeout Socket超时时间(毫秒) + * @return 响应内容字符串 + * @throws IOException 当请求失败时抛出 + */ + public static String doGet(String url, Map params, int connectionTimeout, + int socketTimeout) + throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, connectionTimeout, + socketTimeout, + null, null); + } + + /** + * 执行GET请求(指定所有超时时间) + * 使用指定的所有超时时间执行GET请求 + * + * @param url 请求URL,不能为null + * @param params 请求参数,可以为null + * @param connectionRequestTimeout 连接请求超时时间(毫秒) + * @param connectionTimeout 连接超时时间(毫秒) + * @param socketTimeout Socket超时时间(毫秒) + * @return 响应内容字符串 + * @throws IOException 当请求失败时抛出 + */ + public static String doGet(String url, Map params, int connectionRequestTimeout, + int connectionTimeout, int socketTimeout) throws IOException { + + return doGet(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doGet(String url, Map params, Map headers) + throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doGet(String url, Map params, Map headers, + int socketTimeout) + throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doGet(String url, Map params, Map headers, + int connectionTimeout, int socketTimeout) throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doGet(String url, Map params, Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout) throws IOException { + + return doGet(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doGet(String url, Map params, InputStream certStream, + String certPsw) + throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doGet(String url, Map params, InputStream certStream, + String certPsw, + int socketTimeout) throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doGet(String url, Map params, InputStream certStream, + String certPsw, + int connectionTimeout, int socketTimeout) throws IOException { + + return doGet(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doGet(String url, Map params, InputStream certStream, + String certPsw, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout) throws IOException { + + return doGet(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, certStream, + certPsw); + } + + public static String doGet(String url, Map params, Map headers, + InputStream certStream, String certPsw) throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doGet(String url, Map params, Map headers, + InputStream certStream, String certPsw, int socketTimeout) throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doGet(String url, Map params, Map headers, + InputStream certStream, String certPsw, int connectionTimeout, int socketTimeout) + throws IOException { + + return doGet(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doGet(String url, Map params, Map headers, + InputStream certStream, String certPsw, int connectionRequestTimeout, int connectionTimeout, + int socketTimeout) throws IOException { + + return doGet(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPost(String url) throws IOException { + + return doPost(url, null, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPost(String url, Map params) throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPost(String url, Map params, int socketTimeout) + throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPost(String url, Map params, int connectionTimeout, + int socketTimeout) + throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, connectionTimeout, + socketTimeout, + null, null); + } + + public static String doPost(String url, Map params, int connectionRequestTimeout, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPost(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doPost(String url, Map params, Map headers) + throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPost(String url, Map params, Map headers, + int socketTimeout) + throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPost(String url, Map params, Map headers, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doPost(String url, Map params, Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout) throws IOException { + + return doPost(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doPost(String url, Map params, InputStream certStream, + String certPsw) + throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPost(String url, Map params, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPost(String url, Map params, int connectionTimeout, + int socketTimeout, + InputStream certStream, String certPsw) throws IOException { + + return doPost(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPost(String url, Map params, int connectionRequestTimeout, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPost(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPost(String url, Map params, Map headers, + InputStream certStream, String certPsw) throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPost(String url, Map params, Map headers, + int socketTimeout, + InputStream certStream, String certPsw) throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPost(String url, Map params, Map headers, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPost(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doPost(String url, Map params, Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPost(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPostJson(String url, Map params) throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPostJson(String url, Map params, int socketTimeout) + throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPostJson(String url, Map params, int connectionTimeout, + int socketTimeout) + throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doPostJson(String url, Map params, + int connectionRequestTimeout, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPostJson(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doPostJson(String url, Map params, + Map headers) + throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPostJson(String url, Map params, + Map headers, + int socketTimeout) throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPostJson(String url, Map params, + Map headers, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doPostJson(String url, Map params, + Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout) throws IOException { + + return doPostJson(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + null, null); + } + + public static String doPostJson(String url, Map params, InputStream certStream, + String certPsw) + throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, int connectionTimeout, + int socketTimeout, + InputStream certStream, String certPsw) throws IOException { + + return doPostJson(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, + int connectionRequestTimeout, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPostJson(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPostJson(String url, Map params, + Map headers, + InputStream certStream, String certPsw) throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, + Map headers, + int socketTimeout, InputStream certStream, String certPsw) throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, + Map headers, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPostJson(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doPostJson(String url, Map params, + Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPostJson(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPostXml(String url, Map params) throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPostXml(String url, Map params, int socketTimeout) + throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPostXml(String url, Map params, int connectionTimeout, + int socketTimeout) + throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doPostXml(String url, Map params, + int connectionRequestTimeout, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPostXml(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, null, + null); + } + + public static String doPostXml(String url, Map params, + Map headers) + throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, null, null); + } + + public static String doPostXml(String url, Map params, + Map headers, + int socketTimeout) throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, null, null); + } + + public static String doPostXml(String url, Map params, + Map headers, + int connectionTimeout, int socketTimeout) throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, null, null); + } + + public static String doPostXml(String url, Map params, + Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout) throws IOException { + + return doPostXml(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + null, null); + } + + public static String doPostXml(String url, Map params, InputStream certStream, + String certPsw) + throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, int connectionTimeout, + int socketTimeout, + InputStream certStream, String certPsw) throws IOException { + + return doPostXml(url, params, null, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, + int connectionRequestTimeout, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPostXml(url, params, null, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + public static String doPostXml(String url, Map params, + Map headers, + InputStream certStream, String certPsw) throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + DEFAULT_SOCKET_TIME_OUT, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, + Map headers, + int socketTimeout, InputStream certStream, String certPsw) throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + DEFAULT_CONNECT_TIME_OUT, + socketTimeout, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, + Map headers, + int connectionTimeout, int socketTimeout, InputStream certStream, String certPsw) + throws IOException { + + return doPostXml(url, params, headers, CHARSET, DEFAULT_CONNECTION_REQUST_TIME_OUT, + connectionTimeout, + socketTimeout, certStream, certPsw); + } + + public static String doPostXml(String url, Map params, + Map headers, + int connectionRequestTimeout, int connectionTimeout, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + return doPostXml(url, params, headers, CHARSET, connectionRequestTimeout, connectionTimeout, + socketTimeout, + certStream, certPsw); + } + + /** + * HTTP Get 获取内容 + * + * @param url 请求的url地址 ?之前的地址 + * @param requestParams 请求的参数 + * @param charset 编码格式 + * @return 页面内容 + */ + public static String doGet(String url, Map requestParams, + Map headers, + String charset, int connectionRequestTimeout, int connectTimeout, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + SimpleMap params = CollectionUtil.isEmpty(requestParams) ? null : new SimpleMap<>(requestParams); + if (StringUtil.isBlank(url)) { + throw new IllegalArgumentException("url不能为空!"); + } + if (params != null && !params.isEmpty()) { + List pairs = new ArrayList(params.size()); + for (String key : params.keySet()) { + String value = params.getString(key); + if (value != null) { + pairs.add(new BasicNameValuePair(key, value)); + } + } + // 将请求参数和url进行拼接 + url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset)); + } + + if (log.isDebugEnabled()) { + log.debug("http-get url:{}", url); + } + + HttpGet httpGet = new HttpGet(url); + if (!CollectionUtil.isEmpty(headers)) { + headers.forEach(httpGet::setHeader); + } + + CloseableHttpClient httpClient = buildHttpClient(certStream, certPsw, connectionRequestTimeout, + connectTimeout, + socketTimeout); + + @Cleanup CloseableHttpResponse response = httpClient.execute(httpGet); + int statusCode = response.getStatusLine().getStatusCode(); + + if (statusCode != HttpStatus.SC_OK) { + httpGet.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, "utf-8"); + } + + if (log.isDebugEnabled()) { + log.debug("http-get 响应消息:{}", result == null ? "无" : result); + } + + EntityUtils.consume(entity); + + return result; + } + + /** + * HTTP Post 获取内容 + * + * @param url 请求的url地址 ?之前的地址 + * @param requestParams 请求的参数 + * @param charset 编码格式 + * @return 页面内容 + * @throws IOException + */ + public static String doPost(String url, Map requestParams, + Map headers, + String charset, int connectionRequestTimeout, int connectTimeout, int socketTimeout, + InputStream certStream, + String certPsw) throws IOException { + + SimpleMap params = CollectionUtil.isEmpty(requestParams) ? null : new SimpleMap<>(requestParams); + if (StringUtil.isBlank(url)) { + return null; + } + List pairs = null; + if (params != null && !params.isEmpty()) { + pairs = new ArrayList<>(params.size()); + for (String key : params.keySet()) { + String value = params.getString(key); + if (value != null) { + pairs.add(new BasicNameValuePair(key, value)); + } + } + } + HttpPost httpPost = new HttpPost(url); + httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + if (!CollectionUtil.isEmpty(headers)) { + headers.forEach(httpPost::setHeader); + } + if (pairs != null && pairs.size() > 0) { + httpPost.setEntity(new UrlEncodedFormEntity(pairs, charset)); + } + + if (log.isDebugEnabled()) { + log.debug("http-post url={}, params={}", url, JsonUtil.toJsonString(params)); + } + + CloseableHttpClient httpClient = buildHttpClient(certStream, certPsw, connectionRequestTimeout, + connectTimeout, + socketTimeout); + + @Cleanup CloseableHttpResponse response = httpClient.execute(httpPost); + + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + httpPost.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, charset); + } + + if (log.isDebugEnabled()) { + log.debug("http-post 响应消息:{}", result == null ? "无" : result); + } + + EntityUtils.consume(entity); + return result; + } + + public static String doPostJson(String url, Map params, + Map headers, String charset, + int connectionRequestTimeout, int connectTimeout, int socketTimeout, InputStream certStream, + String certPsw) + throws IOException { + + if (StringUtil.isBlank(url)) { + throw new IllegalArgumentException("url不能为空!"); + } + + String jsonParams = JsonUtil.toJsonString(params); + StringEntity requestEntity = new StringEntity(jsonParams, charset); + HttpPost httpPost = new HttpPost(url); + httpPost.setHeader("Content-type", "application/json"); + if (!CollectionUtil.isEmpty(headers)) { + headers.forEach(httpPost::setHeader); + } + httpPost.setEntity(requestEntity); + + if (log.isDebugEnabled()) { + log.debug("http-post-json url={}, params={}", url, jsonParams); + } + + CloseableHttpClient httpClient = buildHttpClient(certStream, certPsw, connectionRequestTimeout, + connectTimeout, + socketTimeout); + + @Cleanup CloseableHttpResponse response = httpClient.execute(httpPost); + + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + httpPost.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, charset); + } + + if (log.isDebugEnabled()) { + log.debug("http-post-json 响应消息:{}", result == null ? "无" : result); + } + + EntityUtils.consume(entity); + return result; + } + + public static String doPostXml(String url, Map params, + Map headers, String charset, + int connectionRequestTimeout, int connectTimeout, int socketTimeout, InputStream certStream, + String certPsw) + throws IOException { + + if (StringUtil.isBlank(url)) { + throw new IllegalArgumentException("url不能为空!"); + } + + String xmlParams = XmlUtil.formatXml(XmlUtil.map2xml(params, "xml")); + + StringEntity requestEntity = new StringEntity(xmlParams, charset); + HttpPost httpPost = new HttpPost(url); + httpPost.setHeader("Content-type", "application/xml"); + if (!CollectionUtil.isEmpty(headers)) { + headers.forEach(httpPost::setHeader); + } + httpPost.setEntity(requestEntity); + + if (log.isDebugEnabled()) { + log.debug("http-post-xml url={}, params={}", url, xmlParams); + } + + CloseableHttpClient httpClient = buildHttpClient(certStream, certPsw, connectionRequestTimeout, + connectTimeout, + socketTimeout); + + @Cleanup CloseableHttpResponse response = httpClient.execute(httpPost); + + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + httpPost.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, charset); + } + + if (log.isDebugEnabled()) { + log.debug("http-post-xml 响应消息:{}", result == null ? "无" : result); + } + + EntityUtils.consume(entity); + return result; + } + + private static CloseableHttpClient buildHttpClient(InputStream certStream, String certPsw, + int connectionRequestTimeout, int connectTimeout, int socketTimeout) { + + try { + BasicHttpClientConnectionManager connManager; + if (certStream != null) { + char[] password = certPsw.toCharArray(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(certStream, password); + + // 实例化密钥库 & 初始化密钥工厂 + KeyManagerFactory kmf = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password); + + // 创建 SSLContext + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, new SecureRandom()); + + SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( + sslContext, + new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); + + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", sslConnectionSocketFactory).build(), null, null, null); + } else { + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()).build(), null, + null, null); + } + + RequestConfig config = RequestConfig.custom() + .setConnectionRequestTimeout(connectionRequestTimeout) + .setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build(); + CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config) + .setConnectionManager(connManager).build(); + + return httpClient; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new IllegalStateException("无法构建HttpClient!"); + } + } +} + diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/IdUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/IdUtil.java new file mode 100644 index 0000000..9053d72 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/IdUtil.java @@ -0,0 +1,46 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.IdWorker; + +/** + * ID生成工具类 + * 提供各种ID生成功能,包括雪花算法ID和UUID生成 + * 支持分布式环境下的唯一ID生成 + * + * @author lframework@163.com + */ +public class IdUtil { + + /** + * 获取雪花算法ID(字符串格式) + * 生成全局唯一的分布式ID + * + * @return 雪花算法ID字符串 + */ + public static String getId() { + + IdWorker idWorker = ApplicationUtil.getBean(IdWorker.class); + return idWorker.nextIdStr(); + } + + /** + * 获取雪花算法ID(长整型格式) + * 生成全局唯一的分布式ID + * + * @return 雪花算法ID长整型值 + */ + public static long getIdLong() { + IdWorker idWorker = ApplicationUtil.getBean(IdWorker.class); + return idWorker.nextId(); + } + + /** + * 获取UUID(字符串格式) + * 生成标准UUID字符串,不包含连字符 + * + * @return UUID字符串 + */ + public static String getUUID() { + return cn.hutool.core.util.IdUtil.fastSimpleUUID(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/JsonUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/JsonUtil.java new file mode 100644 index 0000000..7292c1f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/JsonUtil.java @@ -0,0 +1,228 @@ +package com.lframework.starter.web.core.utils; + +import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.StringUtil; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.Map; + +/** + * JSON工具类 + * 基于HuTool的JSONUtil进行扩展,提供JSON序列化和反序列化功能 + * 包括对象转JSON、JSON转对象、类型转换等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class JsonUtil extends JSONUtil { + + private static final ObjectMapper OBJECT_MAPPER = ApplicationUtil.getBean(ObjectMapper.class); + + /** + * 将对象转换为JSON字符串 + * 使用Jackson ObjectMapper进行序列化 + * + * @param obj 要转换的对象,可以为null + * @return JSON字符串,如果对象为null则返回null + * @throws DefaultSysException 当序列化失败时抛出 + */ + public static String toJsonString(Object obj) { + + if (obj == null) { + return null; + } + try { + return OBJECT_MAPPER.writer().writeValueAsString(obj); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 将JSON字符串转换为对象(使用TypeReference) + * 支持复杂泛型类型的反序列化 + * + * @param jsonStr JSON字符串,不能为null或空 + * @param typeRef 类型引用,不能为null + * @param 目标类型 + * @return 转换后的对象,如果JSON为空则返回null + * @throws DefaultSysException 当反序列化失败时抛出 + */ + public static T parseObject(String jsonStr, TypeReference typeRef) { + if (StringUtil.isEmpty(jsonStr) || typeRef == null) { + return null; + } + + try { + return OBJECT_MAPPER.readValue(jsonStr, typeRef); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 将JSON字符串转换为对象(使用Class) + * 支持简单类型的反序列化 + * + * @param jsonStr JSON字符串,不能为null或空 + * @param clazz 目标类型,不能为null + * @param 目标类型 + * @return 转换后的对象,如果JSON为空则返回null + * @throws DefaultSysException 当反序列化失败时抛出 + */ + public static T parseObject(String jsonStr, Class clazz) { + + if (StringUtil.isEmpty(jsonStr) || clazz == null) { + return null; + } + + try { + return OBJECT_MAPPER.readValue(jsonStr, clazz); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 将JSON字符串转换为Map + * 支持指定键值类型的Map反序列化 + * + * @param jsonStr JSON字符串,不能为null或空 + * @param keyClazz 键类型,不能为null + * @param valueClazz 值类型,不能为null + * @param 键类型 + * @param 值类型 + * @return 转换后的Map,如果JSON为空则返回null + * @throws DefaultSysException 当反序列化失败时抛出 + */ + public static Map parseMap(String jsonStr, Class keyClazz, Class valueClazz) { + if (StringUtil.isEmpty(jsonStr) || keyClazz == null || valueClazz == null) { + return null; + } + + try { + return OBJECT_MAPPER.readValue(jsonStr, + OBJECT_MAPPER.getTypeFactory().constructMapType(Map.class, keyClazz, valueClazz)); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 将JSON字符串转换为List + * 支持指定元素类型的List反序列化 + * + * @param jsonStr JSON字符串,不能为null或空 + * @param clazz 元素类型,不能为null + * @param 元素类型 + * @return 转换后的List,如果JSON为空则返回null + * @throws DefaultSysException 当反序列化失败时抛出 + */ + public static List parseList(String jsonStr, Class clazz) { + + if (StringUtil.isEmpty(jsonStr) || clazz == null) { + return null; + } + + try { + return OBJECT_MAPPER.readValue(jsonStr, + OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 对象类型转换 + * 使用Jackson进行对象类型转换 + * + * @param obj 要转换的对象,不能为null + * @param clazz 目标类型,不能为null + * @param 目标类型 + * @return 转换后的对象,如果对象为null则返回null + */ + public static T convert(Object obj, Class clazz) { + + if (obj == null || clazz == null) { + return null; + } + + return OBJECT_MAPPER.convertValue(obj, clazz); + } + + /** + * 判断字符串是否为JSON对象 + * 验证字符串是否为有效的JSON对象格式 + * + * @param jsonStr 要验证的字符串,不能为null + * @return true-是JSON对象,false-不是JSON对象或格式无效 + */ + public static boolean isJsonObject(String jsonStr) { + + if (StringUtil.isBlank(jsonStr)) { + return false; + } + + try { + JsonNode jsonNode = OBJECT_MAPPER.readTree(jsonStr); + return jsonNode.getNodeType() != JsonNodeType.ARRAY; + } catch (JsonProcessingException e) { + return false; + } + } + + /** + * 判断字符串是否为JSON数组 + * 验证字符串是否为有效的JSON数组格式 + * + * @param jsonStr 要验证的字符串,不能为null + * @return true-是JSON数组,false-不是JSON数组或格式无效 + */ + public static boolean isJsonArray(String jsonStr) { + + if (StringUtil.isBlank(jsonStr)) { + return false; + } + + try { + JsonNode jsonNode = OBJECT_MAPPER.readTree(jsonStr); + return jsonNode.getNodeType() == JsonNodeType.ARRAY; + } catch (JsonProcessingException e) { + return false; + } + } + + /** + * 判断字符串是否为有效JSON + * 验证字符串是否为有效的JSON格式 + * + * @param jsonStr 要验证的字符串,不能为null + * @return true-是有效JSON,false-不是有效JSON + */ + public static boolean isJson(String jsonStr) { + + if (StringUtil.isBlank(jsonStr)) { + return false; + } + + try { + OBJECT_MAPPER.readTree(jsonStr); + } catch (JsonProcessingException e) { + return false; + } + + return true; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/OpLogUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/OpLogUtil.java new file mode 100644 index 0000000..0b44541 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/OpLogUtil.java @@ -0,0 +1,204 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.threads.DefaultRunnable; +import com.lframework.starter.web.inner.service.OpLogsService; +import com.lframework.starter.web.inner.vo.oplogs.CreateOpLogsVo; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.concurrent.ExecutorService; + +/** + * 操作日志工具类 + * 提供操作日志记录和管理功能,支持异步日志提交和变量管理 + * 包括日志初始化、变量设置、日志提交、线程池管理等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class OpLogUtil { + + private static final ThreadLocal>> VARIABLE_POOL = new InheritableThreadLocal<>(); + + private static final ThreadLocal> LOG_ID_POOL = new InheritableThreadLocal<>(); + + private static final ThreadLocal> EXTRA_POOL = new InheritableThreadLocal<>(); + + private static final ThreadLocal> OP_LOG_POOL = new InheritableThreadLocal<>(); + + private static final ExecutorService OP_LOG_EXECUTOR = ThreadUtil.newExecutorByBlockingCoefficient( + 0); + + /** + * 初始化操作日志 + * 为指定日志ID初始化日志环境 + * + * @param logId 日志ID,不能为null + */ + public static void init(String logId) { + + initPool(); + + LOG_ID_POOL.get().add(logId); + + VARIABLE_POOL.get().putIfAbsent(logId, new HashMap<>()); + } + + /** + * 添加操作日志 + * 将操作日志添加到当前线程的日志池中 + * + * @param list 操作日志列表,不能为null + */ + public static void addLogs(Collection list) { + + try { + OP_LOG_POOL.get().addAll(list); + } catch (Exception e) { + // 这里异常不抛出 + log.error(e.getMessage(), e); + } + } + + /** + * 设置日志变量 + * 为当前日志ID设置变量 + * + * @param key 变量键,不能为null + * @param value 变量值,可以为null + */ + public static void setVariable(String key, Object value) { + + VARIABLE_POOL.get().get(getCurrentLogId()).put(key, value); + } + + /** + * 获取日志变量 + * 获取当前日志ID的所有变量 + * + * @return 变量映射,如果不存在则返回null + */ + public static Map getVariables() { + + return VARIABLE_POOL.get().get(getCurrentLogId()); + } + + /** + * 获取额外信息 + * 获取当前日志ID的额外信息(JSON格式) + * + * @return 额外信息的JSON字符串,如果不存在则返回null + */ + public static String getExtra() { + + Object value = EXTRA_POOL.get().get(getCurrentLogId()); + + return value == null ? null : JsonUtil.toJsonString(value); + } + + /** + * 设置额外信息 + * 为当前日志ID设置额外信息 + * + * @param value 额外信息对象,可以为null + */ + public static void setExtra(Object value) { + + EXTRA_POOL.get().put(getCurrentLogId(), value); + } + + /** + * 提交操作日志(使用当前用户) + * 异步提交当前线程的所有操作日志 + */ + public static void submitLog() { + submitLog(SecurityUtil.getCurrentUser()); + } + + /** + * 提交操作日志(指定用户) + * 异步提交当前线程的所有操作日志 + * + * @param currentUser 当前用户信息,可以为null + */ + public static void submitLog(AbstractUserDetails currentUser) { + if (LOG_ID_POOL.get() == null || LOG_ID_POOL.get().size() != 1) { + return; + } + List logs = OP_LOG_POOL.get(); + OpLogsService opLogsService = ApplicationUtil.getBean(OpLogsService.class); + OP_LOG_EXECUTOR.submit(new DefaultRunnable(() -> { + if (SecurityUtil.getCurrentUser() != null) { + opLogsService.create(logs); + } else { + if (currentUser != null) { + try { + SecurityUtil.setCurrentUser(currentUser); + opLogsService.create(logs); + } finally { + SecurityUtil.removeCurrentUser(); + } + } + } + })); + } + + /** + * 清理日志环境 + * 清理当前线程的日志相关数据 + */ + public static void clear() { + boolean allClear = false; + if (LOG_ID_POOL.get().size() == 1) { + allClear = true; + } + + VARIABLE_POOL.get().remove(getCurrentLogId()); + EXTRA_POOL.get().remove(getCurrentLogId()); + LOG_ID_POOL.get().remove(LOG_ID_POOL.get().size() - 1); + + if (allClear) { + VARIABLE_POOL.remove(); + EXTRA_POOL.remove(); + LOG_ID_POOL.remove(); + OP_LOG_POOL.remove(); + } + } + + /** + * 初始化线程池 + * 初始化当前线程的日志相关线程池 + */ + private static void initPool() { + + if (VARIABLE_POOL.get() == null) { + VARIABLE_POOL.set(new HashMap<>()); + } + + if (LOG_ID_POOL.get() == null) { + LOG_ID_POOL.set(new ArrayList<>()); + } + + if (EXTRA_POOL.get() == null) { + EXTRA_POOL.set(new HashMap<>()); + } + + if (OP_LOG_POOL.get() == null) { + OP_LOG_POOL.set(new ArrayList<>()); + } + } + + /** + * 获取当前日志ID + * 获取当前线程栈顶的日志ID + * + * @return 当前日志ID + */ + private static String getCurrentLogId() { + + return LOG_ID_POOL.get().get(LOG_ID_POOL.get().size() - 1); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageHelperUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageHelperUtil.java new file mode 100644 index 0000000..21a47df --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageHelperUtil.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.core.utils; + +import com.github.pagehelper.PageHelper; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.constants.MybatisConstants; +import com.lframework.starter.web.core.vo.PageVo; + +/** + * 分页插件工具类 + * 提供PageHelper分页插件的便捷操作方法 + * 包括分页开启、参数处理、默认值设置等功能 + * + * @author lframework@163.com + */ +public class PageHelperUtil { + + /** + * 开启分页 + * 使用指定的页码和页大小开启分页 + * + * @param pageIndex 页码,从1开始,会自动调整为最小值1 + * @param pageSize 每页大小,会自动调整为最小值1 + */ + public static void startPage(int pageIndex, int pageSize) { + + pageIndex = Math.max(pageIndex, 1); + pageSize = Math.max(pageSize, 1); + + PageHelper.startPage(pageIndex, pageSize); + } + + /** + * 根据分页VO开启分页 + * 使用分页VO中的参数开启分页,如果参数为空则使用默认值 + * + * @param pageVo 分页VO,可以为null + */ + public static void startPage(PageVo pageVo) { + + if (ObjectUtil.isNull(pageVo)) { + startPage(MybatisConstants.DEFAULT_PAGE_INDEX, MybatisConstants.DEFAULT_PAGE_SIZE); + return; + } + + if (ObjectUtil.isNull(pageVo.getPageIndex())) { + pageVo.setPageIndex(MybatisConstants.DEFAULT_PAGE_INDEX); + } + + if (ObjectUtil.isNull(pageVo.getPageSize())) { + pageVo.setPageSize(MybatisConstants.DEFAULT_PAGE_SIZE); + } + + startPage(pageVo.getPageIndex(), pageVo.getPageSize()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageResultUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageResultUtil.java new file mode 100644 index 0000000..08de8d3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/PageResultUtil.java @@ -0,0 +1,172 @@ +package com.lframework.starter.web.core.utils; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.BeanUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import jakarta.validation.constraints.NotNull; +import lombok.NonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 分页结果工具类 + * 提供分页数据转换和构建功能,支持MyBatis-Plus和PageHelper的分页结果转换 + * 包括分页信息提取、数据转换、分页结果构建等功能 + * + * @author lframework@163.com + */ +public class PageResultUtil { + + /** + * 将MyBatis-Plus分页结果转换为PageResult + * 不包含额外数据 + * + * @param page MyBatis-Plus分页结果,不能为null + * @param 数据类型 + * @return 转换后的分页结果 + */ + public static PageResult convert(@NonNull IPage page) { + + return convert(page, null); + } + + /** + * 将PageHelper分页结果转换为PageResult + * 不包含额外数据 + * + * @param pageInfo PageHelper分页结果,不能为null + * @param 数据类型 + * @return 转换后的分页结果 + */ + public static PageResult convert(@NonNull PageInfo pageInfo) { + + return convert(pageInfo, null); + } + + /** + * 将MyBatis-Plus分页结果转换为PageResult + * 支持包含额外数据 + * + * @param page MyBatis-Plus分页结果,不能为null + * @param extra 额外数据,可以为null + * @param 数据类型 + * @return 转换后的分页结果 + */ + public static PageResult convert(@NotNull IPage page, + Map extra) { + PageResult pageResult = new PageResult<>(); + List datas = new ArrayList(page.getRecords()); + pageResult.setDatas(datas); + pageResult.setHasPrev(page.getCurrent() > 1); + pageResult.setHasNext(page.getCurrent() < page.getPages()); + pageResult.setPageIndex(page.getCurrent()); + pageResult.setPageSize(page.getSize()); + pageResult.setTotalCount(page.getTotal()); + pageResult.setTotalPage((int) page.getPages()); + if (!ObjectUtil.isEmpty(extra)) { + pageResult.setExtra(extra); + } + + return pageResult; + } + + /** + * 将PageHelper分页结果转换为PageResult + * 支持包含额外数据 + * + * @param pageInfo PageHelper分页结果,不能为null + * @param extra 额外数据,可以为null + * @param 数据类型 + * @return 转换后的分页结果 + */ + public static PageResult convert(@NonNull PageInfo pageInfo, + Map extra) { + + PageResult pageResult = new PageResult<>(); + List datas = new ArrayList(pageInfo.getList()); + pageResult.setDatas(datas); + pageResult.setHasNext(pageInfo.isHasNextPage()); + pageResult.setHasPrev(pageInfo.isHasPreviousPage()); + pageResult.setPageIndex(pageInfo.getPageNum()); + pageResult.setPageSize(pageInfo.getPageSize()); + pageResult.setTotalCount(pageInfo.getTotal()); + pageResult.setTotalPage(pageInfo.getPages()); + if (!ObjectUtil.isEmpty(extra)) { + pageResult.setExtra(extra); + } + + return pageResult; + } + + /** + * 重建分页结果 + * 保留原分页信息,替换数据列表 + * + * @param pageResult 原分页结果,不能为null + * @param datas 新的数据列表,可以为null + * @param 数据类型 + * @return 重建后的分页结果 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static PageResult rebuild(@SuppressWarnings("rawtypes") PageResult pageResult, + List datas) { + + PageResult result = new PageResult<>(); + BeanUtil.copyProperties(pageResult, result, "datas"); + + result.setDatas(datas == null ? CollectionUtil.emptyList() : datas); + + pageResult.setDatas(datas); + + return result; + } + + /** + * 创建新的分页结果实例 + * 不包含额外数据 + * + * @param pageIndex 页码,从1开始 + * @param pageSize 每页大小 + * @param totalCount 总记录数 + * @param datas 数据列表,可以为null + * @param 数据类型 + * @return 分页结果实例 + */ + public static PageResult newInstance(long pageIndex, long pageSize, long totalCount, + List datas) { + + return newInstance(pageIndex, pageSize, totalCount, datas, null); + } + + /** + * 创建新的分页结果实例 + * 支持包含额外数据 + * + * @param pageIndex 页码,从1开始 + * @param pageSize 每页大小 + * @param totalCount 总记录数 + * @param datas 数据列表,可以为null + * @param extra 额外数据,可以为null + * @param 数据类型 + * @return 分页结果实例 + */ + public static PageResult newInstance(long pageIndex, long pageSize, long totalCount, + List datas, Map extra) { + PageResult pageResult = new PageResult<>(); + pageResult.setTotalCount(totalCount); + pageResult.setPageSize(pageSize); + pageResult.setPageIndex(pageIndex); + pageResult.setTotalPage((int) (totalCount / pageSize) + (totalCount % pageSize > 0 ? 1 : 0)); + pageResult.setDatas(datas); + pageResult.setExtra(extra); + pageResult.setHasNext(pageResult.getPageIndex() < pageResult.getTotalPage()); + pageResult.setHasPrev(pageResult.getPageIndex() > 1); + + return pageResult; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/RequestUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/RequestUtil.java new file mode 100644 index 0000000..44db2fb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/RequestUtil.java @@ -0,0 +1,222 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * HTTP请求工具类 + * 提供HTTP请求相关的工具方法,支持请求信息获取和处理 + * 包括请求头获取、参数提取、IP地址获取、请求体读取等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class RequestUtil { + + /** + * 获取当前HTTP请求对象 + * 从Spring的RequestContextHolder中获取当前请求 + * + * @return HTTP请求对象 + */ + public static HttpServletRequest getRequest() { + + HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder + .currentRequestAttributes())).getRequest(); + + return request; + } + + /** + * 获取当前HTTP响应对象 + * 从Spring的RequestContextHolder中获取当前响应 + * + * @return HTTP响应对象 + */ + public static HttpServletResponse getResponse() { + + HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder + .currentRequestAttributes())).getResponse(); + + return response; + } + + /** + * 获取所有请求头 + * 获取当前请求的所有请求头信息 + * + * @return 请求头映射,如果无请求头则返回空Map + */ + public static Map getHeaders() { + + HttpServletRequest request = getRequest(); + + Enumeration headerNames = request.getHeaderNames(); + if (CollectionUtil.isEmpty(headerNames)) { + return CollectionUtil.emptyMap(); + } + + Map headers = new HashMap<>(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + + return headers; + } + + /** + * 获取请求参数 + * 从指定请求中提取所有参数 + * + * @param request HTTP请求对象,不能为null + * @return 参数映射,参数名为键,参数值为值 + */ + public static Map getParameters(HttpServletRequest request) { + + Map parameterMap = request.getParameterMap(); + Map parameters = new HashMap<>(parameterMap.size()); + + parameterMap.entrySet().stream().forEach(entry -> { + String[] values = entry.getValue(); + if (!ArrayUtil.isEmpty(values)) { + parameters.put(entry.getKey(), values[0]); + } + }); + + return parameters; + } + + /** + * 获取请求体字节数组 + * 从指定请求中读取请求体内容 + * + * @param request HTTP请求对象,不能为null + * @return 请求体字节数组,如果读取失败则返回null + */ + public static byte[] getRequestBody(HttpServletRequest request) { + + int len = request.getContentLength(); + ServletInputStream is = null; + try { + is = request.getInputStream(); + + byte[] buffer = new byte[len]; + is.read(buffer, 0, len); + + return buffer; + } catch (IOException e) { + log.error(e.getMessage(), e); + + return null; + } + } + + /** + * 获取当前请求体字节数组 + * 从当前请求中读取请求体内容 + * + * @return 请求体字节数组,如果读取失败则返回null + */ + public static byte[] getRequestBody() { + + HttpServletRequest request = getRequest(); + return getRequestBody(request); + } + + /** + * 获取请求体字符串 + * 从指定请求中读取请求体内容并转换为UTF-8字符串 + * + * @param request HTTP请求对象,不能为null + * @return 请求体字符串,如果读取失败则返回null + */ + public static String getRequestBodyStr(HttpServletRequest request) { + byte[] bytes = getRequestBody(request); + + return new String(bytes, StandardCharsets.UTF_8); + } + + /** + * 获取当前请求体字符串 + * 从当前请求中读取请求体内容并转换为UTF-8字符串 + * + * @return 请求体字符串,如果读取失败则返回null + */ + public static String getRequestBodyStr() { + byte[] bytes = getRequestBody(); + + return new String(bytes, StandardCharsets.UTF_8); + } + + /** + * 获取当前请求参数 + * 从当前请求中提取所有参数 + * + * @return 参数映射,参数名为键,参数值为值 + */ + public static Map getParameters() { + + Map parameterMap = getRequest().getParameterMap(); + Map parameters = new HashMap<>(parameterMap.size()); + + parameterMap.entrySet().stream().forEach(entry -> { + String[] values = entry.getValue(); + if (!ArrayUtil.isEmpty(values)) { + parameters.put(entry.getKey(), values[0]); + } + }); + + return parameters; + } + + /** + * 获取请求的客户端IP地址 + * 通过多种方式尝试获取真实的客户端IP地址 + * + * @return 客户端IP地址 + */ + public static String getRequestIp() { + + HttpServletRequest request = getRequest(); + + String ip = request.getHeader("x-forwarded-for"); + if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) { + // 多次反向代理后会有多个ip值,第一个ip才是真实ip + if (ip.indexOf(",") != -1) { + ip = ip.split(",")[0]; + } + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/ResponseUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ResponseUtil.java new file mode 100644 index 0000000..a1570ec --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ResponseUtil.java @@ -0,0 +1,137 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +/** + * HTTP响应工具类 + * 提供HTTP响应相关的工具方法,支持响应数据输出和文件下载 + * 包括JSON响应、错误响应、文件下载等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class ResponseUtil { + + /** + * 获取当前HTTP响应对象 + * 从Spring的RequestContextHolder中获取当前响应 + * + * @return HTTP响应对象 + */ + public static HttpServletResponse getResponse() { + + HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse(); + + return response; + } + + /** + * 响应错误信息 + * 将错误信息以JSON格式响应给客户端 + * + * @param response HTTP响应对象,不能为null + * @param e 业务异常,不能为null + * @throws DefaultSysException 当响应写入失败时抛出 + */ + public static void respFailJson(HttpServletResponse response, BaseException e) { + + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(StringPool.CHARACTER_ENCODING_UTF_8); + + try { + response.getWriter().print(JsonUtil.toJsonString(InvokeResultBuilder.fail(e))); + } catch (IOException ex) { + log.error(ex.getMessage(), ex); + throw new DefaultSysException(); + } + } + + /** + * 响应成功JSON + * 将成功数据以JSON格式响应给客户端 + * + * @param response HTTP响应对象,不能为null + * @param obj 响应数据,可以为null + * @throws DefaultSysException 当响应写入失败时抛出 + */ + public static void respSuccessJson(HttpServletResponse response, Object obj) { + + response.setStatus(HttpStatus.OK.value()); + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(StringPool.CHARACTER_ENCODING_UTF_8); + + try { + response.getWriter().print(JsonUtil.toJsonString(InvokeResultBuilder.success(obj))); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(); + } + } + + /** + * 下载文件(使用文件名) + * 使用文件的原文件名进行下载 + * + * @param file 要下载的文件,不能为null + */ + public static void download(File file) { + + download(file, file.getName()); + } + + /** + * 下载文件(指定文件名) + * 使用指定的文件名进行下载 + * + * @param file 要下载的文件,不能为null + * @param fileName 下载文件名,不能为null + */ + public static void download(File file, String fileName) { + + download(file, fileName, "application/octet-stream"); + } + + /** + * 下载文件(指定文件名和内容类型) + * 使用指定的文件名和内容类型进行下载 + * + * @param file 要下载的文件,不能为null + * @param fileName 下载文件名,不能为null + * @param contentType 内容类型,不能为null + * @throws DefaultSysException 当文件读取失败时抛出 + */ + public static void download(File file, String fileName, String contentType) { + + HttpServletResponse response = getResponse(); + response.setContentType(contentType); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setHeader("FileName", fileName); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + + OutputStream os = null; + try { + os = response.getOutputStream(); + os.write(FileUtil.readBytes(file)); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/SimpleMap.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/SimpleMap.java new file mode 100644 index 0000000..598cf9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/SimpleMap.java @@ -0,0 +1,150 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.StringUtil; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * 简单Map工具类 + * 继承HashMap并提供便捷的类型转换方法 + * 包括字符串转换、数值转换、空值过滤等功能 + * + * @author lframework@163.com + */ +public class SimpleMap extends HashMap implements Map, Cloneable, Serializable { + + /** + * 构造函数(指定初始容量和负载因子) + * + * @param initialCapacity 初始容量 + * @param loadFactor 负载因子 + */ + public SimpleMap(int initialCapacity, float loadFactor) { + + super(initialCapacity, loadFactor); + } + + /** + * 构造函数(指定初始容量) + * + * @param initialCapacity 初始容量 + */ + public SimpleMap(int initialCapacity) { + + super(initialCapacity); + } + + /** + * 默认构造函数 + */ + public SimpleMap() { + + } + + /** + * 构造函数(基于现有Map) + * + * @param m 现有Map,不能为null + */ + public SimpleMap(Map m) { + + super(m); + } + + /** + * 获取字符串值(使用默认值null) + * + * @param k 键,不能为null + * @return 字符串值,如果不存在或转换失败则返回null + */ + public String getString(K k) { + + return getString(k, null); + } + + /** + * 获取字符串值(指定默认值) + * + * @param k 键,不能为null + * @param defaultValue 默认值,可以为null + * @return 字符串值,如果不存在则返回默认值 + */ + public String getString(K k, V defaultValue) { + + Object v = this.getOrDefault(k, defaultValue); + if (v == null) { + return null; + } + if (v instanceof String) { + return (String) v; + } + + return String.valueOf(v); + } + + /** + * 获取长整型值(使用默认值null) + * + * @param k 键,不能为null + * @return 长整型值,如果不存在或转换失败则返回null + */ + public Long getLong(K k) { + + return getLong(k, null); + } + + /** + * 获取长整型值(指定默认值) + * + * @param k 键,不能为null + * @param defaultValue 默认值,可以为null + * @return 长整型值,如果不存在或转换失败则返回默认值 + */ + public Long getLong(K k, V defaultValue) { + + Object v = this.getOrDefault(k, defaultValue); + if (v == null || StringUtil.isEmpty(v.toString())) { + return null; + } + if (v instanceof Long) { + return (Long) v; + } + + return Long.valueOf(v.toString()); + } + + /** + * 重写put方法,过滤空值 + * 只有当值不为null且不为空字符串时才存储 + * + * @param key 键,不能为null + * @param value 值,如果为null或空字符串则不存储 + * @return 如果存储成功则返回原值,否则返回null + */ + @Override + public V put(K key, V value) { + + if (value == null) { + return null; + } + + if (value instanceof CharSequence && StringUtil.isEmpty((CharSequence) value)) { + return null; + } + + return super.put(key, value); + } + + /** + * 转换为JSON字符串 + * 将当前Map转换为JSON格式的字符串 + * + * @return JSON字符串 + */ + public String toJsonString() { + + return JsonUtil.toJsonString(this); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/SpelUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/SpelUtil.java new file mode 100644 index 0000000..92f0120 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/SpelUtil.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.core.utils; + +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.util.Map; + +/** + * Spring表达式语言工具类 + * 提供SpEL表达式解析和计算功能,支持动态表达式执行 + * 包括表达式解析、变量绑定、上下文构建等功能 + * + * @author lframework@163.com + */ +public class SpelUtil { + + private static final SpelExpressionParser PARSER; + + static { + PARSER = new SpelExpressionParser(); + } + + /** + * 解析SpEL表达式(使用指定上下文) + * 使用指定的评估上下文解析表达式 + * + * @param expression SpEL表达式,不能为null + * @param ctx 评估上下文,不能为null + * @return 表达式计算结果 + */ + public static Object parse(String expression, EvaluationContext ctx) { + + return PARSER.parseExpression(expression).getValue(ctx); + } + + /** + * 解析SpEL表达式(使用变量映射) + * 使用变量映射构建上下文并解析表达式 + * + * @param expression SpEL表达式,不能为null + * @param vars 变量映射,不能为null + * @return 表达式计算结果 + */ + public static Object parse(String expression, Map vars) { + + EvaluationContext ctx = buildContext(); + vars.forEach(ctx::setVariable); + + return parse(expression, ctx); + } + + /** + * 构建评估上下文 + * 创建标准的SpEL评估上下文 + * + * @return 评估上下文实例 + */ + public static EvaluationContext buildContext() { + + return new StandardEvaluationContext(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/TenantUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/TenantUtil.java new file mode 100644 index 0000000..f141fc4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/TenantUtil.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.core.utils; + +/** + * 多租户工具类 + * 提供多租户相关的工具方法,支持租户功能开关控制 + * 包括租户启用状态检查等功能 + * + * @author lframework@163.com + */ +public class TenantUtil { + + /** + * 检查是否启用多租户功能 + * 从配置中获取多租户功能的启用状态 + * + * @return true-已启用多租户,false-未启用多租户 + */ + public static boolean enableTenant() { + return true; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/TransactionUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/TransactionUtil.java new file mode 100644 index 0000000..c55d8a3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/TransactionUtil.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.core.utils; + +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; + +/** + * 事务工具类 + * 提供手动事务管理功能,支持编程式事务控制 + * 包括事务获取、提交、回滚等功能 + * + * @author lframework@163.com + */ +public class TransactionUtil { + + /** + * 获取事务状态 + * 创建新的事务并返回事务状态对象 + * + * @return 事务状态对象 + */ + public static TransactionStatus getTransaction() { + PlatformTransactionManager platformTransactionManager = ApplicationUtil.getBean( + PlatformTransactionManager.class); + TransactionDefinition transactionDefinition = ApplicationUtil.getBean( + TransactionDefinition.class); + + return platformTransactionManager.getTransaction(transactionDefinition); + } + + /** + * 提交事务 + * 提交指定的事务状态 + * + * @param transactionStatus 事务状态对象,不能为null + */ + public static void commit(TransactionStatus transactionStatus) { + PlatformTransactionManager platformTransactionManager = ApplicationUtil.getBean( + PlatformTransactionManager.class); + platformTransactionManager.commit(transactionStatus); + } + + /** + * 回滚事务 + * 回滚指定的事务状态 + * + * @param transactionStatus 事务状态对象,不能为null + */ + public static void rollback(TransactionStatus transactionStatus) { + PlatformTransactionManager platformTransactionManager = ApplicationUtil.getBean( + PlatformTransactionManager.class); + platformTransactionManager.rollback(transactionStatus); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/UploadUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/UploadUtil.java new file mode 100644 index 0000000..e7e091c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/UploadUtil.java @@ -0,0 +1,208 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.*; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.components.upload.UploadHandlerFactory; +import com.lframework.starter.web.core.components.upload.client.dto.UploadDto; +import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler; +import com.lframework.starter.web.core.components.upload.handler.UploadHandler; +import com.lframework.starter.web.inner.service.SysConfService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 文件上传工具类 + * 提供文件上传功能,支持多种上传处理器和文件类型验证 + * 包括文件上传、路径生成、文件类型检查等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class UploadUtil { + + /** + * 上传文件(使用默认参数) + * 使用默认设置上传文件,不进行文件类型限制 + * + * @param file 上传文件,不能为null + * @return 上传结果DTO + * @throws DefaultSysException 当文件上传失败时抛出 + */ + public static UploadDto upload(MultipartFile file) { + + return upload(file, Collections.emptyList(), false); + } + + /** + * 上传文件(指定父路径) + * 使用指定的父路径上传文件 + * + * @param file 上传文件,不能为null + * @param parentPath 父路径,不能为null + * @return 上传结果DTO + * @throws DefaultSysException 当文件上传失败时抛出 + */ + public static UploadDto upload(MultipartFile file, String parentPath) { + + return upload(file, parentPath, false); + } + + /** + * 上传文件(指定父路径和安全设置) + * 使用指定的父路径和安全设置上传文件 + * + * @param file 上传文件,不能为null + * @param parentPath 父路径,不能为null + * @param security 是否启用安全模式 + * @return 上传结果DTO + * @throws DefaultSysException 当文件上传失败时抛出 + */ + public static UploadDto upload(MultipartFile file, String parentPath, Boolean security) { + + return upload(file, Collections.singletonList(parentPath), security); + } + + /** + * 上传文件(指定父路径列表和安全设置) + * 使用指定的父路径列表和安全设置上传文件 + * + * @param file 上传文件,不能为null + * @param parentPathList 父路径列表,不能为null + * @param security 是否启用安全模式 + * @return 上传结果DTO + * @throws DefaultSysException 当文件上传失败时抛出 + */ + public static UploadDto upload(MultipartFile file, List parentPathList, + Boolean security) { + + Assert.notNull(file); + try (InputStream is = file.getInputStream()) { + return upload(is, file.getOriginalFilename(), parentPathList, security); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 上传文件 + * + * @param file + * @return + */ + public static UploadDto upload(File file) { + + return upload(file, Collections.emptyList(), false); + } + + /** + * 上传文件 + * + * @param file + * @return + */ + public static UploadDto upload(File file, String parentPath) { + + return upload(file, parentPath, false); + } + + /** + * 上传文件 + * + * @param file + * @return + */ + public static UploadDto upload(File file, String parentPath, Boolean security) { + + return upload(file, Collections.singletonList(parentPath), security); + } + + /** + * 上传文件 + * + * @param file + * @return + */ + public static UploadDto upload(File file, List parentPathList, Boolean security) { + + Assert.notNull(file); + try (InputStream is = FileUtil.getInputStream(file)) { + return upload(is, file.getName(), parentPathList, security); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * 上传文件 + * + * @return + */ + public static UploadDto upload(InputStream is, String fileName, List parentPathList, + Boolean security) { + + Assert.notNull(is); + SysConfService sysConfService = ApplicationUtil.getBean(SysConfService.class); + String key = security ? "security-upload.type" : "upload.type"; + String uploadTypeStr = sysConfService.findByKey(key, "LOCAL"); + + String suffix = FileUtil.getSuffix(fileName); + String randomFileName = IdUtil.getUUID(); + String fullFileName = + randomFileName + (StringUtil.isEmpty(suffix) ? StringPool.EMPTY_STR : ("." + suffix)); + + if (security) { + SecurityUploadHandler uploadHandler = UploadHandlerFactory.getSecurityInstance(uploadTypeStr); + + return uploadHandler.upload(is, getDefaultLocations(parentPathList), fullFileName); + } else { + UploadHandler uploadHandler = UploadHandlerFactory.getInstance(uploadTypeStr); + + return uploadHandler.upload(is, getDefaultLocations(parentPathList), fullFileName); + } + } + + public static String generatePresignedUrl(String uploadType, String objectName) { + + SysConfService sysConfService = ApplicationUtil.getBean(SysConfService.class); + SecurityUploadHandler uploadHandler = UploadHandlerFactory.getSecurityInstance(uploadType); + Long expire = sysConfService.getLong("security-upload.sign-url-expired", 600L); + + return uploadHandler.generatePresignedUrl(objectName, expire); + } + + /** + * 获取默认的locations + * + * @return + */ + private static List getDefaultLocations(List parentPathList) { + + LocalDate now = LocalDate.now(); + List locations = new ArrayList<>(); + if(TenantUtil.enableTenant()) { + locations.add(TenantContextHolder.getTenantIdStr()); + } + if (!CollectionUtil.isEmpty(parentPathList)) { + locations.addAll(parentPathList.stream().filter(t -> !StringUtil.isBlank(t)).collect( + Collectors.toList())); + } + locations.add(DateUtil.formatDate(now, "yyyy")); + locations.add(DateUtil.formatDate(now, "MM")); + locations.add(DateUtil.formatDate(now, "dd")); + + return locations; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/ValidateUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ValidateUtil.java new file mode 100644 index 0000000..ed14c92 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/ValidateUtil.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; + +import java.util.Enumeration; +import java.util.Map; + +/** + * 验证工具类 + * 提供各种类型对象的空值验证功能,支持多种数据类型的判空 + * 包括字符串、集合、数组、Map等类型的空值检查 + * + * @author lframework@163.com + */ +public class ValidateUtil { + + /** + * 判断对象是否为空 + * 支持多种类型的空值检查,包括字符串、集合、数组、Map等 + * + * @param val 要检查的对象,可以为null + * @return true-对象为空,false-对象不为空 + */ + public static boolean isEmpty(Object val) { + + if (val == null) { + return true; + } + + if (val instanceof CharSequence) { + return StringUtil.isEmpty((CharSequence) val); + } + + if (val instanceof Iterable) { + return CollectionUtil.isEmpty((Iterable) val); + } + + if (val instanceof Map) { + return CollectionUtil.isEmpty((Map) val); + } + + if (val instanceof Enumeration) { + return CollectionUtil.isEmpty((Enumeration) val); + } + + if (val instanceof Object[]) { + return ArrayUtil.isEmpty((Object[]) val); + } + + return false; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/utils/VideoUtil.java b/web-starter/src/main/java/com/lframework/starter/web/core/utils/VideoUtil.java new file mode 100644 index 0000000..cdd197f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/utils/VideoUtil.java @@ -0,0 +1,81 @@ +package com.lframework.starter.web.core.utils; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import lombok.extern.slf4j.Slf4j; +import org.jcodec.api.FrameGrab; +import org.jcodec.api.JCodecException; +import org.jcodec.common.model.Picture; +import org.jcodec.scale.AWTUtil; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +/** + * 视频工具类 + * 提供视频处理相关的工具方法,支持视频帧提取和图片保存 + * 包括视频帧提取、图片保存等功能 + * + * @author lframework@163.com + */ +@Slf4j +public class VideoUtil { + + /** + * 获取视频指定帧的图片 + * 从视频文件中提取指定帧号的图片 + * + * @param file 视频文件,不能为null + * @param frameNumber 帧号,不能为null + * @return 图片对象,如果提取失败则抛出异常 + * @throws DefaultSysException 当视频处理失败时抛出 + */ + public static BufferedImage getImage(File file, Integer frameNumber) { + Picture picture = null; + try { + picture = FrameGrab.getFrameFromFile(file, frameNumber); + } catch (IOException | JCodecException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + BufferedImage bufferedImage = AWTUtil.toBufferedImage(picture); + + return bufferedImage; + } + + /** + * 获取视频指定帧的图片并保存 + * 从视频文件中提取指定帧号的图片并保存到指定路径 + * + * @param file 视频文件,不能为null + * @param frameNumber 帧号,不能为null + * @param fullPath 保存路径,不能为null + * @return 保存的图片文件,如果处理失败则抛出异常 + * @throws DefaultSysException 当视频处理失败时抛出 + */ + public static File getImage(File file, Integer frameNumber, String fullPath) { + BufferedImage bufferedImage = getImage(file, frameNumber); + return savePngImage(bufferedImage, fullPath); + } + + /** + * 保存图片为PNG格式 + * 将BufferedImage保存为PNG格式的图片文件 + * + * @param image 图片对象,不能为null + * @param fullPath 保存路径,不能为null + * @return 保存的图片文件,如果保存失败则抛出异常 + * @throws DefaultSysException 当图片保存失败时抛出 + */ + public static File savePngImage(BufferedImage image, String fullPath) { + try { + File saveFile = new File(fullPath); + ImageIO.write(image, "png", new File(fullPath)); + return saveFile; + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/vo/BaseVo.java b/web-starter/src/main/java/com/lframework/starter/web/core/vo/BaseVo.java new file mode 100644 index 0000000..0fee954 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/vo/BaseVo.java @@ -0,0 +1,9 @@ +package com.lframework.starter.web.core.vo; + +/** + * Vo基类 + * + * @author zmj + */ +public interface BaseVo { +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/vo/PageVo.java b/web-starter/src/main/java/com/lframework/starter/web/core/vo/PageVo.java new file mode 100644 index 0000000..a766dc2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/vo/PageVo.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.core.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 分页Vo + * + * @author zmj + */ +@Data +public abstract class PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 当前页码 + */ + @Schema(description = "当前页码", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer pageIndex; + + /** + * 每页条数 + */ + @Schema(description = "每页条数", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer pageSize; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/vo/SortPageVo.java b/web-starter/src/main/java/com/lframework/starter/web/core/vo/SortPageVo.java new file mode 100644 index 0000000..097d67f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/core/vo/SortPageVo.java @@ -0,0 +1,22 @@ +package com.lframework.starter.web.core.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public abstract class SortPageVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 排序字段 + */ + @Schema(description = "排序字段") + private String sortField; + + /** + * 排序类型 + */ + @Schema(description = "排序类型") + private String sortOrder; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/CollectMenuBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/CollectMenuBo.java new file mode 100644 index 0000000..fc7cdab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/CollectMenuBo.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.VoidDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class CollectMenuBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 路由路径 + */ + @Schema(description = "路由路径") + private String path; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/ForgetPswUserInfoBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/ForgetPswUserInfoBo.java new file mode 100644 index 0000000..f90cfe6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/ForgetPswUserInfoBo.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.SuperBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class ForgetPswUserInfoBo implements SuperBo { + + /** + * 用户名 + */ + @Schema(description = "用户名") + private String username; + + /** + * 邮箱 + */ + @Schema(description = "邮箱,脱敏") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话,脱敏") + private String telephone; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/LoginBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/LoginBo.java new file mode 100644 index 0000000..81243fe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/LoginBo.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.system.LoginDto; +import com.lframework.starter.web.inner.dto.system.LoginDto.UserInfoDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Set; + +@Data +public class LoginBo extends BaseBo { + + /** + * Token + */ + @Schema(description = "Token") + private String token; + + /** + * 用户信息 + */ + @Schema(description = "用户信息") + private UserInfoBo user; + + /** + * 角色 + */ + @Schema(description = "角色") + private Set roles; + + public LoginBo() { + } + + public LoginBo(LoginDto dto) { + super(dto); + } + + @Override + protected void afterInit(LoginDto dto) { + + this.user = new UserInfoBo(dto.getUser()); + } + + @Data + public static class UserInfoBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + public UserInfoBo() { + } + + public UserInfoBo(UserInfoDto dto) { + super(dto); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/MenuBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/MenuBo.java new file mode 100644 index 0000000..c0ba760 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/MenuBo.java @@ -0,0 +1,115 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.VoidDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class MenuBo extends BaseBo { + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 组件 + */ + @Schema(description = "组件") + private String component; + + /** + * 子节点 + */ + @Schema(description = "子节点") + private List children; + + /** + * 路由路径 + */ + @Schema(description = "路由路径") + private String path; + + /** + * 元数据 + */ + @Schema(description = "元数据") + private MetaBo meta; + + public MenuBo() { + } + + @Data + public static class MetaBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 是否隐藏 + */ + @Schema(description = "是否隐藏") + private Boolean hideMenu; + + /** + * 是否不缓存 + */ + @Schema(description = "是否不缓存") + private Boolean ignoreKeepAlive; + + /** + * 是否固定 + */ + @Schema(description = "是否固定") + private Boolean affix = Boolean.FALSE; + + /** + * 是否外部链接 + */ + @Schema(description = "是否外部链接") + private Boolean isLink = Boolean.FALSE; + + /** + * 是否收藏 + */ + @Schema(description = "是否收藏") + private Boolean isCollect = Boolean.FALSE; + + /** + * 内嵌链接地址 + */ + @Schema(description = "内嵌链接地址") + private String frameSrc; + + /** + * 自定义列表ID + */ + @Schema(description = "自定义列表ID") + private String customListId; + + /** + * 自定义页面ID + */ + @Schema(description = "自定义页面ID") + private String customPageId; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TelephoneLoginBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TelephoneLoginBo.java new file mode 100644 index 0000000..51bf258 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TelephoneLoginBo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.system.LoginDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 手机号登录Bo + * + * @author zmj + * @since 2022/4/25 + */ +@Data +public class TelephoneLoginBo extends BaseBo { + + /** + * 登录信息 + */ + @Schema(description = "登录信息") + private LoginBo loginInfo; + + /** + * 是否绑定用户 + */ + @Schema(description = "是否绑定用户") + private Boolean isBind = Boolean.TRUE; + + public TelephoneLoginBo() { + + } + + public TelephoneLoginBo(LoginDto dto) { + + this.afterInit(dto); + } + + @Override + protected void afterInit(LoginDto dto) { + + this.loginInfo = new LoginBo(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TenantRequireBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TenantRequireBo.java new file mode 100644 index 0000000..d7a5af8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/auth/TenantRequireBo.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.inner.bo.auth; + +import com.lframework.starter.web.core.bo.SuperBo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class TenantRequireBo implements SuperBo { + + /** + * 是否开启多租户 + */ + @Schema(description = "是否开启多租户") + private Boolean enable; + + /** + * 当前租户ID + */ + @Schema(description = "当前租户ID") + private Integer tenantId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/oplog/OpLogInUserCenterBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/oplog/OpLogInUserCenterBo.java new file mode 100644 index 0000000..d37fc0b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/oplog/OpLogInUserCenterBo.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.inner.bo.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.OpLogs; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class OpLogInUserCenterBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 日志名称 + */ + @Schema(description = "日志名称") + private String name; + + /** + * 类别 + */ + @Schema(description = "类别") + private Integer logType; + + /** + * IP + */ + @Schema(description = "IP") + private String ip; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public OpLogInUserCenterBo() { + + } + + public OpLogInUserCenterBo(OpLogs dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/GetQrtzBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/GetQrtzBo.java new file mode 100644 index 0000000..82ef807 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/GetQrtzBo.java @@ -0,0 +1,101 @@ +package com.lframework.starter.web.inner.bo.qrtz; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class GetQrtzBo extends BaseBo { + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分组 + */ + @Schema(description = "分组") + private String group; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 执行类名 + */ + @Schema(description = "执行类名") + private String targetClassName; + + /** + * 执行方法名 + */ + @Schema(description = "执行方法名") + private String targetMethodName; + + /** + * 执行参数类型 + */ + @Schema(description = "执行参数类型") + private List targetParamTypes; + + /** + * 执行参数 + */ + @Schema(description = "执行参数") + private List targetParams; + + /** + * 脚本 + */ + @Schema(description = "脚本") + private String script; + + /** + * 任务类型 + */ + @Schema(description = "任务类型") + private Integer jobType; + + /** + * Cron表达式 + */ + @Schema(description = "Cron表达式") + private String cron; + + /** + * 状态 + */ + @Schema(description = "状态") + private String state; + + public GetQrtzBo(QrtzDto dto) { + super(dto); + } + + @Override + public BaseBo convert(QrtzDto dto) { + return super.convert(dto, GetQrtzBo::getState); + } + + @Override + protected void afterInit(QrtzDto dto) { + this.jobType = dto.getJobType().getCode(); + if (dto.getState() != null) { + this.state = dto.getState().getCode(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/QueryQrtzBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/QueryQrtzBo.java new file mode 100644 index 0000000..6866ff2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/qrtz/QueryQrtzBo.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.inner.bo.qrtz; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryQrtzBo extends BaseBo { + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分组 + */ + @Schema(description = "分组") + private String group; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 任务类型 + */ + @Schema(description = "任务类型") + private Integer jobType; + + /** + * Cron表达式 + */ + @Schema(description = "Cron表达式") + private String cron; + + /** + * 状态 + */ + @Schema(description = "状态") + private String state; + + public QueryQrtzBo(QrtzDto dto) { + super(dto); + } + + @Override + public BaseBo convert(QrtzDto dto) { + return super.convert(dto, QueryQrtzBo::getState); + } + + @Override + protected void afterInit(QrtzDto dto) { + this.jobType = dto.getJobType().getCode(); + if (dto.getState() != null) { + this.state = dto.getState().getCode(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/GetSysDeptBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/GetSysDeptBo.java new file mode 100644 index 0000000..d0d0b37 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/GetSysDeptBo.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.bo.system.dept; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDept; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysDeptBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 简称 + */ + @Schema(description = "简称") + private String shortName; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysDeptBo() { + + } + + public GetSysDeptBo(SysDept dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptSelectorBo.java new file mode 100644 index 0000000..fee28af --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.bo.system.dept; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDept; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDeptSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + public SysDeptSelectorBo() { + + } + + public SysDeptSelectorBo(SysDept dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptTreeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptTreeBo.java new file mode 100644 index 0000000..a9a64f0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dept/SysDeptTreeBo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.bo.system.dept; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDept; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDeptTreeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + public SysDeptTreeBo() { + + } + + public SysDeptTreeBo(SysDept dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/GetSysDataDicBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/GetSysDataDicBo.java new file mode 100644 index 0000000..3c09290 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/GetSysDataDicBo.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.bo.system.dic; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.service.system.SysDataDicCategoryService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysDataDicBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @Schema(description = "分类名称") + private String categoryName; + + + public GetSysDataDicBo() { + + } + + public GetSysDataDicBo(SysDataDic dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDic dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + SysDataDicCategoryService sysDataDicCategoryService = ApplicationUtil.getBean( + SysDataDicCategoryService.class); + SysDataDicCategory category = sysDataDicCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/QuerySysDataDicBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/QuerySysDataDicBo.java new file mode 100644 index 0000000..8dd82dc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/QuerySysDataDicBo.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.bo.system.dic; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.service.system.SysDataDicCategoryService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysDataDicBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @Schema(description = "分类名称") + private String categoryName; + + + public QuerySysDataDicBo() { + + } + + public QuerySysDataDicBo(SysDataDic dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDic dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + SysDataDicCategoryService sysDataDicCategoryService = ApplicationUtil.getBean( + SysDataDicCategoryService.class); + SysDataDicCategory category = sysDataDicCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/SysDataDicSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/SysDataDicSelectorBo.java new file mode 100644 index 0000000..dd6df50 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/SysDataDicSelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.bo.system.dic; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDic; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataDicSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysDataDicSelectorBo() { + } + + public SysDataDicSelectorBo(SysDataDic dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java new file mode 100644 index 0000000..695a126 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.bo.system.dic.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysDataDicCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + + public GetSysDataDicCategoryBo() { + + } + + public GetSysDataDicCategoryBo(SysDataDicCategory dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java new file mode 100644 index 0000000..c896831 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.bo.system.dic.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysDataDicCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + + public QuerySysDataDicCategoryBo() { + + } + + public QuerySysDataDicCategoryBo(SysDataDicCategory dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java new file mode 100644 index 0000000..b8888ab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.bo.system.dic.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataDicCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysDataDicCategorySelectorBo() { + } + + public SysDataDicCategorySelectorBo(SysDataDicCategory dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/GetSysDataDicItemBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/GetSysDataDicItemBo.java new file mode 100644 index 0000000..c923cf4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/GetSysDataDicItemBo.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.inner.bo.system.dic.item; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 字典ID + */ + @Schema(description = "字典ID") + private String dicId; + + /** + * 排序 + */ + @Schema(description = "排序") + private Integer orderNo; + + + public GetSysDataDicItemBo() { + + } + + public GetSysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/QuerySysDataDicItemBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/QuerySysDataDicItemBo.java new file mode 100644 index 0000000..c629e40 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/QuerySysDataDicItemBo.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.inner.bo.system.dic.item; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 字典ID + */ + @Schema(description = "字典ID") + private String dicId; + + /** + * 排序 + */ + @Schema(description = "排序") + private Integer orderNo; + + + public QuerySysDataDicItemBo() { + + } + + public QuerySysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/SysDataDicItemBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/SysDataDicItemBo.java new file mode 100644 index 0000000..ee4b6e2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/dic/item/SysDataDicItemBo.java @@ -0,0 +1,48 @@ +package com.lframework.starter.web.inner.bo.system.dic.item; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysDataDicItemBo() { + + } + + public SysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDicItem dto) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dataDic = sysDataDicService.findById(dto.getDicId()); + this.id = dataDic.getCode() + StringPool.DATA_DIC_SPLIT + this.code; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/GetSysGenerateCodeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/GetSysGenerateCodeBo.java new file mode 100644 index 0000000..7c87b06 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/GetSysGenerateCodeBo.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.bo.system.generate; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.GenerateCodeDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import com.lframework.starter.web.inner.service.GenerateCodeService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 编号规则 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysGenerateCodeBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @Schema(description = "ID") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 配置规则 + */ + @Schema(description = "配置规则") + private String configStr; + + public GetSysGenerateCodeBo() { + + } + + public GetSysGenerateCodeBo(SysGenerateCode dto) { + + super(dto); + } + + @Override + protected void afterInit(SysGenerateCode dto) { + if (!StringUtil.isBlank(dto.getConfigStr())) { + GenerateCodeService generateCodeService = ApplicationUtil.getBean(GenerateCodeService.class); + GenerateCodeDto generateCodeDto = new GenerateCodeDto(); + generateCodeDto.setId(dto.getId()); + generateCodeDto.setConfigStr(dto.getConfigStr()); + + this.configStr = JsonUtil.toJsonString(generateCodeService.getRules(generateCodeDto)); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/QuerySysGenerateCodeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/QuerySysGenerateCodeBo.java new file mode 100644 index 0000000..12582b4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/generate/QuerySysGenerateCodeBo.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.bo.system.generate; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 编号规则 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysGenerateCodeBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @Schema(description = "ID") + private Long id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public QuerySysGenerateCodeBo() { + + } + + public QuerySysGenerateCodeBo(SysGenerateCode dto) { + + super(dto); + } + + @Override + protected void afterInit(SysGenerateCode dto) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/GetSysMenuBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/GetSysMenuBo.java new file mode 100644 index 0000000..c1d4193 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/GetSysMenuBo.java @@ -0,0 +1,180 @@ +package com.lframework.starter.web.inner.bo.system.menu; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysMenuBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称(前端使用) + */ + @Schema(description = "名称(前端使用)") + private String name; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 组件类型 + */ + @Schema(description = "组件类型(前端使用)") + private Integer componentType; + + /** + * 组件(前端使用) + */ + @Schema(description = "组件(前端使用)") + private String component; + + /** + * 自定义列表ID + */ + @Schema(description = "自定义列表ID") + private String customListId; + + /** + * 自定义列表名称 + */ + @Schema(description = "自定义列表名称") + private String customListName; + + /** + * 自定义表单ID + */ + @Schema(description = "自定义表单ID") + private String customFormId; + + /** + * 自定义表单名称 + */ + @Schema(description = "自定义表单名称") + private String customFormName; + + /** + * 自定义请求参数 + */ + @Schema(description = "自定义请求参数") + private String requestParam; + + /** + * 自定义页面ID + */ + @Schema(description = "自定义页面ID") + private String customPageId; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 父级名称 + */ + @Schema(description = "父级名称") + private String parentName; + + /** + * 路由路径(前端使用) + */ + @Schema(description = "路由路径(前端使用)") + private String path; + + /** + * 是否缓存(前端使用) + */ + @Schema(description = "是否缓存(前端使用)") + private Boolean noCache; + + /** + * 类型 0-目录 1-菜单 2-功能 + */ + @Schema(description = "类型 0-目录 1-菜单 2-功能") + private Integer display; + + /** + * 是否隐藏(前端使用) + */ + @Schema(description = "是否隐藏(前端使用)") + private Boolean hidden; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 是否特殊菜单 + */ + @Schema(description = "是否特殊菜单") + private Boolean isSpecial; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysMenuBo() { + + } + + public GetSysMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public
BaseBo convert(SysMenu dto) { + + return super.convert(dto, GetSysMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + if (!StringUtil.isBlank(dto.getParentId())) { + SysMenuService sysMenuService = ApplicationUtil.getBean(SysMenuService.class); + this.parentName = sysMenuService.findById(dto.getParentId()).getTitle(); + } + + this.componentType = dto.getComponentType() == null ? null : dto.getComponentType().getCode(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/QuerySysMenuBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/QuerySysMenuBo.java new file mode 100644 index 0000000..7d487be --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/QuerySysMenuBo.java @@ -0,0 +1,93 @@ +package com.lframework.starter.web.inner.bo.system.menu; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysMenu; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysMenuBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 类型 + */ + @Schema(description = "类型") + private Integer display; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 是否特殊菜单 + */ + @Schema(description = "是否特殊菜单") + private Boolean isSpecial; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public QuerySysMenuBo() { + + } + + public QuerySysMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public BaseBo convert(SysMenu dto) { + + return super.convert(dto, QuerySysMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/SysMenuSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/SysMenuSelectorBo.java new file mode 100644 index 0000000..a402229 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/menu/SysMenuSelectorBo.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.bo.system.menu; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysMenu; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysMenuSelectorBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + public SysMenuSelectorBo() { + + } + + public SysMenuSelectorBo(SysMenu dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/GetSysMailMessageBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/GetSysMailMessageBo.java new file mode 100644 index 0000000..6991506 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/GetSysMailMessageBo.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.bo.system.message.mail; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 邮件消息 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysMailMessageBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容") + private String content; + + public GetSysMailMessageBo() { + + } + + public GetSysMailMessageBo(SysMailMessage dto) { + + super(dto); + } + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/QuerySysMailMessageBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/QuerySysMailMessageBo.java new file mode 100644 index 0000000..8b671e3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/mail/QuerySysMailMessageBo.java @@ -0,0 +1,70 @@ +package com.lframework.starter.web.inner.bo.system.message.mail; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.annotations.constants.EncryType; +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 邮件消息 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysMailMessageBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 接收邮箱 + */ + @Schema(description = "接收邮箱") + @EncryptConvert(type = EncryType.EMAIL) + private String mail; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 发送状态 + */ + @Schema(description = "发送状态") + private Integer sendStatus; + + public QuerySysMailMessageBo() { + + } + + public QuerySysMailMessageBo(SysMailMessage dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/GetSysSiteMessageBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/GetSysSiteMessageBo.java new file mode 100644 index 0000000..3fe7458 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/GetSysSiteMessageBo.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.bo.system.message.site; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 站内信 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysSiteMessageBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容") + private String content; + + public GetSysSiteMessageBo() { + + } + + public GetSysSiteMessageBo(SysSiteMessage dto) { + + super(dto); + } + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QueryMySysSiteMessageBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QueryMySysSiteMessageBo.java new file mode 100644 index 0000000..f278cbd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QueryMySysSiteMessageBo.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.bo.system.message.site; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 我的站内信 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryMySysSiteMessageBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryMySysSiteMessageBo() { + + } + + public QueryMySysSiteMessageBo(SysSiteMessage dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QuerySysSiteMessageBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QuerySysSiteMessageBo.java new file mode 100644 index 0000000..1c3d5c6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/message/site/QuerySysSiteMessageBo.java @@ -0,0 +1,84 @@ +package com.lframework.starter.web.inner.bo.system.message.site; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.service.system.SysUserService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 站内信 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysSiteMessageBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 接收人姓名 + */ + @Schema(description = "接收人姓名") + private String receiverName; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + + /** + * 已读时间 + */ + @Schema(description = "已读时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime readTime; + + public QuerySysSiteMessageBo() { + + } + + public QuerySysSiteMessageBo(SysSiteMessage dto) { + + super(dto); + } + + @Override + protected void afterInit(SysSiteMessage dto) { + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class); + SysUser receiver = sysUserService.findById(dto.getReceiverId()); + this.receiverName = receiver.getName(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/module/QuerySysModuleBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/module/QuerySysModuleBo.java new file mode 100644 index 0000000..6edb01c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/module/QuerySysModuleBo.java @@ -0,0 +1,46 @@ +package com.lframework.starter.web.inner.bo.system.module; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysModule; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QuerySysModuleBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 是否启用 + */ + @Schema(description = "是否启用") + private Boolean enabled; + + /** + * 过期时间 + */ + @Schema(description = "过期时间") + private LocalDateTime expireTime; + + public QuerySysModuleBo(SysModule dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/GetSysNoticeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/GetSysNoticeBo.java new file mode 100644 index 0000000..2a38b0a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/GetSysNoticeBo.java @@ -0,0 +1,57 @@ +package com.lframework.starter.web.inner.bo.system.notice; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysNotice; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 系统通知 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysNoticeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容") + private String content; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + private Boolean published; + + public GetSysNoticeBo() { + + } + + public GetSysNoticeBo(SysNotice dto) { + + super(dto); + } + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QueryMySysNoticeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QueryMySysNoticeBo.java new file mode 100644 index 0000000..db7c6b5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QueryMySysNoticeBo.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.bo.system.notice; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 我的系统通知 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryMySysNoticeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + + /** + * 发布时间 + */ + @Schema(description = "发布时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime publishTime; + + public QueryMySysNoticeBo() { + + } + + public QueryMySysNoticeBo(QuerySysNoticeByUserDto dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QuerySysNoticeBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QuerySysNoticeBo.java new file mode 100644 index 0000000..f46c07d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notice/QuerySysNoticeBo.java @@ -0,0 +1,90 @@ +package com.lframework.starter.web.inner.bo.system.notice; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysNotice; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统通知 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysNoticeBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 是否发布 + */ + @Schema(description = "是否发布") + private Boolean published; + + /** + * 发布时间 + */ + @Schema(description = "发布时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime publishTime; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 已读人数 + */ + @Schema(description = "已读人数") + private Integer readedNum; + + /** + * 未读人数 + */ + @Schema(description = "未读人数") + private Integer unReadNum; + + public QuerySysNoticeBo() { + + } + + public QuerySysNoticeBo(SysNotice dto) { + + super(dto); + } + + @Override + protected void afterInit(SysNotice dto) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/GetSysNotifyGroupBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/GetSysNotifyGroupBo.java new file mode 100644 index 0000000..03eca27 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/GetSysNotifyGroupBo.java @@ -0,0 +1,89 @@ +package com.lframework.starter.web.inner.bo.system.notify; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.service.system.SysNotifyGroupReceiverService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 消息通知组 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysNotifyGroupBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 接收者类型 + */ + @Schema(description = "接收者类型") + private Integer receiverType; + + /** + * 接收者ID + */ + @Schema(description = "接收者ID") + private List receiverIds; + + /** + * 消息类型 + */ + @Schema(description = "消息类型") + private List messageType; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysNotifyGroupBo() { + + } + + public GetSysNotifyGroupBo(SysNotifyGroup dto) { + + super(dto); + } + + @Override + public BaseBo convert(SysNotifyGroup dto) { + return super.convert(dto, GetSysNotifyGroupBo::getReceiverType, + GetSysNotifyGroupBo::getMessageType); + } + + @Override + protected void afterInit(SysNotifyGroup dto) { + + this.receiverType = dto.getReceiverType().getCode(); + + SysNotifyGroupReceiverService sysNotifyGroupReceiverService = ApplicationUtil.getBean( + SysNotifyGroupReceiverService.class); + this.receiverIds = sysNotifyGroupReceiverService.getReceiverIdsByGroupId(dto.getId()); + + this.messageType = Arrays.stream(dto.getMessageType().split(StringPool.STR_SPLIT)) + .map(Integer::valueOf).collect( + Collectors.toList()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/QuerySysNotifyGroupBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/QuerySysNotifyGroupBo.java new file mode 100644 index 0000000..f7a251a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/QuerySysNotifyGroupBo.java @@ -0,0 +1,93 @@ +package com.lframework.starter.web.inner.bo.system.notify; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.enums.system.SysNotifyMessageType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + *

+ * 消息通知组 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysNotifyGroupBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 接收者类型 + */ + @Schema(description = "接收者类型") + private String receiverType; + + /** + * 消息类型 + */ + @Schema(description = "消息类型") + private String messageType; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySysNotifyGroupBo() { + + } + + public QuerySysNotifyGroupBo(SysNotifyGroup dto) { + + super(dto); + } + + @Override + public BaseBo convert(SysNotifyGroup dto) { + return super.convert(dto, QuerySysNotifyGroupBo::getReceiverType, + QuerySysNotifyGroupBo::getMessageType); + } + + @Override + protected void afterInit(SysNotifyGroup dto) { + + this.receiverType = dto.getReceiverType().getDesc(); + this.messageType = Arrays.stream(dto.getMessageType().split(StringPool.STR_SPLIT)) + .map(Integer::valueOf).map( + t -> EnumUtil.getDesc(SysNotifyMessageType.class, t)) + .collect(Collectors.joining(StringPool.STR_SPLIT_CN)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/SysNotifyGroupSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/SysNotifyGroupSelectorBo.java new file mode 100644 index 0000000..b3ed8d8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/notify/SysNotifyGroupSelectorBo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.bo.system.notify; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysNotifyGroupSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysNotifyGroupSelectorBo() { + + } + + public SysNotifyGroupSelectorBo(SysNotifyGroup dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/GetSysOpenDomainBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/GetSysOpenDomainBo.java new file mode 100644 index 0000000..b76e823 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/GetSysOpenDomainBo.java @@ -0,0 +1,57 @@ +package com.lframework.starter.web.inner.bo.system.open; + +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysOpenDomainBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * API密钥 + */ + @Schema(description = "API密钥") + @EncryptConvert + private String apiSecret; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysOpenDomainBo() { + + } + + public GetSysOpenDomainBo(SysOpenDomain dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/QuerySysOpenDomainBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/QuerySysOpenDomainBo.java new file mode 100644 index 0000000..f177edd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/QuerySysOpenDomainBo.java @@ -0,0 +1,57 @@ +package com.lframework.starter.web.inner.bo.system.open; + +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysOpenDomainBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * API密钥 + */ + @Schema(description = "API密钥") + @EncryptConvert + private String apiSecret; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public QuerySysOpenDomainBo() { + + } + + public QuerySysOpenDomainBo(SysOpenDomain dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/SysOpenDomainSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/SysOpenDomainSelectorBo.java new file mode 100644 index 0000000..f747372 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/open/SysOpenDomainSelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.bo.system.open; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysOpenDomainSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + public SysOpenDomainSelectorBo() { + } + + public SysOpenDomainSelectorBo(SysOpenDomain dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/GetOpLogBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/GetOpLogBo.java new file mode 100644 index 0000000..7b844c0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/GetOpLogBo.java @@ -0,0 +1,66 @@ +package com.lframework.starter.web.inner.bo.system.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.OpLogs; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class GetOpLogBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 日志名称 + */ + @Schema(description = "日志名称") + private String name; + + /** + * 类别 + */ + @Schema(description = "类别") + private Integer logType; + + /** + * IP地址 + */ + @Schema(description = "IP地址") + private String ip; + + /** + * 补充信息 + */ + @Schema(description = "补充信息") + private String extra; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public GetOpLogBo() { + + } + + public GetOpLogBo(OpLogs dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/QueryOpLogBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/QueryOpLogBo.java new file mode 100644 index 0000000..4edb9b4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/oplog/QueryOpLogBo.java @@ -0,0 +1,60 @@ +package com.lframework.starter.web.inner.bo.system.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.OpLogs; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QueryOpLogBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 日志名称 + */ + @Schema(description = "日志名称") + private String name; + + /** + * 类别 + */ + @Schema(description = "类别") + private Integer logType; + + /** + * IP地址 + */ + @Schema(description = "IP地址") + private String ip; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryOpLogBo() { + + } + + public QueryOpLogBo(OpLogs dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/GetSysParameterBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/GetSysParameterBo.java new file mode 100644 index 0000000..224bba7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/GetSysParameterBo.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.inner.bo.system.parameter; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysParameter; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 系统参数 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysParameterBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @Schema(description = "ID") + private Long id; + + /** + * 键 + */ + @Schema(description = "键") + private String pmKey; + + /** + * 值 + */ + @Schema(description = "值") + private String pmValue; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysParameterBo() { + + } + + public GetSysParameterBo(SysParameter dto) { + + super(dto); + } + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/QuerySysParameterBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/QuerySysParameterBo.java new file mode 100644 index 0000000..550f9ef --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/parameter/QuerySysParameterBo.java @@ -0,0 +1,74 @@ +package com.lframework.starter.web.inner.bo.system.parameter; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysParameter; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统参数 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysParameterBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @Schema(description = "ID") + private Long id; + + /** + * 键 + */ + @Schema(description = "键") + private String pmKey; + + /** + * 值 + */ + @Schema(description = "值") + private String pmValue; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySysParameterBo() { + + } + + public QuerySysParameterBo(SysParameter dto) { + + super(dto); + } + + @Override + protected void afterInit(SysParameter dto) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java new file mode 100644 index 0000000..cd6b58a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java @@ -0,0 +1,95 @@ +package com.lframework.starter.web.inner.bo.system.permission; + +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.VoidDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class QuerySysDataPermissionModelDetailBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 明细ID + */ + @Schema(description = "明细ID") + private Integer detailId; + + /** + * 节点类型 + */ + @Schema(description = "节点类型") + private Integer nodeType; + + /** + * 计算类型 + */ + @Schema(description = "计算类型") + private Integer calcType; + + /** + * 值 + */ + @Schema(description = "值") + private String value; + + /** + * 值 + */ + @Schema(description = "值") + private List values; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 模型ID + */ + @Schema(description = "模型ID") + private Integer modelId; + + /** + * 条件 + */ + @Schema(description = "条件") + private Integer[] conditionTypes; + + /** + * 输入类型 + */ + @Schema(description = "输入类型") + @EnumConvert + private Integer inputType; + + /** + * 条件类型 + */ + @Schema(description = "条件类型") + private Integer conditionType; + + /** + * 前段枚举名 + */ + @Schema(description = "前端枚举名") + private String enumName; + + /** + * 子节点 + */ + @Schema(description = "子节点") + private List children; + + public QuerySysDataPermissionModelDetailBo() { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/SysDataPermissionModelDetailBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/SysDataPermissionModelDetailBo.java new file mode 100644 index 0000000..78a8893 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/permission/SysDataPermissionModelDetailBo.java @@ -0,0 +1,61 @@ +package com.lframework.starter.web.inner.bo.system.permission; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.annotations.convert.EnumConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysDataPermissionModelDetail; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataPermissionModelDetailBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 模型ID + */ + @Schema(description = "模型ID") + private Integer modelId; + + /** + * 条件 + */ + @Schema(description = "条件") + private String[] conditionTypes; + + /** + * 输入类型 + */ + @Schema(description = "输入类型") + @EnumConvert + private Integer inputType; + + /** + * 前段枚举名 + */ + @Schema(description = "前端枚举名") + private String enumName; + + public SysDataPermissionModelDetailBo() { + } + + public SysDataPermissionModelDetailBo(SysDataPermissionModelDetail dto) { + super(dto); + } + + @Override + protected void afterInit(SysDataPermissionModelDetail dto) { + this.conditionTypes = dto.getConditionType().split(StringPool.STR_SPLIT); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/GetSysRoleBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/GetSysRoleBo.java new file mode 100644 index 0000000..c48730f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/GetSysRoleBo.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.bo.system.role; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRole; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysRoleBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysRoleBo() { + + } + + public GetSysRoleBo(SysRole dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QueryRoleMenuBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QueryRoleMenuBo.java new file mode 100644 index 0000000..ad100ed --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QueryRoleMenuBo.java @@ -0,0 +1,85 @@ +package com.lframework.starter.web.inner.bo.system.role; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysMenu; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryRoleMenuBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 类型 + */ + @Schema(description = "类型") + private Integer display; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + /** + * 是否选择 + */ + @Schema(description = "是否选择") + private Boolean selected = Boolean.FALSE; + + public QueryRoleMenuBo() { + + } + + public QueryRoleMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public
BaseBo convert(SysMenu dto) { + + return super.convert(dto, QueryRoleMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QuerySysRoleBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QuerySysRoleBo.java new file mode 100644 index 0000000..7205385 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/QuerySysRoleBo.java @@ -0,0 +1,83 @@ +package com.lframework.starter.web.inner.bo.system.role; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRole; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class QuerySysRoleBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @Schema(description = "修改人") + private String updateBy; + + /** + * 修改时间 + */ + @Schema(description = "修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySysRoleBo() { + + } + + public QuerySysRoleBo(SysRole dto) { + + super(dto); + } + + @Override + protected void afterInit(SysRole dto) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/SysRoleSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/SysRoleSelectorBo.java new file mode 100644 index 0000000..64be5d7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/SysRoleSelectorBo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.bo.system.role; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRole; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysRoleSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysRoleSelectorBo() { + + } + + public SysRoleSelectorBo(SysRole dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/GetSysRoleCategoryBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/GetSysRoleCategoryBo.java new file mode 100644 index 0000000..5620bb5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/GetSysRoleCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.bo.system.role.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetSysRoleCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + + public GetSysRoleCategoryBo() { + + } + + public GetSysRoleCategoryBo(SysRoleCategory dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/QuerySysRoleCategoryBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/QuerySysRoleCategoryBo.java new file mode 100644 index 0000000..1c67e14 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/QuerySysRoleCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.bo.system.role.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QuerySysRoleCategoryBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + + public QuerySysRoleCategoryBo() { + + } + + public QuerySysRoleCategoryBo(SysRoleCategory dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/SysRoleCategorySelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/SysRoleCategorySelectorBo.java new file mode 100644 index 0000000..1d3ca7f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/role/category/SysRoleCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.bo.system.role.category; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysRoleCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysRoleCategorySelectorBo() { + } + + public SysRoleCategorySelectorBo(SysRoleCategory dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/GetTenantBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/GetTenantBo.java new file mode 100644 index 0000000..21cf8ff --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/GetTenantBo.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.bo.system.tenant; + +import com.lframework.starter.web.core.annotations.constants.EncryType; +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.Tenant; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetTenantBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 绑定域名 + */ + @Schema(description = "绑定域名") + private String serverName; + + /** + * JdbcUrl + */ + @Schema(description = "JdbcUrl") + @EncryptConvert + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @Schema(description = "Jdbc用户名") + @EncryptConvert + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @Schema(description = "Jdbc密码") + @EncryptConvert(type = EncryType.PASSWORD) + private String jdbcPassword; + + /** + * 是否为平台管理租户 + */ + @Schema(description = "是否为平台管理租户") + private Boolean isPlatform; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + public GetTenantBo(Tenant dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/QueryTenantBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/QueryTenantBo.java new file mode 100644 index 0000000..26cfae6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/QueryTenantBo.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.bo.system.tenant; + +import com.lframework.starter.web.core.annotations.constants.EncryType; +import com.lframework.starter.web.core.annotations.convert.EncryptConvert; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.Tenant; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryTenantBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 绑定域名 + */ + @Schema(description = "绑定域名") + private String serverName; + + /** + * JdbcUrl + */ + @Schema(description = "JdbcUrl") + @EncryptConvert + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @Schema(description = "Jdbc用户名") + @EncryptConvert + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @Schema(description = "Jdbc密码") + @EncryptConvert(type = EncryType.PASSWORD) + private String jdbcPassword; + + /** + * 是否为平台管理租户 + */ + @Schema(description = "是否为平台管理租户") + private Boolean isPlatform; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + public QueryTenantBo(Tenant dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/TenantSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/TenantSelectorBo.java new file mode 100644 index 0000000..cf935fa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/tenant/TenantSelectorBo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.bo.system.tenant; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.Tenant; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class TenantSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + public TenantSelectorBo() { + + } + + public TenantSelectorBo(Tenant dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/GetSysUserBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/GetSysUserBo.java new file mode 100644 index 0000000..ee47f06 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/GetSysUserBo.java @@ -0,0 +1,139 @@ +package com.lframework.starter.web.inner.bo.system.user; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.*; +import com.lframework.starter.web.inner.service.system.SysDeptService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Data +public class GetSysUserBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 用户名 + */ + @Schema(description = "用户名") + private String username; + + /** + * 邮箱 + */ + @Schema(description = "邮箱") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话") + private String telephone; + + /** + * 性别 + */ + @Schema(description = "性别") + private Integer gender; + + /** + * 部门 + */ + @Schema(description = "部门") + private List depts; + + /** + * 部门名称 + */ + @Schema(description = "部门名称") + private String deptName; + + + /** + * 角色 + */ + @Schema(description = "角色") + private List roles; + + /** + * 角色名称 + */ + @Schema(description = "角色名称") + private String roleName; + + /** + * 是否锁定 + */ + @Schema(description = "是否锁定") + private Boolean lockStatus; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysUserBo() { + + } + + public GetSysUserBo(SysUser dto) { + + super(dto); + } + + @Override + protected void afterInit(SysUser dto) { + SysUserDeptService sysUserDeptService = ApplicationUtil.getBean(SysUserDeptService.class); + List userDepts = sysUserDeptService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userDepts)) { + SysDeptService sysDeptService = ApplicationUtil.getBean(SysDeptService.class); + this.depts = userDepts.stream().map(SysUserDept::getDeptId) + .collect(Collectors.toList()); + + this.deptName = StringUtil.join(StringPool.STR_SPLIT_CN, + userDepts.stream().map(t -> sysDeptService.findById(t.getDeptId())) + .filter(Objects::nonNull).map(SysDept::getName) + .collect(Collectors.toList())); + } + + SysUserRoleService sysUserRoleService = ApplicationUtil.getBean(SysUserRoleService.class); + List userRoles = sysUserRoleService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userRoles)) { + SysRoleService sysRoleService = ApplicationUtil.getBean(SysRoleService.class); + this.roles = userRoles.stream().map(SysUserRole::getRoleId) + .collect(Collectors.toList()); + + this.roleName = StringUtil.join(StringPool.STR_SPLIT_CN, + userRoles.stream().map(t -> sysRoleService.findById(t.getRoleId())) + .filter(Objects::nonNull).map(SysRole::getName) + .collect(Collectors.toList())); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QuerySysUserBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QuerySysUserBo.java new file mode 100644 index 0000000..1af2303 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QuerySysUserBo.java @@ -0,0 +1,153 @@ +package com.lframework.starter.web.inner.bo.system.user; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.*; +import com.lframework.starter.web.inner.service.system.SysDeptService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Data +public class QuerySysUserBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 部门名称 + */ + @Schema(description = "部门名称") + private String deptName; + + /** + * 角色名称 + */ + @Schema(description = "角色名称") + private String roleName; + + /** + * 用户名 + */ + @Schema(description = "用户名") + private String username; + + /** + * 邮箱 + */ + @Schema(description = "邮箱") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话") + private String telephone; + + /** + * 性别 + */ + @Schema(description = "性别") + private Integer gender; + + /** + * 是否锁定 + */ + @Schema(description = "是否锁定") + private Boolean lockStatus; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @Schema(description = "修改人") + private String updateBy; + + /** + * 修改时间 + */ + @Schema(description = "修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySysUserBo() { + + } + + public QuerySysUserBo(SysUser dto) { + + super(dto); + } + + @Override + protected void afterInit(SysUser dto) { + SysUserDeptService sysUserDeptService = ApplicationUtil.getBean(SysUserDeptService.class); + List userDepts = sysUserDeptService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userDepts)) { + SysDeptService sysDeptService = ApplicationUtil.getBean(SysDeptService.class); + List deptNames = new ArrayList<>(userDepts.size()); + for (SysUserDept userDept : userDepts) { + SysDept dept = sysDeptService.findById(userDept.getDeptId()); + deptNames.add(dept.getName()); + } + + this.deptName = StringUtil.join(StringPool.STR_SPLIT_CN, deptNames); + } + + SysUserRoleService sysUserRoleService = ApplicationUtil.getBean(SysUserRoleService.class); + List userRoles = sysUserRoleService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userRoles)) { + SysRoleService sysRoleService = ApplicationUtil.getBean(SysRoleService.class); + List roleNames = new ArrayList<>(userRoles.size()); + for (SysUserRole userRole : userRoles) { + SysRole role = sysRoleService.findById(userRole.getRoleId()); + roleNames.add(role.getName()); + } + + this.roleName = StringUtil.join(StringPool.STR_SPLIT_CN, roleNames); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QueryUserRoleBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QueryUserRoleBo.java new file mode 100644 index 0000000..96f36f3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/QueryUserRoleBo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.web.inner.bo.system.user; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysRole; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class QueryUserRoleBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 是否选中 + */ + @Schema(description = "是否选中") + private Boolean selected = Boolean.FALSE; + + public QueryUserRoleBo() { + + } + + public QueryUserRoleBo(SysRole dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/SysUserSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/SysUserSelectorBo.java new file mode 100644 index 0000000..e8bcd08 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/SysUserSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.bo.system.user; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysUser; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysUserSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + + public SysUserSelectorBo() { + + } + + public SysUserSelectorBo(SysUser dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/GetSysUserGroupBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/GetSysUserGroupBo.java new file mode 100644 index 0000000..cf81d48 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/GetSysUserGroupBo.java @@ -0,0 +1,68 @@ +package com.lframework.starter.web.inner.bo.system.user.group; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import com.lframework.starter.web.inner.service.system.SysUserGroupDetailService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 用户组 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysUserGroupBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 用户ID + */ + @Schema(description = "用户ID") + private List userIds; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + public GetSysUserGroupBo() { + + } + + public GetSysUserGroupBo(SysUserGroup dto) { + + super(dto); + } + + @Override + protected void afterInit(SysUserGroup dto) { + + SysUserGroupDetailService sysUserGroupDetailService = ApplicationUtil.getBean( + SysUserGroupDetailService.class); + this.userIds = sysUserGroupDetailService.getUserIdsByGroupId(dto.getId()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/QuerySysUserGroupBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/QuerySysUserGroupBo.java new file mode 100644 index 0000000..2395358 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/QuerySysUserGroupBo.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.bo.system.user.group; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 用户组 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysUserGroupBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySysUserGroupBo() { + + } + + public QuerySysUserGroupBo(SysUserGroup dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/SysUserGroupSelectorBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/SysUserGroupSelectorBo.java new file mode 100644 index 0000000..838c6e4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/system/user/group/SysUserGroupSelectorBo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.bo.system.user.group; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysUserGroupSelectorBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + public SysUserGroupSelectorBo() { + + } + + public SysUserGroupSelectorBo(SysUserGroup dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/bo/usercenter/UserInfoBo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/usercenter/UserInfoBo.java new file mode 100644 index 0000000..bdafd95 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/bo/usercenter/UserInfoBo.java @@ -0,0 +1,61 @@ +package com.lframework.starter.web.inner.bo.usercenter; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.inner.dto.system.UserInfoDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UserInfoBo extends BaseBo { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 登录名 + */ + @Schema(description = "登录名") + private String username; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 邮箱 + */ + @Schema(description = "邮箱") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话") + private String telephone; + + /** + * 性别 + */ + @Schema(description = "性别") + private Integer gender; + + public UserInfoBo() { + + } + + public UserInfoBo(UserInfoDto dto) { + + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/AuthOpLogType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/AuthOpLogType.java new file mode 100644 index 0000000..612064b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/AuthOpLogType.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.inner.components.oplog; + + +import com.lframework.starter.web.core.components.oplog.OpLogType; + +public class AuthOpLogType implements OpLogType { + + @Override + public Integer getCode() { + return 1; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/OtherOpLogType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/OtherOpLogType.java new file mode 100644 index 0000000..9a9412a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/OtherOpLogType.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.inner.components.oplog; + + +import com.lframework.starter.web.core.components.oplog.OpLogType; + +public class OtherOpLogType implements OpLogType { + + @Override + public Integer getCode() { + return 99; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/SystemOpLogType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/SystemOpLogType.java new file mode 100644 index 0000000..3b9ff10 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/oplog/SystemOpLogType.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.inner.components.oplog; + + +import com.lframework.starter.web.core.components.oplog.OpLogType; + +public class SystemOpLogType implements OpLogType { + + @Override + public Integer getCode() { + return 2; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/OrderDataPermissionDataPermissionType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/OrderDataPermissionDataPermissionType.java new file mode 100644 index 0000000..173363a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/OrderDataPermissionDataPermissionType.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.inner.components.permission; + +import com.lframework.starter.web.core.components.permission.SysDataPermissionDataPermissionType; + +/** + * 单据数据权限 + */ +public final class OrderDataPermissionDataPermissionType implements SysDataPermissionDataPermissionType { + + @Override + public Integer getCode() { + return 2; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/ProductDataPermissionDataPermissionType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/ProductDataPermissionDataPermissionType.java new file mode 100644 index 0000000..9b57abe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/permission/ProductDataPermissionDataPermissionType.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.inner.components.permission; + +import com.lframework.starter.web.core.components.permission.SysDataPermissionDataPermissionType; + +/** + * 商品数据权限 + */ +public final class ProductDataPermissionDataPermissionType implements + SysDataPermissionDataPermissionType { + + @Override + public Integer getCode() { + return 1; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApprovePassOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApprovePassOrderTimeLineBizType.java new file mode 100644 index 0000000..08bbfa8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApprovePassOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class ApprovePassOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 4; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApproveReturnOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApproveReturnOrderTimeLineBizType.java new file mode 100644 index 0000000..3e51179 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/ApproveReturnOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class ApproveReturnOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 5; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CancelApproveOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CancelApproveOrderTimeLineBizType.java new file mode 100644 index 0000000..e1b6d91 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CancelApproveOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class CancelApproveOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 6; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CreateOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CreateOrderTimeLineBizType.java new file mode 100644 index 0000000..17d7693 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/CreateOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class CreateOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 1; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/NormalOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/NormalOrderTimeLineBizType.java new file mode 100644 index 0000000..1d14bac --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/NormalOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class NormalOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 0; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/SendOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/SendOrderTimeLineBizType.java new file mode 100644 index 0000000..9a3a3a4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/SendOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class SendOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 3; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/UpdateOrderTimeLineBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/UpdateOrderTimeLineBizType.java new file mode 100644 index 0000000..5feb42d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/components/timeline/UpdateOrderTimeLineBizType.java @@ -0,0 +1,11 @@ +package com.lframework.starter.web.inner.components.timeline; + +import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType; + +public class UpdateOrderTimeLineBizType implements OrderTimeLineBizType { + + @Override + public Integer getCode() { + return 2; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/AuthController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/AuthController.java new file mode 100644 index 0000000..165c3d4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/AuthController.java @@ -0,0 +1,627 @@ +package com.lframework.starter.web.inner.controller; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.codec.Base64; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.code.kaptcha.Producer; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.UserLoginException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.config.properties.KaptchaProperties; +import com.lframework.starter.web.core.annotations.openapi.OpenApi; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.captcha.CaptchaValidator; +import com.lframework.starter.web.core.components.permission.SysDataPermissionDataPermissionType; +import com.lframework.starter.web.core.components.redis.RedisHandler; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.security.*; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.dto.GenerateCaptchaDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.bo.auth.CollectMenuBo; +import com.lframework.starter.web.inner.bo.auth.LoginBo; +import com.lframework.starter.web.inner.bo.auth.MenuBo; +import com.lframework.starter.web.inner.bo.auth.MenuBo.MetaBo; +import com.lframework.starter.web.inner.bo.auth.TenantRequireBo; +import com.lframework.starter.web.inner.components.oplog.AuthOpLogType; +import com.lframework.starter.web.inner.dto.system.LoginDto; +import com.lframework.starter.web.inner.dto.system.MenuDto; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; +import com.lframework.starter.web.inner.entity.SysUserDept; +import com.lframework.starter.web.inner.entity.SysUserRole; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionDataBizType; +import com.lframework.starter.web.inner.enums.system.SysMenuComponentType; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.inner.service.SysConfService; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.TenantService; +import com.lframework.starter.web.inner.service.system.*; +import com.lframework.starter.web.inner.vo.system.permission.SysDataPermissionModelDetailVo; +import com.lframework.starter.web.inner.vo.system.user.GetLoginCaptchaRequireVo; +import com.lframework.starter.web.inner.vo.system.user.LoginVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.FastByteArrayOutputStream; +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.RestController; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.time.LocalDate; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 默认用户认证Controller + * + * @author zmj + */ +@Tag(name = "用户认证") +@Slf4j +@Validated +@RestController +public class AuthController extends DefaultBaseController { + + @Autowired + private Producer producer; + + @Autowired + private KaptchaProperties kaptchaProperties; + + @Autowired + private RedisHandler redisHandler; + + @Autowired + private CaptchaValidator captchaValidator; + + @Autowired + private PasswordEncoderWrapper passwordEncoderWrapper; + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private UserTokenResolver userTokenResolver; + + @Autowired + private TenantService tenantService; + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @Autowired + private SysDataPermissionModelDetailService sysDataPermissionModelDetailService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + @Autowired + private SysConfService sysConfService; + + /** + * 是否为多租户 + */ + @Operation(summary = "是否为多租户") + @OpenApi + @GetMapping("/auth/tenant/require") + public InvokeResult getTenantRequire() { + TenantRequireBo result = new TenantRequireBo(); + result.setEnable(TenantUtil.enableTenant()); + result.setTenantId(TenantContextHolder.getTenantId()); + + return InvokeResultBuilder.success(result); + } + + /** + * 是否需要登录验证码 + */ + @Operation(summary = "是否需要登录验证码") + @OpenApi + @PostMapping("/auth/captcha/require") + public InvokeResult getLoginCaptchaRequire(@Valid GetLoginCaptchaRequireVo vo) { + String username = vo.getUsername(); + String tenantId = null; + if (TenantUtil.enableTenant()) { + Tenant tenant = null; + if (vo.getTenantId() != null) { + tenant = tenantService.getById(vo.getTenantId()); + } else { + // 检查租户是否存在 + Wrapper queryTenantWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getName, vo.getTenantName()); + tenant = tenantService.getOne(queryTenantWrapper); + } + + if (tenant == null) { + throw new DefaultClientException("用户名或密码错误!"); + } + + if (!tenant.getAvailable()) { + throw new DefaultClientException("用户已停用,无法登录!"); + } + + tenantId = tenant.getId().toString(); + + TenantContextHolder.setTenantId(tenant.getId()); + } + + String loginCaptchaEnabled = sysConfService.findByKey("login-captcha.enabled", "true"); + return InvokeResultBuilder.success(Boolean.valueOf(loginCaptchaEnabled)); + } + + /** + * 获取登录验证码 + */ + @Operation(summary = "获取登录验证码") + @OpenApi + @GetMapping("/auth/captcha") + public InvokeResult generateCaptcha() { + + String code = producer.createText(); + BufferedImage image = producer.createImage(code); + + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try { + ImageIO.write(image, "jpg", os); + } catch (IOException e) { + throw new DefaultClientException("验证码生成失败,请稍后重试!"); + } + + String sn = IdUtil.getUUID(); + //将验证码存至redis + redisHandler.set(StringUtil.format(StringPool.LOGIN_CAPTCHA_KEY, sn), code, + kaptchaProperties.getExpireTime() * 60 * 1000L); + + GenerateCaptchaDto resp = new GenerateCaptchaDto(); + resp.setSn(sn); + resp.setImage("data:image/jpeg;base64," + Base64.encode(os.toByteArray())); + + log.debug("获取验证码成功, SN={}, code={}", sn, code); + + return InvokeResultBuilder.success(resp); + } + + @Operation(summary = "登录") + @OpenApi + @OpLog(type = AuthOpLogType.class, name = "用户登录") + @PostMapping("/auth/login") + public InvokeResult login(@Valid LoginVo vo) { + + String username = vo.getUsername(); + String password = vo.getPassword(); + Tenant tenant = null; + String tenantId = null; + if (TenantUtil.enableTenant()) { + if (vo.getTenantId() != null) { + tenant = tenantService.getById(vo.getTenantId()); + } else { + if (StringUtil.isBlank(vo.getTenantName())) { + throw new DefaultClientException("用户名或密码错误!"); + } + // 检查租户是否存在 + Wrapper queryTenantWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getName, vo.getTenantName()); + tenant = tenantService.getOne(queryTenantWrapper); + } + + username = vo.getUsername(); + + if (tenant == null) { + throw new DefaultClientException("用户名或密码错误!"); + } + + if (!tenant.getAvailable()) { + throw new DefaultClientException("用户已停用,无法登录!"); + } + + tenantId = tenant.getId().toString(); + + TenantContextHolder.setTenantId(tenant.getId()); + } + + log.info("用户 {} {} 开始登录", tenantId, username); + + String loginCaptchaEnabled = sysConfService.findByKey("login-captcha.enabled", "true"); + log.info("当前用户登录需要验证码 = {}", loginCaptchaEnabled); + if (Boolean.valueOf(loginCaptchaEnabled)) { + String sn = vo.getSn(); + String captcha = vo.getCaptcha(); + captchaValidator.validate(sn, captcha); + } + + this.checkUserLogin(tenantId == null ? null : Integer.valueOf(tenantId), username, password); + + AbstractUserDetails user = userDetailsService.loadUserByUsername(username); + + if (TenantUtil.enableTenant()) { + user.setIsPlatform(tenant.getIsPlatform()); + } else { + user.setIsPlatform(true); + } + + LoginDto dto = this.doLogin(user); + + this.addAttributesToSession(user); + + return InvokeResultBuilder.success(new LoginBo(dto)); + } + + @Operation(summary = "退出登录") + @OpenApi + @OpLog(type = AuthOpLogType.class, name = "退出登录") + @PostMapping("/auth/logout") + public InvokeResult logout() { + + StpUtil.logout(); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "获取用户信息") + @GetMapping("/auth/info") + public InvokeResult info() { + + AbstractUserDetails user = getCurrentUser(); + LoginDto info = new LoginDto(null, user.getName(), user.getPermissions()); + + return InvokeResultBuilder.success(new LoginBo(info)); + } + + @Operation(summary = "获取用户菜单") + @GetMapping("/auth/menus") + public InvokeResult> menus() { + + AbstractUserDetails user = getCurrentUser(); + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + List menus = sysMenuService.getMenuByUserId(user.getId(), user.isAdmin(), moduleIds); + + // 组装成树形菜单 + List topMenus = menus.stream().filter(t -> StringUtil.isBlank(t.getParentId())) + .collect(Collectors.toList()); + + List results = new ArrayList<>(); + for (MenuDto topMenu : topMenus) { + MenuBo menuBo = new MenuBo(); + menuBo.setName(topMenu.getName()); + menuBo.setComponent("LAYOUT"); + menuBo.setChildren(parseChildrenMenu(topMenu, menus)); + menuBo.setPath(topMenu.getPath()); + + MetaBo meta = new MetaBo(); + meta.setId(topMenu.getId()); + meta.setTitle(topMenu.getMeta().getTitle()); + meta.setIcon(topMenu.getMeta().getIcon()); + meta.setHideMenu(topMenu.getHidden()); + meta.setIgnoreKeepAlive(topMenu.getMeta().getNoCache()); + meta.setIsCollect(topMenu.getIsCollect()); + + menuBo.setMeta(meta); + + results.add(menuBo); + } + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "验证当前登录人的登录密码") + @PostMapping("/auth/check/password") + public InvokeResult checkPassword( + @NotBlank(message = "登录密码不能为空!") String password) { + return InvokeResultBuilder.success(passwordEncoderWrapper.getEncoder() + .matches(password, SecurityUtil.getCurrentUser().getPassword())); + } + + private List parseChildrenMenu(MenuDto topMenu, List menus) { + List children = menus.stream() + .filter(t -> StringUtil.equals(t.getParentId(), topMenu.getId())).map(t -> { + MenuBo menuBo = new MenuBo(); + menuBo.setName(t.getName()); + menuBo.setChildren(parseChildrenMenu(t, menus)); + + menuBo.setComponent(t.getComponent()); + menuBo.setPath( + StringUtil.startWith(t.getPath(), "/") ? t.getPath().substring(1) : t.getPath()); + MetaBo meta = new MetaBo(); + meta.setId(t.getId()); + meta.setTitle(t.getMeta().getTitle()); + meta.setIcon(t.getMeta().getIcon()); + meta.setHideMenu(t.getHidden()); + meta.setIgnoreKeepAlive(t.getMeta().getNoCache()); + meta.setIsCollect(t.getIsCollect()); + if (RegUtil.isMatch(PatternPool.PATTERN_HTTP_URL, menuBo.getPath())) { + meta.setIsLink(Boolean.TRUE); + } + + // 如果是功能 + if (SysMenuDisplay.FUNCTION.getCode().equals(t.getDisplay())) { + // 普通 + if (SysMenuComponentType.NORMAL.getCode().equals(t.getComponentType())) { + if ("/iframes/index".equalsIgnoreCase(t.getComponent())) { + menuBo.setComponent(null); + meta.setFrameSrc(menuBo.getPath().substring(menuBo.getPath().indexOf("?src=") + 5)); + menuBo.setPath(menuBo.getPath().substring(0, menuBo.getPath().indexOf("?src="))); + } + } + } + + menuBo.setMeta(meta); + + return menuBo; + }).collect(Collectors.toList()); + + return children; + } + + @Operation(summary = "收藏菜单") + @Parameter(name = "menuId", description = "菜单ID") + @PostMapping("/menu/collect") + public InvokeResult collectMenu(String menuId) { + + AbstractUserDetails user = getCurrentUser(); + sysMenuService.collect(user.getId(), menuId); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "获取已收藏的菜单") + @GetMapping("/menu/collect") + public InvokeResult> getCollectMenus() { + AbstractUserDetails user = getCurrentUser(); + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + List menus = sysMenuService.getMenuByUserId(user.getId(), user.isAdmin(), moduleIds); + + List collectMenus = menus.stream().filter(t -> t.getIsCollect()) + .collect(Collectors.toList()); + List results = collectMenus.stream().map(t -> { + CollectMenuBo result = new CollectMenuBo(); + result.setId(t.getId()); + result.setTitle(t.getMeta().getTitle()); + result.setIcon(t.getMeta().getIcon()); + if (StringUtil.isBlank(result.getIcon())) { + // 如果没有图标 那么就往上级找 + String icon = null; + String parentId = t.getParentId(); + while (StringUtil.isNotEmpty(parentId)) { + MenuDto parentMenu = null; + for (MenuDto m : menus) { + if (m.getId().equals(parentId)) { + parentMenu = m; + } + } + + if (parentMenu == null) { + break; + } + + if (StringUtil.isNotBlank(parentMenu.getMeta().getIcon())) { + icon = parentMenu.getMeta().getIcon(); + break; + } + + parentId = parentMenu.getParentId(); + } + result.setIcon(icon); + } + + List pathList = new ArrayList<>(); + pathList.add(t.getPath()); + String parentId = t.getParentId(); + while (StringUtil.isNotEmpty(parentId)) { + MenuDto parentMenu = null; + for (MenuDto m : menus) { + if (m.getId().equals(parentId)) { + parentMenu = m; + } + } + + if (parentMenu == null) { + break; + } + + if (StringUtil.isNotBlank(parentMenu.getPath())) { + pathList.add(parentMenu.getPath()); + } + + parentId = parentMenu.getParentId(); + } + + pathList = CollectionUtil.reverse(pathList); + result.setPath(CollectionUtil.join(pathList, "")); + + return result; + }).collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "取消收藏菜单") + @Parameter(name = "menuId", description = "菜单ID") + @PostMapping("/menu/collect/cancel") + public InvokeResult cancelCollectMenu(String menuId) { + + AbstractUserDetails user = getCurrentUser(); + sysMenuService.cancelCollect(user.getId(), menuId); + + return InvokeResultBuilder.success(); + } + + private LoginDto doLogin(AbstractUserDetails user) { + + if (!user.isAccountNonExpired()) { + throw new UserLoginException("账户已过期,不允许登录!"); + } + + if (!user.isAccountNonLocked()) { + throw new UserLoginException("账户已过期,不允许登录!"); + } + + if (!user.isAccountNonLocked()) { + throw new UserLoginException("账户已锁定,不允许登录!"); + } + + if (!user.isEnabled()) { + throw new UserLoginException("账户已停用,不允许登录!"); + } + + if (user.isNoPermission()) { + throw new UserLoginException("账户未授权,不允许登录!"); + } + // 登录 + // loginId需要唯一 + String loginId = + (user.getTenantId() == null ? "" : user.getTenantId() + "@") + user.getUsername() + "@" + + IdUtil.getUUID(); + + StpUtil.login(loginId); + + user.setLoginId(loginId); + + StpUtil.getSession().set(SecurityConstants.USER_INFO_KEY, user); + + String token = userTokenResolver.getToken(); + + return new LoginDto(token, user.getName(), user.getPermissions()); + } + + private void checkUserLogin(Integer tenantId, String username, String password) { + AbstractUserDetails user = userDetailsService.loadUserByUsername(username); + String lockKey = + (tenantId == null ? "noTenant" : tenantId) + "_" + username + "_" + DateUtil.formatDate( + LocalDate.now()) + "_LOGIN_LOCK"; + if (!passwordEncoderWrapper.getEncoder().matches(password, user.getPassword())) { + long loginErrorNum = redisHandler.incr(lockKey, 1); + redisHandler.expire(lockKey, 86400000L); + int failNum = 5; + if (loginErrorNum < failNum) { + throw new UserLoginException( + "您已经登录失败" + loginErrorNum + "次,您还可以尝试" + (failNum - loginErrorNum) + + "次!"); + } else { + sysUserService.lockById(user.getId()); + + sysUserService.cleanCacheByKey(user.getId()); + + redisHandler.expire(lockKey, 1L); + // 锁定用户 + throw new UserLoginException("用户已锁定,无法登录!"); + } + } else { + redisHandler.expire(lockKey, 1L); + } + } + + protected void addAttributesToSession(AbstractUserDetails user) { + Map dataPermissionMap = new HashMap<>(); + Map beans = ApplicationUtil.getBeansOfType(SysDataPermissionDataPermissionType.class); + Collection permissionTypes = beans.values(); + for (SysDataPermissionDataPermissionType permissionType : permissionTypes) { + List sqlTemplates = new ArrayList<>(); + + List userRoles = sysUserRoleService.getByUserId(user.getId()); + if (CollectionUtil.isNotEmpty(userRoles)) { + for (SysUserRole userRole : userRoles) { + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + userRole.getRoleId(), + SysDataPermissionDataBizType.ROLE.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + } + } + + List userDepts = sysUserDeptService.getByUserId(user.getId()); + if (CollectionUtil.isNotEmpty(userDepts)) { + for (SysUserDept userDept : userDepts) { + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + userDept.getDeptId(), + SysDataPermissionDataBizType.DEPT.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + } + } + + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + user.getId(), + SysDataPermissionDataBizType.USER.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + + if (CollectionUtil.isNotEmpty(sqlTemplates)) { + dataPermissionMap.put(permissionType.getCode().toString(), + "(" + CollectionUtil.join(sqlTemplates, " AND ") + ")"); + } + } + + StpUtil.getSession().set(SecurityConstants.DATA_PERMISSION_SQL_MAP, dataPermissionMap); + + Map dataPermissionVar = new HashMap<>(); + List userDepts = sysUserDeptService.getByUserId(user.getId()); + List curDeptIds = userDepts.stream().map(SysUserDept::getDeptId) + .map(t -> "'" + t + "'").collect( + Collectors.toList()); + dataPermissionVar.put("curDeptIds", + CollectionUtil.isEmpty(curDeptIds) ? IdUtil.getId() : CollectionUtil.join(curDeptIds, ",")); + + StpUtil.getSession().set(SecurityConstants.DATA_PERMISSION_SQL_VAR, dataPermissionVar); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/QrtzController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/QrtzController.java new file mode 100644 index 0000000..b3dba70 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/QrtzController.java @@ -0,0 +1,165 @@ +package com.lframework.starter.web.inner.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.qrtz.GetQrtzBo; +import com.lframework.starter.web.inner.bo.qrtz.QueryQrtzBo; +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.inner.service.QrtzService; +import com.lframework.starter.web.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.UpdateQrtzVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@Tag(name = "定时器管理") +@RestController +@RequestMapping("/qrtz") +public class QrtzController extends DefaultBaseController { + + @Autowired + private QrtzService qrtzService; + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"development:qrtz:manage"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryQrtzVo vo) { + + PageResult pageResult = qrtzService.query(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryQrtzBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询 + * + * @return + */ + @Operation(summary = "查询") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + QrtzDto data = qrtzService.findById(name, group); + if (data == null) { + throw new DefaultClientException("任务不存在!"); + } + + return InvokeResultBuilder.success(new GetQrtzBo(data)); + } + + /** + * 创建 + * + * @param vo + * @return + */ + @Operation(summary = "创建") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateQrtzVo vo) { + qrtzService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + * + * @param vo + * @return + */ + @Operation(summary = "修改") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateQrtzVo vo) { + qrtzService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 暂停 + * + * @return + */ + @Operation(summary = "暂停") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @PutMapping("/pause") + public InvokeResult pause(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.pause(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 恢复 + * + * @return + */ + @Operation(summary = "恢复") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @PutMapping("/resume") + public InvokeResult resume(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.resume(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 触发 + * + * @return + */ + @Operation(summary = "触发") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @PutMapping("/trigger") + public InvokeResult trigger(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.trigger(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + * + * @return + */ + @Operation(summary = "删除") + @HasPermission(value = {"development:qrtz:manage"},requirePlatform = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.delete(name, group); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/UserCenterController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/UserCenterController.java new file mode 100644 index 0000000..1132796 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/UserCenterController.java @@ -0,0 +1,187 @@ +package com.lframework.starter.web.inner.controller; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.PasswordEncoderWrapper; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.oplog.OpLogInUserCenterBo; +import com.lframework.starter.web.inner.bo.usercenter.UserInfoBo; +import com.lframework.starter.web.inner.components.oplog.AuthOpLogType; +import com.lframework.starter.web.inner.dto.system.UserInfoDto; +import com.lframework.starter.web.inner.entity.OpLogs; +import com.lframework.starter.web.inner.service.OpLogsService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import com.lframework.starter.web.inner.vo.oplogs.QueryOpLogsVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户中心 + * + * @author zmj + */ +@Tag(name = "个人中心") +@Validated +@RestController +@RequestMapping("/center") +public class UserCenterController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private OpLogsService opLogsService; + + @Autowired + private PasswordEncoderWrapper encoderWrapper; + + /** + * 获取用户信息 + */ + @Operation(summary = "获取用户信息") + @GetMapping("/info") + public InvokeResult getInfo() { + + String userId = getCurrentUser().getId(); + UserInfoDto info = sysUserService.getInfo(userId); + + return InvokeResultBuilder.success(new UserInfoBo(info)); + } + + /** + * 修改密码 + */ + @Operation(summary = "修改密码") + @Parameters({ + @Parameter(name = "oldPsw", description = "旧密码"), + @Parameter(name = "newPsw", description = "新密码"), + @Parameter(name = "confirmPsw", description = "确认密码")}) + @OpLog(type = AuthOpLogType.class, name = "修改密码,原密码:{},新密码:{}", params = {"#oldPsw", "#newPsw"}) + @PatchMapping("/password") + public InvokeResult updatePassword(@NotBlank(message = "旧密码不能为空!") String oldPsw, + @NotBlank(message = "新密码不能为空!") String newPsw, + @NotBlank(message = "确认密码不能为空!") String confirmPsw) { + + AbstractUserDetails user = getCurrentUser(); + if (!encoderWrapper.getEncoder().matches(oldPsw, user.getPassword())) { + throw new InputErrorException("旧密码不正确,请重新输入!"); + } + + if (!StringUtil.equals(newPsw, confirmPsw)) { + throw new InputErrorException("两次密码输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.PATTERN_PASSWORD, newPsw)) { + throw new InputErrorException("密码格式不正确,请检查!"); + } + + sysUserService.updatePassword(user.getId(), newPsw); + + //修改密码后,退出登录状态 + SecurityUtil.logout(); + + return InvokeResultBuilder.success(); + } + + /** + * 修改邮箱 + */ + @Operation(summary = "修改邮箱") + @Parameters({ + @Parameter(name = "newEmail", description = "新邮箱地址"), + @Parameter(name = "confirmEmail", description = "确认邮箱地址")}) + @OpLog(type = AuthOpLogType.class, name = "修改邮箱,新邮箱:{}", params = "#newEmail") + @PatchMapping("/email") + public InvokeResult updateEmail(@NotBlank(message = "新邮箱地址不能为空!") String newEmail, + @NotBlank(message = "确认邮箱地址不能为空!") String confirmEmail) { + + AbstractUserDetails user = getCurrentUser(); + + if (!StringUtil.equals(newEmail, confirmEmail)) { + throw new InputErrorException("两次邮箱地址输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.EMAIL, newEmail)) { + throw new InputErrorException("邮箱地址格式不正确,请检查!"); + } + + sysUserService.updateEmail(user.getId(), newEmail); + + sysUserService.cleanCacheByKey(user.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 修改联系电话 + */ + @Operation(summary = "修改联系电话") + @Parameters({ + @Parameter(name = "newTelephone", description = "新联系电话"), + @Parameter(name = "confirmTelephone", description = "确认联系电话")}) + @OpLog(type = AuthOpLogType.class, name = "修改联系电话,新联系电话:{}", params = "#newTelephone") + @PatchMapping("/telephone") + public InvokeResult updateTelephone(@NotBlank(message = "新联系电话不能为空!") String newTelephone, + @NotBlank(message = "确认联系电话不能为空!") String confirmTelephone) { + + AbstractUserDetails user = getCurrentUser(); + + if (!StringUtil.equals(newTelephone, confirmTelephone)) { + throw new InputErrorException("两次联系电话输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.PATTERN_CN_TEL, newTelephone)) { + throw new InputErrorException("联系电话格式不正确,请检查!"); + } + + sysUserService.updateTelephone(user.getId(), newTelephone); + + sysUserService.cleanCacheByKey(user.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 查询操作日志 + */ + @Operation(summary = "查询操作日志") + @GetMapping("/oplog") + public InvokeResult> oplog(@Valid QueryOpLogsVo vo) { + + vo.setCreateBy(SecurityUtil.getCurrentUser().getId()); + + PageResult pageResult = opLogsService.query(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(OpLogInUserCenterBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/DefaultSysSelectorController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/DefaultSysSelectorController.java new file mode 100644 index 0000000..4c23db2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/DefaultSysSelectorController.java @@ -0,0 +1,487 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.bo.system.dept.SysDeptSelectorBo; +import com.lframework.starter.web.inner.bo.system.dic.SysDataDicSelectorBo; +import com.lframework.starter.web.inner.bo.system.dic.category.SysDataDicCategorySelectorBo; +import com.lframework.starter.web.inner.bo.system.menu.SysMenuSelectorBo; +import com.lframework.starter.web.inner.bo.system.notify.SysNotifyGroupSelectorBo; +import com.lframework.starter.web.inner.bo.system.open.SysOpenDomainSelectorBo; +import com.lframework.starter.web.inner.bo.system.role.SysRoleSelectorBo; +import com.lframework.starter.web.inner.bo.system.role.category.SysRoleCategorySelectorBo; +import com.lframework.starter.web.inner.bo.system.tenant.TenantSelectorBo; +import com.lframework.starter.web.inner.bo.system.user.SysUserSelectorBo; +import com.lframework.starter.web.inner.bo.system.user.group.SysUserGroupSelectorBo; +import com.lframework.starter.web.inner.entity.*; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.TenantService; +import com.lframework.starter.web.inner.service.system.*; +import com.lframework.starter.web.inner.vo.system.dept.SysDeptSelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.starter.web.inner.vo.system.notify.SysNotifyGroupSelectorVo; +import com.lframework.starter.web.inner.vo.system.open.SysOpenDomainSelectorVo; +import com.lframework.starter.web.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.starter.web.inner.vo.system.role.category.SysRoleCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.starter.web.inner.vo.system.user.SysUserSelectorVo; +import com.lframework.starter.web.inner.vo.system.user.group.SysUserGroupSelectorVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 数据选择器 + * + * @author zmj + */ +@Tag(name = "数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class DefaultSysSelectorController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysDeptService sysDeptService; + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private SysRoleCategoryService sysRoleCategoryService; + + @Autowired + private SysDataDicCategoryService sysDataDicCategoryService; + + @Autowired + private SysDataDicService sysDataDicService; + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + @Autowired + private TenantService tenantService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + @Autowired + private SysNotifyGroupService sysNotifyGroupService; + + @Autowired + private SysUserGroupService sysUserGroupService; + + /** + * 系统菜单 + */ + @Operation(summary = "系统菜单") + @HasPermission(requirePlatform = true) + @GetMapping("/menu") + public InvokeResult> menu(@Valid SysMenuSelectorVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + List datas = sysMenuService.selector(vo, moduleIds); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysMenuSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "部门") + @GetMapping("/dept") + public InvokeResult> dept(@Valid SysDeptSelectorVo vo) { + + List results = CollectionUtil.emptyList(); + List datas = sysDeptService.selector(vo); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysDeptSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 加载部门 + */ + @Operation(summary = "加载部门") + @PostMapping("/dept/load") + public InvokeResult> loadDept( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysDeptService.findById(t)).filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SysDeptSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "角色") + @GetMapping("/role") + public InvokeResult> role(@Valid SysRoleSelectorVo vo) { + + PageResult pageResult = sysRoleService.selector(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysRoleSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载角色 + */ + @Operation(summary = "加载角色") + @PostMapping("/role/load") + public InvokeResult> loadRole( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysRoleService.findById(t)).filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SysRoleSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "角色分类") + @GetMapping("/role/category") + public InvokeResult> roleCategory( + @Valid SysRoleCategorySelectorVo vo) { + + PageResult pageResult = sysRoleCategoryService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysRoleCategorySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载角色分类 + */ + @Operation(summary = "加载角色分类") + @PostMapping("/role/category/load") + public InvokeResult> loadRoleCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysRoleCategoryService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream().map(SysRoleCategorySelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "租户") + @HasPermission(requirePlatform = true) + @GetMapping("/tenant") + public InvokeResult> tenant(@Valid TenantSelectorVo vo) { + + PageResult pageResult = tenantService.selector(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(TenantSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载租户 + */ + @Operation(summary = "加载租户") + @HasPermission(requirePlatform = true) + @PostMapping("/tenant/load") + public InvokeResult> loadTenant( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(Objects::nonNull).map(t -> tenantService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(TenantSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "用户") + @GetMapping("/user") + public InvokeResult> user(@Valid SysUserSelectorVo vo) { + + PageResult pageResult = sysUserService.selector(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysUserSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载用户 + */ + @Operation(summary = "加载用户") + @PostMapping("/user/load") + public InvokeResult> loadUser( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysUserService.findById(t)).filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SysUserSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "数据字典分类") + @GetMapping("/dic/category") + public InvokeResult> dataDicCategory( + @Valid SysDataDicCategorySelectorVo vo) { + + PageResult pageResult = sysDataDicCategoryService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysDataDicCategorySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据字典分类 + */ + @Operation(summary = "加载数据字典分类") + @PostMapping("/dic/category/load") + public InvokeResult> loadDataDicCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysDataDicCategoryService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream() + .map(SysDataDicCategorySelectorBo::new).collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "数据字典") + @GetMapping("/dic") + public InvokeResult> dataDic(@Valid SysDataDicSelectorVo vo) { + + PageResult pageResult = sysDataDicService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysDataDicSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据字典 + */ + @Operation(summary = "加载数据字典") + @PostMapping("/dic/load") + public InvokeResult> loadDataDic( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysDataDicService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream().map(SysDataDicSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 开放域 + */ + @Operation(summary = "开放域") + @GetMapping("/openDomain") + public InvokeResult> openDomain( + @Valid SysOpenDomainSelectorVo vo) { + + PageResult pageResult = sysOpenDomainService.selector(vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysOpenDomainSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载开放域 + */ + @Operation(summary = "加载开放域") + @PostMapping("/openDomain/load") + public InvokeResult> openDomain( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(Objects::nonNull) + .map(t -> sysOpenDomainService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream().map(SysOpenDomainSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "消息通知组") + @GetMapping("/notify/group") + public InvokeResult> notifyGroup( + @Valid SysNotifyGroupSelectorVo vo) { + + PageResult pageResult = sysNotifyGroupService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysNotifyGroupSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载消息通知组 + */ + @Operation(summary = "加载消息通知组") + @PostMapping("/notify/group/load") + public InvokeResult> loadNotifyGroup( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysNotifyGroupService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream().map(SysNotifyGroupSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "用户组") + @GetMapping("/user/group") + public InvokeResult> userGroup( + @Valid SysUserGroupSelectorVo vo) { + + PageResult pageResult = sysUserGroupService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysUserGroupSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载用户组 + */ + @Operation(summary = "加载用户组") + @PostMapping("/user/group/load") + public InvokeResult> loadUserGroup( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysUserGroupService.findById(t)).filter(Objects::nonNull) + .collect(Collectors.toList()); + List results = datas.stream().map(SysUserGroupSelectorBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/OpLogController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/OpLogController.java new file mode 100644 index 0000000..56d8b13 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/OpLogController.java @@ -0,0 +1,84 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.oplog.GetOpLogBo; +import com.lframework.starter.web.inner.bo.system.oplog.QueryOpLogBo; +import com.lframework.starter.web.inner.entity.OpLogs; +import com.lframework.starter.web.inner.service.OpLogsService; +import com.lframework.starter.web.inner.vo.oplogs.QueryOpLogsVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 操作日志 + * + * @author zmj + */ +@Tag(name = "操作日志") +@Validated +@RestController +@RequestMapping("/system/oplog") +public class OpLogController extends DefaultBaseController { + + @Autowired + private OpLogsService opLogsService; + + /** + * 操作日志列表 + */ + @Operation(summary = "操作日志列表") + @HasPermission({"system:oplog:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryOpLogsVo vo) { + + PageResult pageResult = opLogsService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryOpLogBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 操作日志详情 + */ + @Operation(summary = "操作日志详情") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:oplog:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "ID不能为空") String id) { + + OpLogs data = opLogsService.findById(id); + + if (data == null) { + throw new DefaultClientException("操作日志不存在!"); + } + + GetOpLogBo result = new GetOpLogBo(data); + + return InvokeResultBuilder.success(result); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicCategoryController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicCategoryController.java new file mode 100644 index 0000000..68cca60 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicCategoryController.java @@ -0,0 +1,142 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.inner.bo.system.dic.category.GetSysDataDicCategoryBo; +import com.lframework.starter.web.inner.bo.system.dic.category.QuerySysDataDicCategoryBo; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.service.system.SysDataDicCategoryService; +import com.lframework.starter.web.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.starter.web.inner.vo.system.dic.category.QuerySysDataDicCategoryVo; +import com.lframework.starter.web.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据字典分类 + * + * @author zmj + */ +@Tag(name = "数据字典分类") +@Validated +@RestController +@RequestMapping("/system/dic/category") +public class SysDataDicCategoryController extends DefaultBaseController { + + @Autowired + private SysDataDicCategoryService sysDataDicCategoryService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:dic-category:*"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysDataDicCategoryVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + List datas = sysDataDicCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic-category:*"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysDataDicCategory data = sysDataDicCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典分类不存在!"); + } + + GetSysDataDicCategoryBo result = new GetSysDataDicCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据字典分类 + */ + @Operation(summary = "新增数据字典分类") + @HasPermission(value = {"system:dic-category:add"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicCategoryVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysDataDicCategoryService.create(vo); + + sysDataDicCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典分类 + */ + @Operation(summary = "修改数据字典分类") + @HasPermission(value = {"system:dic-category:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicCategoryVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysDataDicCategoryService.update(vo); + + sysDataDicCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "删除数据字典分类") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic-category:delete"}, requirePlatform = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + sysDataDicCategoryService.deleteById(id); + + sysDataDicCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicController.java new file mode 100644 index 0000000..1aa4af5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicController.java @@ -0,0 +1,146 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.dic.GetSysDataDicBo; +import com.lframework.starter.web.inner.bo.system.dic.QuerySysDataDicBo; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import com.lframework.starter.web.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.UpdateSysDataDicVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据字典 + * + * @author zmj + */ +@Tag(name = "数据字典") +@Validated +@RestController +@RequestMapping("/system/dic") +public class SysDataDicController extends DefaultBaseController { + + @Autowired + private SysDataDicService sysDataDicService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:dic:*"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysDataDicVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + PageResult pageResult = sysDataDicService.query(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic:*"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysDataDic data = sysDataDicService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + GetSysDataDicBo result = new GetSysDataDicBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据字典 + */ + @Operation(summary = "新增数据字典") + @HasPermission(value = {"system:dic:add"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysDataDicService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典 + */ + @Operation(summary = "修改数据字典") + @HasPermission(value = {"system:dic:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysDataDicService.update(vo); + + sysDataDicService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 删除数据字典 + */ + @Operation(summary = "删除数据字典") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic:delete"}, requirePlatform = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + sysDataDicService.deleteById(id); + + sysDataDicService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicItemController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicItemController.java new file mode 100644 index 0000000..5d9b242 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataDicItemController.java @@ -0,0 +1,181 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.dic.item.GetSysDataDicItemBo; +import com.lframework.starter.web.inner.bo.system.dic.item.QuerySysDataDicItemBo; +import com.lframework.starter.web.inner.bo.system.dic.item.SysDataDicItemBo; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.service.system.SysDataDicItemService; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import com.lframework.starter.web.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.UpdateSysDataDicItemVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据字典值 + * + * @author zmj + */ +@Tag(name = "数据字典值") +@Validated +@RestController +@RequestMapping("/system/dic/item") +public class SysDataDicItemController extends DefaultBaseController { + + @Autowired + private SysDataDicItemService sysDataDicItemService; + + @Autowired + private SysDataDicService sysDataDicService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:dic-item:*"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysDataDicItemVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + PageResult pageResult = sysDataDicItemService.query(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic-item:*"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysDataDicItem data = sysDataDicItemService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典值不存在!"); + } + + GetSysDataDicItemBo result = new GetSysDataDicItemBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据字典编号查询 + */ + @Operation(summary = "根据字典编号查询") + @Parameter(name = "code", description = "字典编号") + @GetMapping("/bydic") + public InvokeResult> getByDicCode( + @NotBlank(message = "字典编号不能为空!") String code) { + List datas = sysDataDicItemService.findByDicCode(code); + + List results = datas.stream().map(SysDataDicItemBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 新增数据字典值 + */ + @Operation(summary = "新增数据字典值") + @HasPermission(value = {"system:dic-item:add"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicItemVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysDataDicItemService.create(vo); + + SysDataDic dic = sysDataDicService.findById(vo.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典值 + */ + @Operation(summary = "修改数据字典值") + @HasPermission(value = {"system:dic-item:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicItemVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + SysDataDicItem item = sysDataDicItemService.findById(vo.getId()); + + sysDataDicItemService.update(vo); + + SysDataDic dic = sysDataDicService.findById(item.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + sysDataDicItemService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 删除数据字典值 + */ + @Operation(summary = "删除数据字典值") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:dic-item:delete"}, requirePlatform = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysDataDicItem item = sysDataDicItemService.findById(id); + + sysDataDicItemService.deleteById(id); + + SysDataDic dic = sysDataDicService.findById(item.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + sysDataDicItemService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionDataController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionDataController.java new file mode 100644 index 0000000..ca1359a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionDataController.java @@ -0,0 +1,95 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.security.SecurityConstants; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionDataBizType; +import com.lframework.starter.web.inner.service.system.SysDataPermissionDataService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.vo.system.permission.CreateSysDataPermissionDataVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 数据权限数据 + * + * @author zmj + */ +@Tag(name = "数据权限数据") +@Validated +@RestController +@RequestMapping("/system/data/permission/data") +public class SysDataPermissionDataController extends DefaultBaseController { + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @Autowired + private SysRoleService sysRoleService; + + @Operation(summary = "保存") + @PostMapping + public InvokeResult save(@Valid @RequestBody List data) { + if (CollectionUtil.isEmpty(data)) { + return InvokeResultBuilder.success(); + } + + for (CreateSysDataPermissionDataVo vo : data) { + if (EnumUtil.getByCode(SysDataPermissionDataBizType.class, vo.getBizType()) + == SysDataPermissionDataBizType.ROLE) { + List roles = vo.getBizIds().stream().map(t -> sysRoleService.findById(t)) + .filter( + Objects::nonNull) + .filter(t -> SecurityConstants.PERMISSION_ADMIN_NAME.equals(t.getPermission())) + .collect(Collectors.toList()); + + if (CollectionUtil.isNotEmpty(roles)) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】为内置权限,不允许设置数据权限!"); + } + } + } + + List records = data.stream() + .flatMap(t -> t.getBizIds().stream() + .map(bizId -> { + SysDataPermissionData record = sysDataPermissionDataService.getByBizId(bizId, + t.getBizType(), + t.getPermissionType()); + if (record == null) { + record = new SysDataPermissionData(); + record.setId(IdUtil.getId()); + record.setBizId(bizId); + record.setBizType( + EnumUtil.getByCode(SysDataPermissionDataBizType.class, t.getBizType())); + record.setPermissionType(t.getPermissionType()); + } + record.setPermission(t.getPermission()); + return record; + })) + .collect(Collectors.toList()); + + sysDataPermissionDataService.saveOrUpdateAllColumnBatch(records); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionModelDetailController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionModelDetailController.java new file mode 100644 index 0000000..96674c7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDataPermissionModelDetailController.java @@ -0,0 +1,150 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.inner.bo.system.permission.QuerySysDataPermissionModelDetailBo; +import com.lframework.starter.web.inner.bo.system.permission.SysDataPermissionModelDetailBo; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; +import com.lframework.starter.web.inner.entity.SysDataPermissionModelDetail; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionDataBizType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailCalcType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailConditionType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailNodeType; +import com.lframework.starter.web.inner.service.system.SysDataPermissionDataService; +import com.lframework.starter.web.inner.service.system.SysDataPermissionModelDetailService; +import com.lframework.starter.web.inner.vo.system.permission.SysDataPermissionModelDetailVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据权限Model明细 + * + * @author zmj + */ +@Tag(name = "数据权限Model明细") +@Validated +@RestController +@RequestMapping("/system/data/permission/model/detail") +public class SysDataPermissionModelDetailController extends DefaultBaseController { + + @Autowired + private SysDataPermissionModelDetailService sysDataPermissionModelDetailService; + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @Operation(summary = "根据模型ID查询") + @Parameter(name = "modelId", description = "模型ID") + @GetMapping + public InvokeResult> getByModelId( + @NotNull(message = "模型ID不能为空!") Integer modelId) { + + Wrapper queryWrapper = Wrappers.lambdaQuery( + SysDataPermissionModelDetail.class).eq(SysDataPermissionModelDetail::getModelId, modelId); + List datas = sysDataPermissionModelDetailService.list( + queryWrapper); + List results = datas.stream() + .map(SysDataPermissionModelDetailBo::new).collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @Operation(summary = "预览SQL") + @PostMapping("/preview") + public InvokeResult preview( + @Valid @RequestBody List models) { + + String sql = sysDataPermissionModelDetailService.toSql(models); + + return InvokeResultBuilder.success(sql); + } + + @Operation(summary = "根据业务ID查询") + @Parameter(name = "modelId", description = "模型ID") + @GetMapping("/query") + public InvokeResult> queryByBizId( + @NotBlank(message = "业务ID不能为空!") String bizId, + @NotNull(message = "业务类型不能为空!") @IsEnum(message = "业务类型格式错误!", enumClass = SysDataPermissionDataBizType.class) Integer bizType, + @NotNull(message = " 权限类型不能为空!") Integer permissionType) { + + SysDataPermissionData data = sysDataPermissionDataService.getByBizId(bizId, bizType, + permissionType); + if (data == null) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + List voList = JsonUtil.parseList(data.getPermission(), + SysDataPermissionModelDetailVo.class); + if (CollectionUtil.isEmpty(voList)) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + List results = this.buildChildren(voList); + + return InvokeResultBuilder.success(results); + } + + private List buildChildren( + List children) { + if (CollectionUtil.isEmpty(children)) { + return Collections.emptyList(); + } + + List results = new ArrayList<>(children.size()); + for (SysDataPermissionModelDetailVo vo : children) { + SysDataPermissionModelDetail modelDetail = sysDataPermissionModelDetailService.getById( + vo.getDetailId()); + QuerySysDataPermissionModelDetailBo result = new QuerySysDataPermissionModelDetailBo(); + result.setId(vo.getId()); + result.setDetailId(vo.getDetailId()); + result.setCalcType(vo.getCalcType()); + result.setNodeType(vo.getNodeType()); + result.setValue(vo.getValue()); + result.setValues(vo.getValues()); + result.setConditionType(vo.getConditionType()); + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, vo.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, vo.getCalcType()); + result.setName(calcType.getDesc()); + result.setChildren(this.buildChildren(vo.getChildren())); + } else { + result.setName(modelDetail.getName()); + result.setModelId(modelDetail.getModelId()); + result.setConditionTypes( + Arrays.stream(modelDetail.getConditionType().split(StringPool.STR_SPLIT)) + .map(t -> EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, t).getCode()) + .toArray(Integer[]::new)); + result.setInputType(modelDetail.getInputType().getCode()); + result.setEnumName(modelDetail.getEnumName()); + } + + results.add(result); + } + + return results; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDeptController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDeptController.java new file mode 100644 index 0000000..ea235ec --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysDeptController.java @@ -0,0 +1,140 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.inner.bo.system.dept.GetSysDeptBo; +import com.lframework.starter.web.inner.bo.system.dept.SysDeptTreeBo; +import com.lframework.starter.web.inner.entity.SysDept; +import com.lframework.starter.web.inner.enums.system.SysDeptNodeType; +import com.lframework.starter.web.inner.service.RecursionMappingService; +import com.lframework.starter.web.inner.service.system.SysDeptService; +import com.lframework.starter.web.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.starter.web.inner.vo.system.dept.UpdateSysDeptVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 部门管理 + * + * @author zmj + */ +@Tag(name = "部门管理") +@Validated +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends DefaultBaseController { + + @Autowired + private SysDeptService sysDeptService; + + @Autowired + private RecursionMappingService recursionMappingService; + + /** + * 部门树形菜单数据 + */ + @Operation(summary = "部门树形菜单数据") + @HasPermission({"system:dept:query", "system:dept:add", "system:dept:modify"}) + @GetMapping("/trees") + public InvokeResult> trees() { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getAvailable, true) + .orderByAsc(SysDept::getCode); + List datas = sysDeptService.list(queryWrapper); + if (CollectionUtil.isEmpty(datas)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List results = datas.stream().map(SysDeptTreeBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 查询部门 + */ + @Operation(summary = "部门详情") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:dept:query", "system:dept:add", "system:dept:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysDept data = sysDeptService.findById(id); + if (data == null) { + throw new DefaultClientException("部门不存在!"); + } + + GetSysDeptBo result = new GetSysDeptBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 删除部门 + */ + @Operation(summary = "删除部门") + @HasPermission({"system:dept:delete"}) + @DeleteMapping + public InvokeResult deleteById( + @Parameter(description = "部门ID", required = true) @NotEmpty(message = "部门ID不能为空!") String id) { + + sysDeptService.deleteById(id); + + List batchIds = new ArrayList<>(); + batchIds.add(id); + + List tmp = recursionMappingService.getNodeChildIds(id, + SysDeptNodeType.class); + batchIds.addAll(tmp); + sysDeptService.cleanCacheByKeys(batchIds); + + return InvokeResultBuilder.success(); + } + + /** + * 新增部门 + */ + @Operation(summary = "新增部门") + @HasPermission({"system:dept:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysDeptVo vo) { + + sysDeptService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改部门 + */ + @Operation(summary = "修改部门") + @HasPermission({"system:dept:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysDeptVo vo) { + + sysDeptService.update(vo); + + sysDeptService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysGenerateCodeController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysGenerateCodeController.java new file mode 100644 index 0000000..29f54d6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysGenerateCodeController.java @@ -0,0 +1,156 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.generator.GenerateCodeFactory; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.generate.GetSysGenerateCodeBo; +import com.lframework.starter.web.inner.bo.system.generate.QuerySysGenerateCodeBo; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import com.lframework.starter.web.inner.service.GenerateCodeService; +import com.lframework.starter.web.inner.service.system.SysGenerateCodeService; +import com.lframework.starter.web.inner.vo.system.generate.*; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 编号规则 Controller + * + * @author zmj + */ +@Tag(name = "编号规则") +@Validated +@RestController +@RequestMapping("/system/generate/code") +public class SysGenerateCodeController extends DefaultBaseController { + + @Autowired + private SysGenerateCodeService sysGenerateCodeService; + + @Autowired + private GenerateCodeService generateCodeService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission({"system:generate-code:manage"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysGenerateCodeVo vo) { + + PageResult pageResult = sysGenerateCodeService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysGenerateCodeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "id") + @HasPermission({"system:generate-code:manage"}) + @GetMapping + public InvokeResult get(@NotNull(message = "id不能为空!") Long id) { + + SysGenerateCode data = sysGenerateCodeService.getById(id); + if (data == null) { + throw new DefaultClientException("编号规则不存在!"); + } + + GetSysGenerateCodeBo result = new GetSysGenerateCodeBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission({"system:generate-code:manage"}) + @PostMapping + public InvokeResult create(@Valid CreateSysGenerateCodeVo vo) { + + sysGenerateCodeService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission({"system:generate-code:manage"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysGenerateCodeVo vo) { + + sysGenerateCodeService.update(vo); + + sysGenerateCodeService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @Operation(summary = "根据ID删除") + @Parameter(name = "id", description = "id") + @HasPermission({"system:generate-code:manage"}) + @DeleteMapping + public InvokeResult deleteById(@NotNull(message = "id不能为空!") Integer id) { + + sysGenerateCodeService.deleteById(id); + + sysGenerateCodeService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 设置规则 + */ + @Operation(summary = "设置规则") + @HasPermission({"system:generate-code:manage"}) + @PatchMapping + public InvokeResult setting(@Valid SettingSysGenerateCodeVo vo) { + + sysGenerateCodeService.setting(vo); + + sysGenerateCodeService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 预览 + */ + @Operation(summary = "预览") + @HasPermission({"system:generate-code:manage"}) + @PostMapping("/preview") + public InvokeResult preview(@Valid PreviewSysGenerateCodeVo vo) { + + return InvokeResultBuilder.success(GenerateCodeFactory.generateExample(vo.getConfigStr())); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMailMessageController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMailMessageController.java new file mode 100644 index 0000000..e405888 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMailMessageController.java @@ -0,0 +1,84 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.message.mail.GetSysMailMessageBo; +import com.lframework.starter.web.inner.bo.system.message.mail.QuerySysMailMessageBo; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import com.lframework.starter.web.inner.service.system.SysMailMessageService; +import com.lframework.starter.web.inner.vo.system.message.mail.QuerySysMailMessageVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 邮件消息 Controller + * + * @author zmj + */ +@Tag(name = "邮件消息") +@Validated +@RestController +@RequestMapping("/system/message/mail") +public class SysMailMessageController extends DefaultBaseController { + + @Autowired + private SysMailMessageService sysMailMessageService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission("system:mail-message:manage") + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysMailMessageVo vo) { + + PageResult pageResult = sysMailMessageService.query(getPageIndex(vo), + getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysMailMessageBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @HasPermission("system:mail-message:manage") + @Parameter(name = "id", description = "id") + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + SysMailMessage data = sysMailMessageService.findById(id); + if (data == null) { + throw new DefaultClientException("邮件消息不存在!"); + } + + GetSysMailMessageBo result = new GetSysMailMessageBo(data); + + return InvokeResultBuilder.success(result); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMenuController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMenuController.java new file mode 100644 index 0000000..dead3d6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysMenuController.java @@ -0,0 +1,269 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.bo.system.menu.GetSysMenuBo; +import com.lframework.starter.web.inner.bo.system.menu.QuerySysMenuBo; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import com.lframework.starter.web.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.starter.web.inner.vo.system.menu.QuerySysMenuVo; +import com.lframework.starter.web.inner.vo.system.menu.UpdateSysMenuVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统菜单管理 + * + * @author zmj + */ +@Tag(name = "系统菜单管理") +@Validated +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends DefaultBaseController { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 系统菜单列表 + */ + @Operation(summary = "系统菜单列表") + @HasPermission(value = {"system:menu:query", "system:menu:add"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysMenuVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + vo.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + List datas = sysMenuService.queryList(moduleIds); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QuerySysMenuBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 新增系统菜单 + */ + @Operation(summary = "新增系统菜单") + @HasPermission(value = {"system:menu:add"}, requirePlatform = true) + @PostMapping + public InvokeResult add(@Valid CreateSysMenuVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + this.validVo(vo); + + sysMenuService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 查看系统菜单 + */ + @Operation(summary = "查看系统菜单") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission({"system:menu:query", "system:menu:add", "system:menu:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysMenu data = sysMenuService.findById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("菜单不存在!"); + } + + return InvokeResultBuilder.success(new GetSysMenuBo(data)); + } + + /** + * 修改系统菜单 + */ + @Operation(summary = "修改系统菜单") + @HasPermission(value = {"system:menu:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult modify(@Valid UpdateSysMenuVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + this.validVo(vo); + + sysMenuService.update(vo); + + sysMenuService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @Operation(summary = "根据ID删除") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:menu:delete"}, requirePlatform = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + sysMenuService.deleteById(id); + + sysMenuService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 启用 + */ + @Operation(summary = "启用") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:menu:modify"}, requirePlatform = true) + @PatchMapping("/enable") + public InvokeResult enable( + @Parameter(description = "菜单ID", required = true) @NotEmpty(message = "菜单ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + sysMenuService.enable(id); + + sysMenuService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 停用 + */ + @Operation(summary = "停用") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:menu:modify"}, requirePlatform = true) + @PatchMapping("/unable") + public InvokeResult unable( + @Parameter(description = "菜单ID", required = true) @NotEmpty(message = "菜单ID不能为空!") String id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + sysMenuService.unable(id); + + sysMenuService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + private void validVo(CreateSysMenuVo vo) { + + SysMenuDisplay sysMenuDisplay = EnumUtil.getByCode(SysMenuDisplay.class, vo.getDisplay()); + + if (sysMenuDisplay == SysMenuDisplay.CATALOG || sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (StringUtil.isBlank(vo.getName())) { + throw new InputErrorException("请输入路由名称!"); + } + + if (StringUtil.isBlank(vo.getPath())) { + throw new InputErrorException("请输入路由路径!"); + } + + if (ObjectUtil.isNull(vo.getHidden())) { + throw new InputErrorException("请选择是否隐藏!"); + } + + if (sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (vo.getComponentType() == null) { + throw new InputErrorException("请选择组件类型!"); + } + if (StringUtil.isBlank(vo.getComponent())) { + throw new InputErrorException("请输入组件!"); + } + if (ObjectUtil.isNull(vo.getNoCache())) { + throw new InputErrorException("请选择是否不缓存!"); + } + + if (!StringUtil.isBlank(vo.getParentId())) { + SysMenu parentMenu = sysMenuService.findById(vo.getParentId()); + + if (parentMenu.getDisplay() != SysMenuDisplay.CATALOG) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.FUNCTION.getDesc() + "”时,父级菜单类型必须是“" + + SysMenuDisplay.CATALOG.getDesc() + "”!"); + } + } + } + } else if (sysMenuDisplay == SysMenuDisplay.PERMISSION) { + if (StringUtil.isBlank(vo.getParentId())) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单不能为空!"); + } + + SysMenu parentMenu = sysMenuService.findById(vo.getParentId()); + if (ObjectUtil.isNull(parentMenu)) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单不能为空!"); + } + + if (parentMenu.getDisplay() != SysMenuDisplay.FUNCTION) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单类型必须是“" + + SysMenuDisplay.FUNCTION.getDesc() + "”!"); + } + if (StringUtil.isBlank(vo.getPermission())) { + throw new InputErrorException("请输入权限!"); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysModuleController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysModuleController.java new file mode 100644 index 0000000..7ee5efe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysModuleController.java @@ -0,0 +1,98 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.bo.system.module.QuerySysModuleBo; +import com.lframework.starter.web.inner.entity.SysModule; +import com.lframework.starter.web.inner.entity.SysModuleTenant; +import com.lframework.starter.web.inner.service.SysModuleService; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.vo.system.module.SysModuleTenantVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统模块管理 + * + * @author zmj + */ +@Tag(name = "系统模块管理") +@Validated +@RestController +@RequestMapping("/system/module") +public class SysModuleController extends DefaultBaseController { + + @Autowired + private SysModuleService sysModuleService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:tenant:module"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@NotNull(message = "租户ID不能为空!") Integer tenantId) { + + if (!TenantUtil.enableTenant()) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + // 先查询所有模块 + List sysModules = sysModuleService.list(); + List results = sysModules.stream().map(QuerySysModuleBo::new) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(results)) { + return InvokeResultBuilder.success(results); + } + + List sysModuleTenants = sysModuleTenantService.getByTenantId(tenantId); + + for (QuerySysModuleBo result : results) { + SysModuleTenant sysModuleTenant = sysModuleTenants.stream() + .filter(t -> ObjectUtil.equal(t.getModuleId(), result.getId())).findFirst().orElse(null); + result.setEnabled(sysModuleTenant != null); + if (sysModuleTenant == null) { + continue; + } + result.setExpireTime(sysModuleTenant.getExpireTime()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 模块授权 + */ + @Operation(summary = "模块授权") + @HasPermission(value = {"system:tenant:module"}, requirePlatform = true) + @PostMapping("/setting") + public InvokeResult setting( + @RequestBody(required = false) @Valid SysModuleTenantVo vo) { + + if (!TenantUtil.enableTenant()) { + return InvokeResultBuilder.success(); + } + sysModuleTenantService.setting(vo); + + sysModuleTenantService.cleanCacheByKey(vo.getTenantId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNoticeController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNoticeController.java new file mode 100644 index 0000000..1e591e1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNoticeController.java @@ -0,0 +1,171 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.threads.DefaultRunnable; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.notice.GetSysNoticeBo; +import com.lframework.starter.web.inner.bo.system.notice.QueryMySysNoticeBo; +import com.lframework.starter.web.inner.bo.system.notice.QuerySysNoticeBo; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.inner.dto.system.notice.SysNoticeDto; +import com.lframework.starter.web.inner.entity.SysNotice; +import com.lframework.starter.web.inner.service.system.SysNoticeService; +import com.lframework.starter.web.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.UpdateSysNoticeVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统通知 Controller + * + * @author zmj + */ +@Tag(name = "系统通知") +@Validated +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends DefaultBaseController { + + @Autowired + private SysNoticeService sysNoticeService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission({"system:notice:publish"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysNoticeVo vo) { + + PageResult pageResult = sysNoticeService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysNoticeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询我的通知 + */ + @Operation(summary = "查询我的通知") + @GetMapping("/query/my") + public InvokeResult> queryMyNotice( + @Valid QuerySysNoticeByUserVo vo) { + + vo.setUserId(SecurityUtil.getCurrentUser().getId()); + + PageResult pageResult = sysNoticeService.queryByUser(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryMySysNoticeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询内容 + */ + @Operation(summary = "根据ID查询内容") + @Parameter(name = "id", description = "id") + @GetMapping("/content") + public InvokeResult getContent(@NotBlank(message = "id不能为空!") String id) { + + SysNoticeDto data = sysNoticeService.getContent(id); + if (data == null) { + throw new DefaultClientException("系统通知不存在!"); + } + + String currentUserId = SecurityUtil.getCurrentUser().getId(); + ThreadUtil.execAsync(new DefaultRunnable(() -> { + sysNoticeService.setReaded(id, currentUserId); + + sysNoticeService.noticeForWs(currentUserId); + })); + + return InvokeResultBuilder.success(data); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "id") + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + SysNotice data = sysNoticeService.findById(id); + if (data == null) { + throw new DefaultClientException("系统通知不存在!"); + } + + GetSysNoticeBo result = new GetSysNoticeBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission({"system:notice:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysNoticeVo vo) { + + sysNoticeService.create(vo); + + if (vo.getPublished()) { + sysNoticeService.noticeForWs(); + } + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission({"system:notice:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysNoticeVo vo) { + + sysNoticeService.update(vo); + + sysNoticeService.cleanCacheByKey(vo.getId()); + + if (vo.getPublished()) { + sysNoticeService.noticeForWs(); + } + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNotifyGroupController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNotifyGroupController.java new file mode 100644 index 0000000..778e698 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysNotifyGroupController.java @@ -0,0 +1,127 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.notify.GetSysNotifyGroupBo; +import com.lframework.starter.web.inner.bo.system.notify.QuerySysNotifyGroupBo; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.service.system.SysNotifyGroupService; +import com.lframework.starter.web.inner.vo.system.notify.CreateSysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.QuerySysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.UpdateSysNotifyGroupVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 消息通知组 Controller + * + * @author zmj + */ +@Tag(name = "消息通知组") +@Validated +@RestController +@RequestMapping("/sys/notify/group") +public class SysNotifyGroupController extends DefaultBaseController { + + @Autowired + private SysNotifyGroupService sysNotifyGroupService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission({"system:notify-group:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QuerySysNotifyGroupVo vo) { + + PageResult pageResult = sysNotifyGroupService.query( + getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysNotifyGroupBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:notify-group:query"}) + @GetMapping("/detail") + public InvokeResult getDetail( + @NotBlank(message = "id不能为空!") String id) { + + SysNotifyGroup data = sysNotifyGroupService.findById(id); + if (data == null) { + throw new DefaultClientException("消息通知组不存在!"); + } + + GetSysNotifyGroupBo result = new GetSysNotifyGroupBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission({"system:notify-group:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateSysNotifyGroupVo vo) { + + sysNotifyGroupService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission({"system:notify-group:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateSysNotifyGroupVo vo) { + + sysNotifyGroupService.update(vo); + + sysNotifyGroupService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "根据ID删除") + @HasPermission({"system:notify-group:delete"}) + @DeleteMapping + public InvokeResult deleteById( + @Parameter(description = "ID", required = true) @NotEmpty(message = "ID不能为空!") String id) { + + sysNotifyGroupService.deleteById(id); + sysNotifyGroupService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysOpenDomainController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysOpenDomainController.java new file mode 100644 index 0000000..f994bcb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysOpenDomainController.java @@ -0,0 +1,126 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.open.GetSysOpenDomainBo; +import com.lframework.starter.web.inner.bo.system.open.QuerySysOpenDomainBo; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import com.lframework.starter.web.inner.service.system.SysOpenDomainService; +import com.lframework.starter.web.inner.vo.system.open.CreateSysOpenDomainVo; +import com.lframework.starter.web.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.starter.web.inner.vo.system.open.UpdateSysOpenDomainSecretVo; +import com.lframework.starter.web.inner.vo.system.open.UpdateSysOpenDomainVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 开放域 + * + * @author zmj + */ +@Tag(name = "开放域") +@Validated +@RestController +@RequestMapping("/system/open/domain") +public class SysOpenDomainController extends DefaultBaseController { + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:open-domain:config"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysOpenDomainVo vo) { + + PageResult pageResult = sysOpenDomainService.query(vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysOpenDomainBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 详情 + */ + @Operation(summary = "详情") + @Parameter(name = "id", description = "ID") + @HasPermission(value = {"system:open-domain:config"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotNull(message = "ID不能为空!") Integer id) { + + SysOpenDomain data = sysOpenDomainService.findById(id); + if (data == null) { + throw new DefaultClientException("开放域不存在!"); + } + + GetSysOpenDomainBo result = new GetSysOpenDomainBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission(value = {"system:open-domain:config"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateSysOpenDomainVo vo) { + + sysOpenDomainService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission(value = {"system:open-domain:config"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateSysOpenDomainVo vo) { + + sysOpenDomainService.update(vo); + + sysOpenDomainService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 修改Api密钥 + */ + @Operation(summary = "修改Api密钥") + @HasPermission(value = {"system:open-domain:config"}, requirePlatform = true) + @PutMapping("/secret") + public InvokeResult updateSecret(@Valid UpdateSysOpenDomainSecretVo vo) { + + sysOpenDomainService.updateApiSecret(vo); + + sysOpenDomainService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysParameterController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysParameterController.java new file mode 100644 index 0000000..ae94420 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysParameterController.java @@ -0,0 +1,154 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.parameter.GetSysParameterBo; +import com.lframework.starter.web.inner.bo.system.parameter.QuerySysParameterBo; +import com.lframework.starter.web.inner.entity.SysParameter; +import com.lframework.starter.web.inner.service.system.SysParameterService; +import com.lframework.starter.web.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.UpdateSysParameterVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统参数 Controller + * + * @author zmj + */ +@Tag(name = "系统参数") +@Validated +@RestController +@RequestMapping("/system/parameter") +public class SysParameterController extends DefaultBaseController { + + @Autowired + private SysParameterService sysParameterService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:parameter:query"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysParameterVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + PageResult pageResult = sysParameterService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysParameterBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:parameter:query"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotNull(message = "id不能为空!") Long id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysParameter data = sysParameterService.getById(id); + if (data == null) { + throw new DefaultClientException("系统参数不存在!"); + } + + GetSysParameterBo result = new GetSysParameterBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission(value = {"system:parameter:add"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateSysParameterVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysParameterService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission(value = {"system:parameter:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateSysParameterVo vo) { + + TenantContextHolder.setTenantId(vo.getTenantId()); + + sysParameterService.update(vo); + + sysParameterService.cleanCacheByKey(vo.getId()); + + SysParameter data = sysParameterService.findById(vo.getId()); + sysParameterService.cleanCacheByKey(data.getPmKey()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @Operation(summary = "根据ID删除") + @Parameters({ + @Parameter(name = "id", description = "ID"), + @Parameter(name = "tenantId", description = "租户ID") + }) + @HasPermission(value = {"system:parameter:delete"}, requirePlatform = true) + @DeleteMapping + public InvokeResult deleteById(@NotNull(message = "id不能为空!") Long id, + @NotNull(message = "租户ID不能为空!") Integer tenantId) { + + TenantContextHolder.setTenantId(tenantId); + + SysParameter data = sysParameterService.findById(id); + + sysParameterService.deleteById(id); + + sysParameterService.cleanCacheByKey(id); + + sysParameterService.cleanCacheByKey(data.getPmKey()); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleCategoryController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleCategoryController.java new file mode 100644 index 0000000..c450767 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleCategoryController.java @@ -0,0 +1,112 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.inner.bo.system.role.category.GetSysRoleCategoryBo; +import com.lframework.starter.web.inner.bo.system.role.category.QuerySysRoleCategoryBo; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import com.lframework.starter.web.inner.service.system.SysRoleCategoryService; +import com.lframework.starter.web.inner.vo.system.role.category.CreateSysRoleCategoryVo; +import com.lframework.starter.web.inner.vo.system.role.category.UpdateSysRoleCategoryVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 角色分类 + * + * @author zmj + */ +@Tag(name = "角色分类") +@Validated +@RestController +@RequestMapping("/sys/role/category") +public class SysRoleCategoryController extends DefaultBaseController { + + @Autowired + private SysRoleCategoryService sysRoleCategoryService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = sysRoleCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysRoleCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "ID") + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysRoleCategory data = sysRoleCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("角色分类不存在!"); + } + + GetSysRoleCategoryBo result = new GetSysRoleCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增角色分类 + */ + @Operation(summary = "新增角色分类") + @PostMapping + public InvokeResult create(@Valid CreateSysRoleCategoryVo vo) { + + sysRoleCategoryService.create(vo); + + sysRoleCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改角色分类 + */ + @Operation(summary = "修改角色分类") + @PutMapping + public InvokeResult update(@Valid UpdateSysRoleCategoryVo vo) { + + sysRoleCategoryService.update(vo); + + sysRoleCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "删除角色分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + sysRoleCategoryService.deleteById(id); + + sysRoleCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleController.java new file mode 100644 index 0000000..d0abd62 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleController.java @@ -0,0 +1,128 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.role.GetSysRoleBo; +import com.lframework.starter.web.inner.bo.system.role.QuerySysRoleBo; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.UpdateSysRoleVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 角色管理 + * + * @author zmj + */ +@Tag(name = "角色管理") +@Validated +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends DefaultBaseController { + + @Autowired + private SysRoleService sysRoleService; + + /** + * 角色列表 + */ + @Operation(summary = "角色列表") + @HasPermission({"system:role:query","system:role:add","system:role:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysRoleVo vo) { + + PageResult pageResult = sysRoleService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysRoleBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询角色 + */ + @Operation(summary = "查询角色") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:role:query","system:role:add","system:role:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysRole data = sysRoleService.findById(id); + if (data == null) { + throw new DefaultClientException("角色不存在!"); + } + + GetSysRoleBo result = new GetSysRoleBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 删除角色 + */ + @Operation(summary = "删除角色") + @HasPermission({"system:role:delete"}) + @DeleteMapping + public InvokeResult deleteById( + @Parameter(description = "角色ID", required = true) @NotEmpty(message = "角色ID不能为空!") String id) { + + sysRoleService.deleteById(id); + + sysRoleService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 新增角色 + */ + @Operation(summary = "新增角色") + @HasPermission({"system:role:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysRoleVo vo) { + + sysRoleService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改角色 + */ + @Operation(summary = "修改角色") + @HasPermission({"system:role:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysRoleVo vo) { + + sysRoleService.update(vo); + + sysRoleService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleMenuController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleMenuController.java new file mode 100644 index 0000000..49d5806 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysRoleMenuController.java @@ -0,0 +1,95 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.bo.system.role.QueryRoleMenuBo; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import com.lframework.starter.web.inner.service.system.SysRoleMenuService; +import com.lframework.starter.web.inner.vo.system.role.SysRoleMenuSettingVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 角色授权 + * + * @author zmj + */ +@Tag(name = "角色授权") +@Validated +@RestController +@RequestMapping("/system/role/menu") +public class SysRoleMenuController extends DefaultBaseController { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysRoleMenuService sysRoleMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 查询角色菜单列表 + */ + @Operation(summary = "查询角色菜单列表") + @Parameter(name = "roleId", description = "角色ID") + @HasPermission({"system:role:permission"}) + @GetMapping("/menus") + public InvokeResult> menus(String roleId) { + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId(TenantContextHolder.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + //查询所有菜单 + List allMenu = sysMenuService.queryList(moduleIds); + if (!CollectionUtil.isEmpty(allMenu)) { + results = allMenu.stream().map(QueryRoleMenuBo::new).collect(Collectors.toList()); + + if (!StringUtil.isBlank(roleId)) { + List menus = sysMenuService.getByRoleId(roleId, moduleIds); + if (!CollectionUtil.isEmpty(menus)) { + //当角色的菜单存在时,设置已选择属性 + for (QueryRoleMenuBo result : results) { + result.setSelected( + menus.stream().anyMatch(t -> StringUtil.equals(t.getId(), result.getId()))); + } + } + } + } + + return InvokeResultBuilder.success(results); + } + + /** + * 授权角色菜单 + */ + @Operation(summary = "授权角色菜单") + @HasPermission({"system:role:permission"}) + @PostMapping("/setting") + public InvokeResult setting(@Valid @RequestBody SysRoleMenuSettingVo vo) { + + sysRoleMenuService.setting(vo); + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysSiteMessageController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysSiteMessageController.java new file mode 100644 index 0000000..42a80b9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysSiteMessageController.java @@ -0,0 +1,136 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.threads.DefaultRunnable; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.message.site.GetSysSiteMessageBo; +import com.lframework.starter.web.inner.bo.system.message.site.QueryMySysSiteMessageBo; +import com.lframework.starter.web.inner.bo.system.message.site.QuerySysSiteMessageBo; +import com.lframework.starter.web.inner.dto.message.site.SiteMessageDto; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.service.system.SysSiteMessageService; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageByUserVo; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 站内信 Controller + * + * @author zmj + */ +@Tag(name = "站内信") +@Validated +@RestController +@RequestMapping("/system/message/site") +public class SysSiteMessageController extends DefaultBaseController { + + @Autowired + private SysSiteMessageService sysSiteMessageService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission("system:site-message:manage") + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysSiteMessageVo vo) { + + PageResult pageResult = sysSiteMessageService.query(getPageIndex(vo), + getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysSiteMessageBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询我的站内信 + */ + @Operation(summary = "查询我的站内信") + @GetMapping("/query/my") + public InvokeResult> queryMySiteMessage( + @Valid QuerySysSiteMessageByUserVo vo) { + + vo.setUserId(SecurityUtil.getCurrentUser().getId()); + + PageResult pageResult = sysSiteMessageService.queryByUser(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryMySysSiteMessageBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询内容 + */ + @Operation(summary = "根据ID查询内容") + @Parameter(name = "id", description = "id") + @GetMapping("/content") + public InvokeResult getContent(@NotBlank(message = "id不能为空!") String id) { + + SiteMessageDto data = sysSiteMessageService.getContent(id); + if (data == null) { + throw new DefaultClientException("站内信不存在!"); + } + + String currentUserId = SecurityUtil.getCurrentUser().getId(); + ThreadUtil.execAsync(new DefaultRunnable(() -> { + if (sysSiteMessageService.setReaded(id)) { + sysSiteMessageService.noticeForWs(currentUserId); + } + })); + + return InvokeResultBuilder.success(data); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @HasPermission("system:site-message:manage") + @Parameter(name = "id", description = "id") + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + SysSiteMessage data = sysSiteMessageService.findById(id); + if (data == null) { + throw new DefaultClientException("站内信不存在!"); + } + + GetSysSiteMessageBo result = new GetSysSiteMessageBo(data); + + return InvokeResultBuilder.success(result); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserController.java new file mode 100644 index 0000000..37b788a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserController.java @@ -0,0 +1,150 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.user.GetSysUserBo; +import com.lframework.starter.web.inner.bo.system.user.QuerySysUserBo; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import com.lframework.starter.web.inner.vo.system.user.CreateSysUserVo; +import com.lframework.starter.web.inner.vo.system.user.QuerySysUserVo; +import com.lframework.starter.web.inner.vo.system.user.UpdateSysUserVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户管理 + * + * @author zmj + */ +@Tag(name = "用户管理") +@Validated +@RestController +@RequestMapping("/system/user") +public class SysUserController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + /** + * 用户列表 + */ + @Operation(summary = "用户列表") + @HasPermission({"system:user:query", "system:user:add", "system:user:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysUserVo vo) { + + PageResult pageResult = sysUserService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysUserBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询用户 + */ + @Operation(summary = "查询用户") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:user:query", "system:user:add", "system:user:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysUser data = sysUserService.findById(id); + if (data == null) { + throw new DefaultClientException("用户不存在!"); + } + + GetSysUserBo result = new GetSysUserBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID删除 + */ + @Operation(summary = "根据ID删除") + @HasPermission({"system:user:delete"}) + @DeleteMapping + public InvokeResult deleteById( + @Parameter(description = "用户ID", required = true) @NotEmpty(message = "用户ID不能为空!") String id) { + + sysUserService.deleteById(id); + + sysUserService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 新增用户 + */ + @Operation(summary = "新增用户") + @HasPermission({"system:user:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateSysUserVo vo) { + + sysUserService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改用户 + */ + @Operation(summary = "修改用户") + @HasPermission({"system:user:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateSysUserVo vo) { + + sysUserService.update(vo); + + sysUserService.cleanCacheByKey(vo.getId()); + + sysUserDeptService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 解锁用户 + */ + @Operation(summary = "解锁用户") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:user:modify"}) + @PatchMapping("/unlock") + public InvokeResult unlock(@NotBlank(message = "ID不能为空!") String id) { + + sysUserService.unlockById(id); + + sysUserService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserDeptController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserDeptController.java new file mode 100644 index 0000000..fa0c0ea --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserDeptController.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.vo.system.dept.SysUserDeptSettingVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户与部门的关系 + * + * @author zmj + */ +@Tag(name = "用户与部门的关系") +@Validated +@RestController +@RequestMapping("/system/user/dept") +public class SysUserDeptController extends DefaultBaseController { + + @Autowired + private SysUserDeptService sysUserDeptService; + + /** + * 设置用户的部门 + */ + @Operation(summary = "设置用户的部门") + @HasPermission({"system:user:modify"}) + @PostMapping("/setting") + public InvokeResult setting(@Valid @RequestBody SysUserDeptSettingVo vo) { + + sysUserDeptService.setting(vo); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserGroupController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserGroupController.java new file mode 100644 index 0000000..97f59cf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserGroupController.java @@ -0,0 +1,127 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.user.group.GetSysUserGroupBo; +import com.lframework.starter.web.inner.bo.system.user.group.QuerySysUserGroupBo; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import com.lframework.starter.web.inner.service.system.SysUserGroupService; +import com.lframework.starter.web.inner.vo.system.user.group.CreateSysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.QuerySysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.UpdateSysUserGroupVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户组 Controller + * + * @author zmj + */ +@Tag(name = "用户组") +@Validated +@RestController +@RequestMapping("/sys/user/group") +public class SysUserGroupController extends DefaultBaseController { + + @Autowired + private SysUserGroupService sysUserGroupService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission({"system:user-group:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QuerySysUserGroupVo vo) { + + PageResult pageResult = sysUserGroupService.query( + getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysUserGroupBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @Operation(summary = "根据ID查询") + @Parameter(name = "id", description = "ID") + @HasPermission({"system:user-group:query"}) + @GetMapping("/detail") + public InvokeResult getDetail( + @NotBlank(message = "id不能为空!") String id) { + + SysUserGroup data = sysUserGroupService.findById(id); + if (data == null) { + throw new DefaultClientException("消息通知组不存在!"); + } + + GetSysUserGroupBo result = new GetSysUserGroupBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @Operation(summary = "新增") + @HasPermission({"system:user-group:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateSysUserGroupVo vo) { + + sysUserGroupService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @Operation(summary = "修改") + @HasPermission({"system:user-group:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateSysUserGroupVo vo) { + + sysUserGroupService.update(vo); + + sysUserGroupService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @Operation(summary = "根据ID删除") + @HasPermission({"system:user-group:delete"}) + @DeleteMapping + public InvokeResult deleteById( + @Parameter(description = "ID", required = true) @NotEmpty(message = "ID不能为空!") String id) { + + sysUserGroupService.deleteById(id); + sysUserGroupService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserRoleController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserRoleController.java new file mode 100644 index 0000000..8590fb8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/SysUserRoleController.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import com.lframework.starter.web.inner.vo.system.user.SysUserRoleSettingVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户授权 + * + * @author zmj + */ +@Tag(name = "用户授权") +@Validated +@RestController +@RequestMapping("/system/user/role") +public class SysUserRoleController extends DefaultBaseController { + + @Autowired + private SysUserRoleService sysUserRoleService; + + /** + * 用户授权 + */ + @Operation(summary = "用户授权") + @HasPermission({"system:user:permission"}) + @PostMapping("/setting") + public InvokeResult setting(@Valid @RequestBody SysUserRoleSettingVo vo) { + + sysUserRoleService.setting(vo); + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/TenantController.java b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/TenantController.java new file mode 100644 index 0000000..4696ef5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/controller/system/TenantController.java @@ -0,0 +1,140 @@ +package com.lframework.starter.web.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.security.HasPermission; +import com.lframework.starter.web.core.components.resp.InvokeResult; +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.controller.DefaultBaseController; +import com.lframework.starter.web.core.event.ReloadTenantEvent; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.EncryptUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.bo.system.tenant.GetTenantBo; +import com.lframework.starter.web.inner.bo.system.tenant.QueryTenantBo; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.service.TenantService; +import com.lframework.starter.web.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.UpdateTenantVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 租户管理 + * + * @author zmj + */ +@Slf4j +@Tag(name = "租户管理") +@Validated +@RestController +@RequestMapping("/system/tenant") +public class TenantController extends DefaultBaseController { + + @Autowired + private TenantService tenantService; + + /** + * 查询列表 + */ + @Operation(summary = "查询列表") + @HasPermission(value = {"system:tenant:query", "system:tenant:add", + "system:tenant:modify"}, requirePlatform = true) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryTenantVo vo) { + + PageResult pageResult = tenantService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = datas.stream().map(QueryTenantBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询详情 + */ + @Operation(summary = "查询详情") + @Parameter(name = "id", description = "ID") + @HasPermission(value = {"system:tenant:query", "system:tenant:add", + "system:tenant:modify"}, requirePlatform = true) + @GetMapping + public InvokeResult get(@NotNull(message = "ID不能为空!") Integer id) { + + Tenant data = tenantService.findById(id); + if (data == null) { + throw new DefaultClientException("租户不存在!"); + } + + GetTenantBo result = new GetTenantBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增租户 + */ + @Operation(summary = "新增租户") + @HasPermission(value = {"system:tenant:add"}, requirePlatform = true) + @PostMapping + public InvokeResult create(@Valid CreateTenantVo vo) { + + Integer tenantId = tenantService.create(vo); + + try { + ReloadTenantEvent event = new ReloadTenantEvent(this, tenantId, vo.getJdbcUrl(), + vo.getJdbcUsername(), vo.getJdbcPassword()); + ApplicationUtil.publishEvent(event); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultClientException( + "动态加载租户数据源失败,请检查配置项!注意:虽然加载数据源失败,但是租户已经新增,请勿重复新增!"); + } + + return InvokeResultBuilder.success(); + } + + /** + * 修改租户 + */ + @Operation(summary = "修改租户") + @HasPermission(value = {"system:tenant:modify"}, requirePlatform = true) + @PutMapping + public InvokeResult update(@Valid UpdateTenantVo vo) { + + tenantService.update(vo); + + tenantService.cleanCacheByKey(vo.getId()); + + if (StringUtil.isNotBlank(vo.getJdbcUrl()) || StringUtil.isNotBlank(vo.getJdbcUsername()) + || StringUtil.isNotBlank(vo.getJdbcPassword())) { + // 这里不走缓存 + Tenant tenant = tenantService.getById(vo.getId()); + try { + ReloadTenantEvent event = new ReloadTenantEvent(this, tenant.getId(), tenant.getJdbcUrl(), + tenant.getJdbcUsername(), EncryptUtil.decrypt(tenant.getJdbcPassword())); + ApplicationUtil.publishEvent(event); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultClientException( + "动态加载租户数据源失败,请检查配置项!"); + } + } + + return InvokeResultBuilder.success(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/dic/city/DicCityDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/dic/city/DicCityDto.java new file mode 100644 index 0000000..38d3a4f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/dic/city/DicCityDto.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.dto.dic.city; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class DicCityDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "DicCityDto"; + + public static final String SELECTOR_CACHE_NAME = "DicCitySelectorDto"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + private String parentId; + + /** + * 层级 + */ + private Integer level; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysMailMessageDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysMailMessageDto.java new file mode 100644 index 0000000..6db933e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysMailMessageDto.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.dto.message; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class SysMailMessageDto implements BaseDto, Serializable { + + /** + * 接收邮件列表 + */ + private List mailList; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 业务键 + */ + private String bizKey; + + /** + * 创建人ID 如果是空表示由系统自动发起 + */ + private String createUserId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysNoticeTaskDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysNoticeTaskDto.java new file mode 100644 index 0000000..fde0eb7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysNoticeTaskDto.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.inner.dto.message; + +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysNoticeTaskDto extends BaseBo implements BaseDto, + Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + + /** + * 发布时间 + */ + @Schema(description = "发布时间") + private String publishTime; + + public SysNoticeTaskDto(QuerySysNoticeByUserDto dto) { + super(dto); + } + + @Override + protected void afterInit(QuerySysNoticeByUserDto dto) { + this.publishTime = DateUtil.formatDateTime(dto.getPublishTime()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysSiteMessageDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysSiteMessageDto.java new file mode 100644 index 0000000..dcdb281 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/SysSiteMessageDto.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.dto.message; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class SysSiteMessageDto implements BaseDto, Serializable { + + /** + * 接收邮件列表 + */ + private List userIdList; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 业务键 + */ + private String bizKey; + + /** + * 创建人ID 如果是空表示由系统自动发起 + */ + private String createUserId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/site/SiteMessageDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/site/SiteMessageDto.java new file mode 100644 index 0000000..08586fb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/message/site/SiteMessageDto.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.dto.message.site; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author zmj + * @since 2022/8/18 + */ +@Data +public class SiteMessageDto extends BaseBo implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容") + private String content; + + public SiteMessageDto(SysSiteMessage dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyDto.java new file mode 100644 index 0000000..ab2ed6c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyDto.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.dto.notify; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysNotifyDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 动态参数 + */ + private Object variables; + + /** + * 业务类型 + */ + private Integer bizType; + + /** + * 通知组ID + */ + private String notifyGroupId; + + /** + * 创建人ID 如果是空表示由系统自动发起 + */ + private String createUserId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyParamsDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyParamsDto.java new file mode 100644 index 0000000..fb7f2ff --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/notify/SysNotifyParamsDto.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.dto.notify; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysNotifyParamsDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 动态参数 + */ + private Object variables; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/order/ApprovePassOrderDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/order/ApprovePassOrderDto.java new file mode 100644 index 0000000..4bbff65 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/order/ApprovePassOrderDto.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.dto.order; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class ApprovePassOrderDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据ID + */ + private String id; + + /** + * 单据总金额 + */ + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + private LocalDateTime approveTime = LocalDateTime.now(); + + /** + * 单据类型 + */ + private OrderType orderType; + + public enum OrderType { + PURCHASE_ORDER, PURCHASE_RETURN, SALE_ORDER, SALE_RETURN, RETAIL_OUT_SHEET, RETAIL_RETURN + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/qrtz/QrtzDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/qrtz/QrtzDto.java new file mode 100644 index 0000000..9246b31 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/qrtz/QrtzDto.java @@ -0,0 +1,79 @@ +package com.lframework.starter.web.inner.dto.qrtz; + +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.inner.enums.system.QrtzJobType; +import com.lframework.starter.web.inner.enums.system.TriggerState; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class QrtzDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + private String name; + + /** + * 分组 + */ + private String group; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 备注 + */ + private String description; + + /** + * 执行类名 + */ + private String targetClassName; + + /** + * 执行方法名 + */ + private String targetMethodName; + + /** + * 执行参数类型 + */ + private List targetParamTypes; + + /** + * 执行参数 + */ + private List targetParams; + + /** + * 脚本 + */ + private String script; + + /** + * 任务类型 + */ + private QrtzJobType jobType; + + /** + * Cron表达式 + */ + private String cron; + + /** + * 状态 + */ + private TriggerState state; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/LoginDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/LoginDto.java new file mode 100644 index 0000000..25f9d0e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/LoginDto.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.inner.dto.system; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.util.Set; + +/** + * 用户登录Dto + * + * @author zmj + */ +@Data +public class LoginDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Token + */ + private String token; + + /** + * 用户信息 + */ + private UserInfoDto user; + + /** + * 角色 + */ + private Set roles; + + public LoginDto(String token, String name, Set roles) { + + this.token = token; + this.setRoles(roles); + + UserInfoDto userInfo = new UserInfoDto(); + userInfo.setName(name); + this.setUser(userInfo); + } + + @Data + public static class UserInfoDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 姓名 + */ + private String name; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuDto.java new file mode 100644 index 0000000..c3ff4c0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuDto.java @@ -0,0 +1,83 @@ +package com.lframework.starter.web.inner.dto.system; + +import com.lframework.starter.web.core.dto.BaseDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 菜单Dto + * + * @author zmj + */ +@Data +public class MenuDto implements BaseDto, Serializable { + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 菜单名称 + */ + @Schema(description = "菜单名称") + private String name; + + /** + * 路径 + */ + @Schema(description = "路径") + private String path; + + /** + * 是否隐藏 + */ + @Schema(description = "是否隐藏") + private Boolean hidden; + + /** + * 类型 0-目录 1-功能菜单 2-权限 + */ + @Schema(description = "类型 0-目录 1-功能菜单 2-权限") + private Integer display; + + /** + * 组件类型 + */ + @Schema(description = "组件类型") + private Integer componentType; + + /** + * 组件 + */ + @Schema(description = "组件") + private String component; + + /** + * 自定义请求参数 + */ + @Schema(description = "自定义请求参数") + private String requestParam; + + + /** + * meta + */ + @Schema(description = "meta") + private MenuMetaDto meta; + + /** + * 父节点ID + */ + @Schema(description = "父节点ID") + private String parentId; + + /** + * 是否收藏 + */ + @Schema(description = "是否收藏") + private Boolean isCollect = Boolean.FALSE; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuMetaDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuMetaDto.java new file mode 100644 index 0000000..28f9061 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/MenuMetaDto.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.dto.system; + +import com.lframework.starter.web.core.dto.BaseDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 菜单Meta Dto + * + * @author zmj + */ +@Data +public class MenuMetaDto implements BaseDto, Serializable { + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 是否不缓存 + */ + @Schema(description = "是否不缓存") + private Boolean noCache; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/UserInfoDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/UserInfoDto.java new file mode 100644 index 0000000..886512a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/UserInfoDto.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.inner.dto.system; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户信息 Dto + * + * @author zmj + */ +@Data +public class UserInfoDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "UserInfoDto"; + + /** + * ID + */ + private String id; + + /** + * 登录名 + */ + private String username; + + /** + * 编号 + */ + private String code; + + /** + * 姓名 + */ + private String name; + + /** + * 邮箱 + */ + private String email; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 性别 + */ + private Integer gender; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/QuerySysNoticeByUserDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/QuerySysNoticeByUserDto.java new file mode 100644 index 0000000..d30a692 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/QuerySysNoticeByUserDto.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.dto.system.notice; + +import com.lframework.starter.web.core.dto.BaseDto; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author zmj + * @since 2022/8/19 + */ +@Data +public class QuerySysNoticeByUserDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 是否已读 + */ + private Boolean readed; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/SysNoticeDto.java b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/SysNoticeDto.java new file mode 100644 index 0000000..8b7e69f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/dto/system/notice/SysNoticeDto.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.dto.system.notice; + +import com.lframework.starter.web.core.bo.BaseBo; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.inner.entity.SysNotice; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author zmj + * @since 2022/8/18 + */ +@Data +public class SysNoticeDto extends BaseBo implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容") + private String content; + + public SysNoticeDto(SysNotice dto) { + super(dto); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/DicCity.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/DicCity.java new file mode 100644 index 0000000..64aebb1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/DicCity.java @@ -0,0 +1,51 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-07 + */ +@Data +@TableName("dic_city") +public class DicCity extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + private String parentId; + + /** + * 层级 + */ + private Integer level; + + /** + * 状态 + */ + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OpLogs.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OpLogs.java new file mode 100644 index 0000000..4523de5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OpLogs.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 操作日志实体类 + *

+ * + * @author zmj + */ +@Data +@TableName("op_logs") +public class OpLogs extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 日志名称 + */ + private String name; + + /** + * 类别 + */ + private Integer logType; + + /** + * IP地址 + */ + private String ip; + + /** + * 补充信息 + */ + private String extra; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OrderTimeLine.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OrderTimeLine.java new file mode 100644 index 0000000..f6acb9d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/OrderTimeLine.java @@ -0,0 +1,65 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-07 + */ +@Data +@TableName("tbl_order_time_line") +public class OrderTimeLine extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "OrderTimeLine"; + + /** + * ID + */ + private String id; + + /** + * 订单ID + */ + private String orderId; + + /** + * 描述内容 + */ + private String content; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 业务类型 + */ + private Integer bizType; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/RecursionMapping.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/RecursionMapping.java new file mode 100644 index 0000000..0237290 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/RecursionMapping.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 递归映射 + *

+ * + * @author zmj + * @since 2021-06-27 + */ +@Data +@TableName("recursion_mapping") +public class RecursionMapping extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 节点ID + */ + private String nodeId; + + /** + * 节点类型 + */ + private Integer nodeType; + + /** + * 从顶点到当前结点的路径,用,分割 + */ + private String path; + + /** + * 节点层级 + */ + private Integer level; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SecurityUploadRecord.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SecurityUploadRecord.java new file mode 100644 index 0000000..bd7849c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SecurityUploadRecord.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.UploadType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 文件收纳箱 + *

+ */ +@Data +@TableName("tbl_security_upload_record") +public class SecurityUploadRecord extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 上传方式 + */ + private UploadType uploadType; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDic.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDic.java new file mode 100644 index 0000000..12c2c9d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDic.java @@ -0,0 +1,82 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 数据字典 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic") +public class SysDataDic extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDic"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicCategory.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicCategory.java new file mode 100644 index 0000000..bd7558c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicCategory.java @@ -0,0 +1,77 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 数据字典分类 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic_category") +public class SysDataDicCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDicCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicItem.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicItem.java new file mode 100644 index 0000000..67b55f8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataDicItem.java @@ -0,0 +1,87 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 数据字典值 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic_item") +public class SysDataDicItem extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDicItem"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 字典ID + */ + private String dicId; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionData.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionData.java new file mode 100644 index 0000000..fc39300 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionData.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionDataBizType; +import lombok.Data; + +/** + *

+ * 数据权限数据 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_permission_data") +public class SysDataPermissionData extends BaseEntity implements BaseDto { + + /** + * ID + */ + private String id; + + /** + * 业务ID + */ + private String bizId; + + /** + * 业务类型 + */ + private SysDataPermissionDataBizType bizType; + + /** + * 权限类型 + */ + private Integer permissionType; + + /** + * 权限 + */ + private String permission; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionModelDetail.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionModelDetail.java new file mode 100644 index 0000000..40359b1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDataPermissionModelDetail.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailInputType; +import lombok.Data; + +/** + *

+ * 数据权限模型明细 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_permission_model_detail") +public class SysDataPermissionModelDetail extends BaseEntity implements BaseDto { + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 模型ID + */ + private Integer modelId; + + /** + * 条件 + */ + private String conditionType; + + /** + * 输入类型 + */ + private SysDataPermissionModelDetailInputType inputType; + + /** + * 表名 + */ + private String tableName; + + /** + * 字段名 + */ + private String columnName; + + /** + * 前段枚举名 + */ + private String enumName; + + /** + * SQL + */ + private String sqlValue; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDept.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDept.java new file mode 100644 index 0000000..ed8267e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysDept.java @@ -0,0 +1,101 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 部门 + *

+ * + * @author zmj + * @since 2021-06-26 + */ +@Data +@TableName("sys_dept") +public class SysDept extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysDept"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * 父级ID + */ + @TableField + private String parentId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysGenerateCode.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysGenerateCode.java new file mode 100644 index 0000000..f96ec58 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysGenerateCode.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 编号规则 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_generate_code") +public class SysGenerateCode extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysGenerateCode"; + + private static final long serialVersionUID = 1L; + /** + * ID + */ + @TableId(value = "id", type = IdType.INPUT) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 配置信息(JSONArray) + */ + private String configStr; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMailMessage.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMailMessage.java new file mode 100644 index 0000000..cc28e50 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMailMessage.java @@ -0,0 +1,93 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.SysMailMessageSendStatus; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 邮件消息 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_mail_message") +public class SysMailMessage extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysMailMessage"; + + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 邮箱 + */ + private String mail; + + /** + * 业务键 + */ + private String bizKey; + + /** + * 发送状态 + */ + private SysMailMessageSendStatus sendStatus; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMenu.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMenu.java new file mode 100644 index 0000000..a95cfa2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysMenu.java @@ -0,0 +1,150 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.SysMenuComponentType; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统菜单 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +@Data +@TableName("sys_menu") +public class SysMenu extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysMenu"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称(前端使用) + */ + private String name; + + /** + * 标题 + */ + private String title; + + /** + * 图标 + */ + private String icon; + + /** + * 组件类型 + */ + private SysMenuComponentType componentType; + + /** + * 组件(前端使用) + */ + private String component; + + /** + * 自定义请求参数 + */ + private String requestParam; + + /** + * 父级ID + */ + private String parentId; + + /** + * 路由路径(前端使用) + */ + private String path; + + /** + * 是否缓存(前端使用) + */ + private Boolean noCache; + + /** + * 类型 0-目录 1-菜单 2-功能 + */ + private SysMenuDisplay display; + + /** + * 是否隐藏(前端使用) + */ + private Boolean hidden; + + /** + * 权限 + */ + private String permission; + + /** + * 是否特殊菜单 + */ + private Boolean isSpecial; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModule.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModule.java new file mode 100644 index 0000000..74b7cf2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModule.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统模块 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_module") +public class SysModule extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysModule"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 备注 + */ + private String description; + + /** + * 是否为平台功能模块 + */ + private Boolean isPlatform; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModuleTenant.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModuleTenant.java new file mode 100644 index 0000000..ffdaa84 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysModuleTenant.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 租户和系统模块关系表 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_module_tenant") +public class SysModuleTenant extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysModuleTenant"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 模块ID + */ + private Integer moduleId; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 过期时间 + */ + private LocalDateTime expireTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotice.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotice.java new file mode 100644 index 0000000..60e3257 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotice.java @@ -0,0 +1,101 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统通知 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notice") +public class SysNotice extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysNotice"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 状态 + */ + private Boolean available; + + /** + * 是否发布 + */ + private Boolean published; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 已读人数 + */ + private Integer readedNum; + + /** + * 未读人数 + */ + private Integer unReadNum; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNoticeLog.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNoticeLog.java new file mode 100644 index 0000000..b348246 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNoticeLog.java @@ -0,0 +1,48 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统通知记录 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notice_log") +public class SysNoticeLog extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysNoticeLog"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String noticeId; + + /** + * 用户ID + */ + private String userId; + + /** + * 是否已读 + */ + private Boolean readed; + + /** + * 已读时间 + */ + private LocalDateTime readTime; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroup.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroup.java new file mode 100644 index 0000000..21b6d88 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroup.java @@ -0,0 +1,93 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.SysNotifyReceiverType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 消息通知组 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notify_group") +public class SysNotifyGroup extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysNotifyGroup"; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 接收者类型 + */ + private SysNotifyReceiverType receiverType; + + /** + * 消息类型 + */ + private String messageType; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroupReceiver.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroupReceiver.java new file mode 100644 index 0000000..e6724c3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysNotifyGroupReceiver.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 消息通知组-接收者关系表 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notify_group_receiver") +public class SysNotifyGroupReceiver extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 消息通知组ID + */ + private String groupId; + + /** + * 接收者ID + */ + private String receiverId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysOpenDomain.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysOpenDomain.java new file mode 100644 index 0000000..67c29f3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysOpenDomain.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 开放域 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +@Data +@TableName("sys_open_domain") +public class SysOpenDomain extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysOpenDomain"; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private String id; + + /** + * 名称 + */ + private String name; + + /** + * API密钥 + */ + private String apiSecret; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysParameter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysParameter.java new file mode 100644 index 0000000..d9df019 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysParameter.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 系统参数 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_parameter") +public class SysParameter extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysParameter"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 键 + */ + private String pmKey; + + /** + * 值 + */ + private String pmValue; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRole.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRole.java new file mode 100644 index 0000000..4200766 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRole.java @@ -0,0 +1,98 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-02 + */ +@Data +@TableName("sys_role") +public class SysRole extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysRole"; + + /** + * ID + */ + private String id; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 权限 + */ + private String permission; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleCategory.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleCategory.java new file mode 100644 index 0000000..6038962 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleCategory.java @@ -0,0 +1,77 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 角色分类 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_role_category") +public class SysRoleCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysRoleCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleMenu.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleMenu.java new file mode 100644 index 0000000..4dfcb3e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysRoleMenu.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_role_menu") +public class SysRoleMenu extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 角色ID + */ + private String roleId; + + /** + * 菜单ID + */ + private String menuId; + + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysSiteMessage.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysSiteMessage.java new file mode 100644 index 0000000..a393b5e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysSiteMessage.java @@ -0,0 +1,97 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 站内信 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_site_message") +public class SysSiteMessage extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysSiteMessage"; + + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 接收人ID + */ + private String receiverId; + + /** + * 业务键 + */ + private String bizKey; + + /** + * 是否已读 + */ + private Boolean readed; + + /** + * 已读时间 + */ + private LocalDateTime readTime; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUser.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUser.java new file mode 100644 index 0000000..32b2b6d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUser.java @@ -0,0 +1,119 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import com.lframework.starter.web.inner.enums.system.Gender; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user") +public class SysUser extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysUser"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 姓名 + */ + private String name; + + /** + * 用户名 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 邮箱 + */ + private String email; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 性别 0-未知 1-男 2-女 + */ + private Gender gender; + + /** + * 状态 1-在用 0停用 + */ + private Boolean available; + + /** + * 锁定状态 + */ + private Boolean lockStatus; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserDept.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserDept.java new file mode 100644 index 0000000..51f4028 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserDept.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user_dept") +public class SysUserDept extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysUserDept"; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 部门ID + */ + private String deptId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroup.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroup.java new file mode 100644 index 0000000..6c10c8f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroup.java @@ -0,0 +1,87 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 用户组 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_user_group") +public class SysUserGroup extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysUserGroup"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroupDetail.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroupDetail.java new file mode 100644 index 0000000..31ff3e9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserGroupDetail.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + */ +@Data +@TableName("sys_user_group_detail") +public class SysUserGroupDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 用户组ID + */ + private String groupId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserRole.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserRole.java new file mode 100644 index 0000000..6fbfcfa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserRole.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user_role") +public class SysUserRole extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 角色ID + */ + private String roleId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserTelephone.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserTelephone.java new file mode 100644 index 0000000..54766d7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/SysUserTelephone.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +@Data +@TableName("sys_user_telephone") +public class SysUserTelephone extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 手机号 + */ + private String telephone; + + /** + * 用户ID + */ + private String userId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/entity/Tenant.java b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/Tenant.java new file mode 100644 index 0000000..494fe93 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/entity/Tenant.java @@ -0,0 +1,78 @@ +package com.lframework.starter.web.inner.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.entity.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 租户 + *

+ * + * @author zmj + * @since 2023-03-05 + */ +@Data +@TableName("tenant") +public class Tenant extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "Tenant"; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * JdbcUrl + */ + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + private String jdbcUsername; + + /** + * Jdbc密码 + */ + private String jdbcPassword; + + /** + * 域名 + */ + private String serverName; + + /** + * 是否为平台管理租户 + */ + private Boolean isPlatform; + + /** + * 状态 + */ + private Boolean available; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Available.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Available.java new file mode 100644 index 0000000..277617a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Available.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum Available implements BaseEnum { + ENABLE(Boolean.TRUE, "启用"), UNABLE(Boolean.FALSE, "停用"); + + + @EnumValue + private final Boolean code; + + private final String desc; + + Available(Boolean code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Boolean getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Gender.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Gender.java new file mode 100644 index 0000000..5708045 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/Gender.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum Gender implements BaseEnum { + UNKNOWN(0, "未知"), MAN(1, "男"), FEMALE(2, "女"); + + @EnumValue + private final Integer code; + + private final String desc; + + Gender(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/NodeType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/NodeType.java new file mode 100644 index 0000000..79759b2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/NodeType.java @@ -0,0 +1,7 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.lframework.starter.web.core.enums.BaseEnum; + +public interface NodeType extends BaseEnum { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/QrtzJobType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/QrtzJobType.java new file mode 100644 index 0000000..cd00bb8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/QrtzJobType.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +/** + * @author zmj + * @since 2022/8/20 + */ +public enum QrtzJobType implements BaseEnum { + EXCUTE_CLASS(1, "指定类"), + GROOVY(2, "Groovy脚本"); + + @EnumValue + private final Integer code; + + private final String desc; + + QrtzJobType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionDataBizType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionDataBizType.java new file mode 100644 index 0000000..40d7f41 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionDataBizType.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysDataPermissionDataBizType implements BaseEnum { + ROLE(0, "角色"), DEPT(1, "部门"), USER(2, "用户"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionDataBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailCalcType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailCalcType.java new file mode 100644 index 0000000..fab65b9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailCalcType.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysDataPermissionModelDetailCalcType implements BaseEnum { + + AND(1, "AND", "并且"), OR(2, "OR", "或者"); + + @EnumValue + private final Integer code; + + private String operation; + + private final String desc; + + SysDataPermissionModelDetailCalcType(Integer code, String operation, String desc) { + + this.code = code; + this.operation = operation; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public String getOperation() { + return operation; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailConditionType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailConditionType.java new file mode 100644 index 0000000..7f6d27d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailConditionType.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysDataPermissionModelDetailConditionType implements BaseEnum { + + EQ(0, "=", "等于"), GT(1, ">", "大于"), GE(2, ">=", "大于或等于"), LT(3, "<", "小于"), LE(4, "<=", + "小于或等于"), NE(5, + "!=", "不等于"), IN(6, "IN", "在列表中"), NOT_IN(7, + "NOT IN", "不在列表中"), LEFT_LIKE(8, "LIKE", "结尾"), RIGHT_LIKE(9, "LIKE", + "开头"), AROUND_LIKE(10, "LIKE", "包含"); + + @EnumValue + private final Integer code; + + private final String operation; + + private final String desc; + + SysDataPermissionModelDetailConditionType(Integer code, String operation, String desc) { + + this.code = code; + this.operation = operation; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public String getOperation() { + return operation; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailInputType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailInputType.java new file mode 100644 index 0000000..56000fa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailInputType.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysDataPermissionModelDetailInputType implements BaseEnum { + + INPUT(0, "输入框"), SELECT(1, "选择器"), DATE_TIME(2, "日期时间选择器"), DATE(3, + "日期选择器"), SQL(99, "SQL"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionModelDetailInputType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailNodeType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailNodeType.java new file mode 100644 index 0000000..1e4f417 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDataPermissionModelDetailNodeType.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysDataPermissionModelDetailNodeType implements BaseEnum { + + CALC(1, "运算节点"), CONDITION(2, "条件节点"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionModelDetailNodeType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDeptNodeType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDeptNodeType.java new file mode 100644 index 0000000..43bd2e9 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysDeptNodeType.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.inner.enums.system; + +import java.io.Serializable; + +public final class SysDeptNodeType implements NodeType, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public Integer getCode() { + + return 1; + } + + @Override + public String getDesc() { + + return "部门"; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMailMessageSendStatus.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMailMessageSendStatus.java new file mode 100644 index 0000000..d52666b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMailMessageSendStatus.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysMailMessageSendStatus implements BaseEnum { + + UN_SEND(0, "待发送"), SENDING(1, "发送中"), SENDED(2, "已发送"), FAIL(9, "发送失败"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysMailMessageSendStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuComponentType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuComponentType.java new file mode 100644 index 0000000..52ddaaa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuComponentType.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysMenuComponentType implements BaseEnum { + + NORMAL(0, "普通"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysMenuComponentType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuDisplay.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuDisplay.java new file mode 100644 index 0000000..8b2f17f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysMenuDisplay.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysMenuDisplay implements BaseEnum { + + CATALOG(0, "目录"), FUNCTION(1, "菜单"), PERMISSION(2, "权限"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysMenuDisplay(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyMessageType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyMessageType.java new file mode 100644 index 0000000..8489fb7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyMessageType.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysNotifyMessageType implements BaseEnum { + + SYS(0, "站内信"), EMAIL(1, "邮件"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysNotifyMessageType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyReceiverType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyReceiverType.java new file mode 100644 index 0000000..00bfb14 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/SysNotifyReceiverType.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum SysNotifyReceiverType implements BaseEnum { + + DEPT(0, "部门及其子部门"), USER(1, "用户"), ROLE(2, "角色"), USER_GROUP(3, "用户组"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysNotifyReceiverType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/TriggerState.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/TriggerState.java new file mode 100644 index 0000000..bf8a7f7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/TriggerState.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum TriggerState implements BaseEnum { + WAITING("WAITING", "等待执行"), + PAUSED("PAUSED", "暂停执行"), + ACQUIRED("ACQUIRED", "正常执行"), + BLOCKED("BLOCKED", "阻塞"), + ERROR("ERROR", "执行错误"), + COMPLETE("COMPLETE", "执行完毕"), + PAUSED_BLOCKED("PAUSED_BLOCKED", "阻塞暂停"); + + @EnumValue + private final String code; + + private final String desc; + + TriggerState(String code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/UploadType.java b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/UploadType.java new file mode 100644 index 0000000..2a279e4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/enums/system/UploadType.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.core.enums.BaseEnum; + +public enum UploadType implements BaseEnum { + LOCAL("LOCAL", "本地"), + OSS("OSS", "阿里云OSS"), + COS("COS", "腾讯云COS"), + OBS("OBS", "华为云OBS"); + + @EnumValue + private final String code; + + private final String desc; + + UploadType(String code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysDeptEvent.java b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysDeptEvent.java new file mode 100644 index 0000000..066f31e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysDeptEvent.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.events.system; + +import com.lframework.starter.web.core.event.DataChangeEvent; +import com.lframework.starter.web.core.event.DataChangeType; +import com.lframework.starter.web.inner.entity.SysDept; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DeleteSysDeptEvent extends DataChangeEvent { + + public DeleteSysDeptEvent(Object source, SysDept entity, + DataChangeType type) { + super(source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysNotifyGroupEvent.java b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysNotifyGroupEvent.java new file mode 100644 index 0000000..36fb892 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysNotifyGroupEvent.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.events.system; + +import com.lframework.starter.web.core.event.DataChangeEvent; +import com.lframework.starter.web.core.event.DataChangeType; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DeleteSysNotifyGroupEvent extends DataChangeEvent { + + public DeleteSysNotifyGroupEvent(Object source, SysNotifyGroup entity, + DataChangeType type) { + super(source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysRoleEvent.java b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysRoleEvent.java new file mode 100644 index 0000000..1cdebfe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysRoleEvent.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.events.system; + +import com.lframework.starter.web.core.event.DataChangeEvent; +import com.lframework.starter.web.core.event.DataChangeType; +import com.lframework.starter.web.inner.entity.SysRole; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DeleteSysRoleEvent extends DataChangeEvent { + + public DeleteSysRoleEvent(Object source, SysRole entity, + DataChangeType type) { + super(source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserEvent.java b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserEvent.java new file mode 100644 index 0000000..dc4fecc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserEvent.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.events.system; + +import com.lframework.starter.web.core.event.DataChangeEvent; +import com.lframework.starter.web.core.event.DataChangeType; +import com.lframework.starter.web.inner.entity.SysUser; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DeleteSysUserEvent extends DataChangeEvent { + + public DeleteSysUserEvent(Object source, SysUser entity, + DataChangeType type) { + super(source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserGroupEvent.java b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserGroupEvent.java new file mode 100644 index 0000000..1f4660f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/events/system/DeleteSysUserGroupEvent.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.events.system; + +import com.lframework.starter.web.core.event.DataChangeEvent; +import com.lframework.starter.web.core.event.DataChangeType; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DeleteSysUserGroupEvent extends DataChangeEvent { + + public DeleteSysUserGroupEvent(Object source, SysUserGroup entity, + DataChangeType type) { + super(source, entity, type); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/AccessDeniedExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/AccessDeniedExceptionConverter.java new file mode 100644 index 0000000..4985546 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/AccessDeniedExceptionConverter.java @@ -0,0 +1,22 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.AccessDeniedException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; + +/** + * 处理无权限异常 + */ +public class AccessDeniedExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof AccessDeniedException; + } + + @Override + public BaseException convert(Throwable e) { + return new AccessDeniedException(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/BindExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/BindExceptionConverter.java new file mode 100644 index 0000000..48e226c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/BindExceptionConverter.java @@ -0,0 +1,57 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; + +/** + * 处理由于传入方式错误导致的异常 + */ +public class BindExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof BindException; + } + + @Override + public BaseException convert(Throwable e) { + + BindException ex = (BindException) e; + if (ex.getErrorCount() > 0) { + ObjectError objectError = ex.getAllErrors().get(0); + + if (objectError instanceof FieldError && "typeMismatch".equals(objectError.getCode())) { + String fieldName = ((FieldError) objectError).getField(); + + Class targetClazz = ex.getBindingResult().getTarget().getClass(); + + TypeMismatch typeMismatch = null; + try { + typeMismatch = targetClazz.getDeclaredField(fieldName).getAnnotation(TypeMismatch.class); + } catch (NoSuchFieldException exp) { + throw new DefaultSysException(exp.getMessage()); + } + if (typeMismatch != null) { + return new InputErrorException(typeMismatch.message()); + } + } + } + for (ObjectError error : ex.getAllErrors()) { + return new InputErrorException(error.getDefaultMessage()); + } + + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ClientExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ClientExceptionConverter.java new file mode 100644 index 0000000..347ffcc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ClientExceptionConverter.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; + +/** + * 处理系统异常 + */ +public class ClientExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof ClientException; + } + + @Override + public BaseException convert(Throwable e) { + return (ClientException) e; + } + + @Override + public int getOrder() { + return SECOND_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ConstraintViolationExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ConstraintViolationExceptionConverter.java new file mode 100644 index 0000000..b80bb1a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ConstraintViolationExceptionConverter.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +public class ConstraintViolationExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof ConstraintViolationException; + } + + @Override + public BaseException convert(Throwable e) { + ConstraintViolationException ex = (ConstraintViolationException) e; + for (ConstraintViolation constraintViolation : ex.getConstraintViolations()) { + return new InputErrorException(constraintViolation.getMessage()); + } + + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ExceptionConverter.java new file mode 100644 index 0000000..d6852fe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/ExceptionConverter.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; + +public class ExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof Exception; + } + + @Override + public BaseException convert(Throwable e) { + return new DefaultSysException(); + } + + @Override + public int getOrder() { + return LAST_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/FileUploadExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/FileUploadExceptionConverter.java new file mode 100644 index 0000000..656e45b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/FileUploadExceptionConverter.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.apache.tomcat.util.http.fileupload.FileUploadException; + +public class FileUploadExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof FileUploadException; + } + + @Override + public BaseException convert(Throwable e) { + return new DefaultClientException("文件上传失败!"); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpMessageNotReadableExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpMessageNotReadableExceptionConverter.java new file mode 100644 index 0000000..6c6ad06 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpMessageNotReadableExceptionConverter.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; + +/** + * 处理由于传入参数类型不匹配导致的异常 + */ +public class HttpMessageNotReadableExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof HttpMessageNotReadableException; + } + + @Override + public BaseException convert(Throwable e) { + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpRequestMethodNotSupportedExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpRequestMethodNotSupportedExceptionConverter.java new file mode 100644 index 0000000..dff90a0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/HttpRequestMethodNotSupportedExceptionConverter.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.springframework.web.HttpRequestMethodNotSupportedException; + +/** + * 处理由于传入方式错误导致的异常 + */ +public class HttpRequestMethodNotSupportedExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof HttpRequestMethodNotSupportedException; + } + + @Override + public BaseException convert(Throwable e) { + return new DefaultSysException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/MethodArgumentNotValidExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/MethodArgumentNotValidExceptionConverter.java new file mode 100644 index 0000000..a16c10f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/MethodArgumentNotValidExceptionConverter.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; + +public class MethodArgumentNotValidExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof MethodArgumentNotValidException; + } + + @Override + public BaseException convert(Throwable e) { + MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e; + for (ObjectError error : ex.getBindingResult().getAllErrors()) { + return new InputErrorException(error.getDefaultMessage()); + } + + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/NotPermissionExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/NotPermissionExceptionConverter.java new file mode 100644 index 0000000..7e21044 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/NotPermissionExceptionConverter.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import cn.dev33.satoken.exception.NotPermissionException; +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.AccessDeniedException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; + +/** + * 处理无权限异常 + */ +public class NotPermissionExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof NotPermissionException; + } + + @Override + public BaseException convert(Throwable e) { + return new AccessDeniedException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/SysExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/SysExceptionConverter.java new file mode 100644 index 0000000..820d760 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/SysExceptionConverter.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.SysException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; + +/** + * 处理系统异常 + */ +public class SysExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof SysException; + } + + @Override + public BaseException convert(Throwable e) { + return new DefaultSysException(); + } + + @Override + public int getOrder() { + return SECOND_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/TypeMismatchExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/TypeMismatchExceptionConverter.java new file mode 100644 index 0000000..43a56da --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/TypeMismatchExceptionConverter.java @@ -0,0 +1,47 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import org.springframework.beans.TypeMismatchException; +import org.springframework.core.MethodParameter; +import org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +/** + * 处理由于传入参数类型不匹配导致的异常 + */ +public class TypeMismatchExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof TypeMismatchException; + } + + @Override + public BaseException convert(Throwable e) { + MethodParameter methodParameter = null; + if (e instanceof MethodArgumentConversionNotSupportedException) { + methodParameter = ((MethodArgumentConversionNotSupportedException) e).getParameter(); + } else if (e instanceof MethodArgumentTypeMismatchException) { + methodParameter = ((MethodArgumentTypeMismatchException) e).getParameter(); + } + + if (methodParameter != null) { + TypeMismatch typeMismatch = methodParameter.getMethod() + .getParameters()[methodParameter.getParameterIndex()].getAnnotation(TypeMismatch.class); + if (typeMismatch != null) { + return new InputErrorException(typeMismatch.message()); + } + } + + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/UnexpectedTypeExceptionConverter.java b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/UnexpectedTypeExceptionConverter.java new file mode 100644 index 0000000..fc34d87 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/handlers/exception/UnexpectedTypeExceptionConverter.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.handlers.exception; + + +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.core.handlers.exception.WebExceptionConverter; +import jakarta.validation.UnexpectedTypeException; + +/** + * 处理传入参数类型转换错误异常 + */ +public class UnexpectedTypeExceptionConverter implements WebExceptionConverter { + + @Override + public boolean isMatch(Throwable e) { + return e instanceof UnexpectedTypeException; + } + + @Override + public BaseException convert(Throwable e) { + + return new InputErrorException(); + } + + @Override + public int getOrder() { + return THIRD_ORDER; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DefaultUserDetailsService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DefaultUserDetailsService.java new file mode 100644 index 0000000..c5f8374 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DefaultUserDetailsService.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.impl; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.AbstractUserDetailsService; +import com.lframework.starter.web.inner.mappers.UserDetailsMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * UserDetaisService默认实现 + * + * @author zmj + */ +@Service +public class DefaultUserDetailsService extends AbstractUserDetailsService { + + @Autowired + private UserDetailsMapper userDetailsMapper; + + @Override + public AbstractUserDetails findByUsername(String username) { + + AbstractUserDetails user = userDetailsMapper.findByUsername(username); + + return user; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DicCityServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DicCityServiceImpl.java new file mode 100644 index 0000000..4c2d4fa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/DicCityServiceImpl.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.inner.impl; + +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.dto.dic.city.DicCityDto; +import com.lframework.starter.web.inner.entity.DicCity; +import com.lframework.starter.web.inner.mappers.DicCityMapper; +import com.lframework.starter.web.inner.service.DicCityService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Service +public class DicCityServiceImpl extends BaseMpServiceImpl implements + DicCityService { + + @Cacheable(value = DicCityDto.SELECTOR_CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List getAll() { + + return getBaseMapper().getAll(); + } + + @Cacheable(value = DicCityDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public DicCityDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Override + public List getChainById(String id) { + + DicCityService thisService = getThis(this.getClass()); + List all = thisService.getAll(); + List results = new ArrayList<>(); + DicCityDto current = all.stream().filter(t -> t.getId().equals(id)).findFirst().orElse(null); + if (current == null) { + return results; + } + + while (current != null) { + results.add(current); + + String pId = current.getParentId(); + current = all.stream().filter(t -> t.getId().equals(pId)).findFirst().orElse(null); + } + + Collections.reverse(results); + + return results; + } + + @CacheEvict(value = DicCityDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/GenerateCodeServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/GenerateCodeServiceImpl.java new file mode 100644 index 0000000..39b7c6b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/GenerateCodeServiceImpl.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.impl; + +import com.lframework.starter.web.core.components.generator.GenerateCodeFactory; +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.dto.GenerateCodeDto; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.inner.mappers.GenerateCodeMapper; +import com.lframework.starter.web.inner.service.GenerateCodeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class GenerateCodeServiceImpl implements GenerateCodeService { + + @Autowired + private GenerateCodeMapper generateCodeMapper; + + @Override + public String generate(Integer id) { + GenerateCodeDto sysGenerateCode = generateCodeMapper.findById(id); + + GenerateCodeService thisService = ApplicationUtil.getBean(this.getClass()); + List ruleList = thisService.getRules(sysGenerateCode); + + return GenerateCodeFactory.generate(ruleList); + } + + @Cacheable(value = GenerateCodeDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #entity.id", unless = "#result == null") + @Override + public List getRules(GenerateCodeDto entity) { + return GenerateCodeFactory.getRules(entity.getConfigStr()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/MailServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/MailServiceImpl.java new file mode 100644 index 0000000..09e8c9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/MailServiceImpl.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.inner.impl; + +import cn.hutool.extra.mail.MailAccount; +import com.lframework.starter.common.utils.MailUtil; +import com.lframework.starter.web.inner.service.MailService; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +@Slf4j +public class MailServiceImpl implements MailService { + + private MailAccount account; + + public MailServiceImpl(MailAccount account) { + + this.account = account; + } + + @Override + public String send(String to, String subject, String content) { + + return this.send(Collections.singletonList(to), subject, content, false, null); + } + + @Override + public String send(String to, String subject, String content, boolean isHtml) { + + return this.send(Collections.singletonList(to), subject, content, isHtml, null); + } + + @Override + public String send(String to, String subject, String content, boolean isHtml, File... files) { + + return this.send(Collections.singletonList(to), subject, content, isHtml, files); + } + + @Override + public String send(List tos, String subject, String content) { + + return this.send(tos, subject, content, false, null); + } + + @Override + public String send(List tos, String subject, String content, boolean isHtml) { + + return this.send(tos, subject, content, isHtml, null); + } + + @Override + public String send(List tos, String subject, String content, boolean isHtml, + File... files) { + + log.info("开始发送邮件"); + if (log.isDebugEnabled()) { + log.debug("收件人={}, 标题={}, 内容={}, isHtml={}, files={}", tos, subject, content, isHtml, files); + } + + return MailUtil.send(this.account, tos, subject, content, isHtml, files); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OpLogsServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OpLogsServiceImpl.java new file mode 100644 index 0000000..2292a90 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OpLogsServiceImpl.java @@ -0,0 +1,121 @@ +package com.lframework.starter.web.inner.impl; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.OpLogs; +import com.lframework.starter.web.inner.mappers.OpLogsMapper; +import com.lframework.starter.web.inner.service.OpLogsService; +import com.lframework.starter.web.inner.vo.oplogs.CreateOpLogsVo; +import com.lframework.starter.web.inner.vo.oplogs.QueryOpLogsVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 操作日志Service实现 + * + * @author zmj + */ +@Slf4j +@Service +public class OpLogsServiceImpl extends BaseMpServiceImpl + implements OpLogsService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateOpLogsVo vo) { + + OpLogs record = this.doCreate(vo); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(Collection list) { + if (CollectionUtil.isEmpty(list)) { + return; + } + List records = list.stream().map(this::doCreate).collect(Collectors.toList()); + this.saveBatch(records); + } + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryOpLogsVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doQuery(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public OpLogs findById(String id) { + + return this.doGetById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void clearLogs(LocalDateTime endTime) { + + log.info("开始清除创建时间早于{}的操作日志", endTime); + + this.doClearLogs(endTime); + } + + protected OpLogs doCreate(CreateOpLogsVo vo) { + + OpLogs record = new OpLogs(); + record.setId(IdUtil.getId()); + record.setName(vo.getName()); + record.setLogType(vo.getLogType()); + if (!StringUtil.isBlank(vo.getCreateBy())) { + record.setCreateBy(vo.getCreateBy()); + } + + if (!StringUtil.isBlank(vo.getCreateById())) { + record.setCreateById(vo.getCreateById()); + } + + if (!StringUtil.isBlank(vo.getExtra())) { + record.setExtra(vo.getExtra()); + } + record.setIp(vo.getIp()); + + return record; + } + + protected List doQuery(QueryOpLogsVo vo) { + + return getBaseMapper().query(vo); + } + + protected OpLogs doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doClearLogs(LocalDateTime endTime) { + + getBaseMapper().clearLogs(endTime); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OrderTimeLineServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OrderTimeLineServiceImpl.java new file mode 100644 index 0000000..f8925dc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/OrderTimeLineServiceImpl.java @@ -0,0 +1,46 @@ +package com.lframework.starter.web.inner.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.OrderTimeLine; +import com.lframework.starter.web.inner.mappers.OrderTimeLineMapper; +import com.lframework.starter.web.inner.service.OrderTimeLineService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +/** + * @author zmj + * @since 2022/8/10 + */ +@Service +public class OrderTimeLineServiceImpl extends + BaseMpServiceImpl implements + OrderTimeLineService { + + @Cacheable(value = OrderTimeLine.CACHE_NAME, key = "@cacheVariables.tenantId() + #orderId", unless = "#result == null") + @Override + public List getByOrder(String orderId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(OrderTimeLine.class).eq(OrderTimeLine::getOrderId, orderId).orderByAsc(OrderTimeLine::getCreateTime); + + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByOrder(String orderId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(OrderTimeLine.class).eq(OrderTimeLine::getOrderId, orderId); + this.remove(deleteWrapper); + } + + @CacheEvict(value = OrderTimeLine.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + super.cleanCacheByKey(key); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/QrtzServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/QrtzServiceImpl.java new file mode 100644 index 0000000..b9826fa --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/QrtzServiceImpl.java @@ -0,0 +1,202 @@ +package com.lframework.starter.web.inner.impl; + +import cn.hutool.core.exceptions.UtilException; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.qrtz.DynamicQrtzJob; +import com.lframework.starter.web.core.components.qrtz.QrtzHandler; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.inner.enums.system.QrtzJobType; +import com.lframework.starter.web.inner.mappers.QrtzMapper; +import com.lframework.starter.web.inner.service.QrtzService; +import com.lframework.starter.web.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.UpdateQrtzVo; +import lombok.extern.slf4j.Slf4j; +import org.quartz.JobDetail; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Slf4j +@DS("master") +@Service +public class QrtzServiceImpl implements QrtzService { + + @Autowired + private QrtzMapper qrtzMapper; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryQrtzVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + vo.setJobClasses(new ArrayList<>()); + vo.getJobClasses().add(DynamicQrtzJob.class.getName()); + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = qrtzMapper.query(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + datas.stream().forEach(this::renderDto); + + return pageResult; + } + + @Override + public QrtzDto findById(String name, String group) { + QrtzDto data = qrtzMapper.findById(name, group); + if (data == null) { + return null; + } + + return renderDto(data); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(CreateQrtzVo vo) { + JobDetail jobDetail = QrtzHandler.getJob(vo.getName(), vo.getGroup()); + if (jobDetail != null) { + throw new DefaultClientException("名称、组不允许重复,请重新输入!"); + } + QrtzJobType jobType = EnumUtil.getByCode(QrtzJobType.class, vo.getJobType()); + if (jobType == QrtzJobType.EXCUTE_CLASS) { + if (StringUtil.isBlank(vo.getTargetClassName())) { + throw new DefaultClientException("类名不能为空!"); + } + if (StringUtil.isBlank(vo.getTargetMethodName())) { + throw new DefaultClientException("方法名不能为空!"); + } + + if (!CollectionUtil.isEmpty(vo.getTargetParamTypes()) || !CollectionUtil.isEmpty( + vo.getTargetParams())) { + int typeSize = vo.getTargetParamTypes() == null ? 0 : vo.getTargetParamTypes().size(); + int paramSize = vo.getTargetParams() == null ? 0 : vo.getTargetParams().size(); + if (typeSize != paramSize) { + throw new DefaultClientException("参数类型与参数数量不匹配!"); + } + } + try { + Class clazz = Class.forName(vo.getTargetClassName()); + ReflectUtil.newInstance(clazz); + Class[] paramTypes = null; + if (!CollectionUtil.isEmpty(vo.getTargetParamTypes())) { + paramTypes = new Class[vo.getTargetParamTypes().size()]; + for (int i = 0; i < vo.getTargetParamTypes().size(); i++) { + String targetParamType = vo.getTargetParamTypes().get(i); + try { + paramTypes[i] = Class.forName(targetParamType); + } catch (ClassNotFoundException e) { + throw new DefaultClientException( + "参数类型:" + targetParamType + "不存在,需要输入类型全名称,如:java.lang.String,请检查!"); + } + } + } + // 验证一下参数 + ReflectUtil.getMethod(clazz, vo.getTargetMethodName(), paramTypes); + + Map jobDataMap = new HashMap<>(); + jobDataMap.put("targetClassName", vo.getTargetClassName()); + jobDataMap.put("targetMethodName", vo.getTargetMethodName()); + jobDataMap.put("targetParamTypes", vo.getTargetParamTypes()); + jobDataMap.put("targetParams", vo.getTargetParams()); + jobDataMap.put("jobType", vo.getJobType()); + if (vo.getTenantId() != null) { + jobDataMap.put(StringPool.TENANT_ID_QRTZ, vo.getTenantId()); + } + + QrtzHandler.addJob(vo.getName(), vo.getGroup(), DynamicQrtzJob.class, + "custom_trigger_" + vo.getName(), vo.getGroup(), vo.getCron(), jobDataMap, + vo.getDescription()); + } catch (ClassNotFoundException e) { + throw new DefaultClientException("类:" + vo.getTargetClassName() + "不存在,请检查!"); + } catch (UtilException e) { + throw new DefaultClientException("类:" + vo.getTargetClassName() + "无法加载,请检查!"); + } + } else { + Map jobDataMap = new HashMap<>(); + jobDataMap.put("script", vo.getScript()); + jobDataMap.put("jobType", vo.getJobType()); + if (vo.getTenantId() != null) { + jobDataMap.put(StringPool.TENANT_ID_QRTZ, vo.getTenantId()); + } + + QrtzHandler.addJob(vo.getName(), vo.getGroup(), DynamicQrtzJob.class, + "custom_trigger_" + vo.getName(), vo.getGroup(), vo.getCron(), jobDataMap, + vo.getDescription()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateQrtzVo vo) { + JobDetail jobDetail = QrtzHandler.getJob(vo.getOriName(), vo.getOriGroup()); + if (jobDetail == null) { + throw new DefaultClientException("任务不存在!"); + } + + this.delete(vo.getOriName(), vo.getOriGroup()); + + this.create(vo); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void resume(String name, String group) { + QrtzHandler.resume(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void pause(String name, String group) { + QrtzHandler.pause(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void trigger(String name, String group) { + QrtzHandler.trigger(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(String name, String group) { + + QrtzHandler.deleteJob(name, group, "custom_trigger_" + name, group); + } + + private QrtzDto renderDto(QrtzDto data) { + JobDetail jobDetail = QrtzHandler.getJob(data.getName(), data.getGroup()); + Integer jobType = jobDetail.getJobDataMap().getIntValue("jobType"); + data.setJobType(EnumUtil.getByCode(QrtzJobType.class, jobType)); + data.setTargetClassName(jobDetail.getJobDataMap().getString("targetClassName")); + data.setTargetMethodName(jobDetail.getJobDataMap().getString("targetMethodName")); + data.setTargetParamTypes((List) jobDetail.getJobDataMap().get("targetParamTypes")); + data.setTargetParams((List) jobDetail.getJobDataMap().get("targetParams")); + data.setScript(jobDetail.getJobDataMap().getString("script")); + Object tenantStr = jobDetail.getJobDataMap().get(StringPool.TENANT_ID_QRTZ); + data.setTenantId(tenantStr == null ? null : Integer.valueOf(String.valueOf(tenantStr))); + + return data; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/RecursionMappingServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/RecursionMappingServiceImpl.java new file mode 100644 index 0000000..e13d288 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/RecursionMappingServiceImpl.java @@ -0,0 +1,113 @@ +package com.lframework.starter.web.inner.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.entity.RecursionMapping; +import com.lframework.starter.web.inner.enums.system.NodeType; +import com.lframework.starter.web.inner.mappers.RecursionMappingMapper; +import com.lframework.starter.web.inner.service.RecursionMappingService; +import lombok.NonNull; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class RecursionMappingServiceImpl extends + BaseMpServiceImpl + implements RecursionMappingService { + + @Override + public List getNodeParentIds(@NonNull String nodeId, + @NonNull Class nodeTypeClazz) { + + if (StringUtil.isEmpty(nodeId)) { + return CollectionUtil.emptyList(); + } + + NodeType nodeType = ApplicationUtil.getBean(nodeTypeClazz); + Wrapper queryWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + + RecursionMapping recursionMappings = getBaseMapper().selectOne(queryWrapper); + if (recursionMappings == null || StringUtil.isEmpty(recursionMappings.getPath())) { + return CollectionUtil.emptyList(); + } + + return StringUtil.split(recursionMappings.getPath(), StringPool.STR_SPLIT); + } + + @Override + public List getNodeChildIds(String nodeId, Class nodeTypeClazz) { + + NodeType nodeType = ApplicationUtil.getBean(nodeTypeClazz); + return getBaseMapper().getNodeChildIds(nodeId, nodeType.getCode()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveNode(String nodeId, Class nodeTypeClazz) { + + this.saveNode(nodeId, nodeTypeClazz, null); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteNode(String nodeId, Class nodeTypeClazz) { + + NodeType nodeType = ApplicationUtil.getBean(nodeTypeClazz); + + Wrapper deleteWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + getBaseMapper().delete(deleteWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteNodeAndChildren(String nodeId, Class nodeTypeClazz) { + NodeType nodeType = ApplicationUtil.getBean(nodeTypeClazz); + List childNodeIds = this.getNodeChildIds(nodeId, nodeTypeClazz); + List allNodeIds = new ArrayList<>(); + allNodeIds.add(nodeId); + allNodeIds.addAll(childNodeIds); + Wrapper deleteWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .in(RecursionMapping::getNodeId, allNodeIds) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + getBaseMapper().delete(deleteWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveNode(@NonNull String nodeId, @NonNull Class nodeTypeClazz, List parentIds) { + + NodeType nodeType = ApplicationUtil.getBean(nodeTypeClazz); + Wrapper queryWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + RecursionMapping data = getBaseMapper().selectOne(queryWrapper); + if(data == null) { + data = new RecursionMapping(); + data.setId(IdUtil.getId()); + data.setNodeId(nodeId); + data.setNodeType(nodeType.getCode()); + } + + data.setLevel(1); + data.setPath(StringPool.EMPTY_STR); + if (!CollectionUtil.isEmpty(parentIds)) { + data.setPath(StringUtil.join(StringPool.STR_SPLIT, parentIds)); + data.setLevel(parentIds.size() + 1); + } + + getBaseMapper().insert(data); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SecurityUploadRecordServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SecurityUploadRecordServiceImpl.java new file mode 100644 index 0000000..f74bb4a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SecurityUploadRecordServiceImpl.java @@ -0,0 +1,30 @@ +package com.lframework.starter.web.inner.impl; + +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.entity.SecurityUploadRecord; +import com.lframework.starter.web.inner.enums.system.UploadType; +import com.lframework.starter.web.inner.mappers.SecurityUploadRecordMapper; +import com.lframework.starter.web.inner.service.SecurityUploadRecordService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SecurityUploadRecordServiceImpl extends + BaseMpServiceImpl implements + SecurityUploadRecordService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(String uploadType, String filePath) { + SecurityUploadRecord uploadRecord = new SecurityUploadRecord(); + uploadRecord.setId(IdUtil.getId()); + uploadRecord.setUploadType(EnumUtil.getByCode(UploadType.class, uploadType)); + uploadRecord.setFilePath(filePath); + + this.save(uploadRecord); + + return uploadRecord.getId(); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleServiceImpl.java new file mode 100644 index 0000000..bafaac1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleServiceImpl.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysModule; +import com.lframework.starter.web.inner.mappers.SysModuleMapper; +import com.lframework.starter.web.inner.service.SysModuleService; +import org.springframework.stereotype.Service; + +@DS("master") +@Service +public class SysModuleServiceImpl extends BaseMpServiceImpl implements + SysModuleService { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleTenantServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleTenantServiceImpl.java new file mode 100644 index 0000000..9ac83cd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/SysModuleTenantServiceImpl.java @@ -0,0 +1,94 @@ +package com.lframework.starter.web.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.entity.SysModule; +import com.lframework.starter.web.inner.entity.SysModuleTenant; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.mappers.SysModuleTenantMapper; +import com.lframework.starter.web.inner.service.SysModuleService; +import com.lframework.starter.web.inner.service.SysModuleTenantService; +import com.lframework.starter.web.inner.service.TenantService; +import com.lframework.starter.web.inner.vo.system.module.SysModuleTenantVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; + +@DS("master") +@Service +public class SysModuleTenantServiceImpl extends + BaseMpServiceImpl implements SysModuleTenantService { + + @Autowired + private TenantService tenantService; + + @Autowired + private SysModuleService sysModuleService; + + @Override + public List getAvailableModuleIdsByTenantId(Integer tenantId) { + SysModuleTenantService thisService = getThis(getClass()); + return thisService.getByTenantId(tenantId).stream() + .filter(t -> DateUtil.now().isBefore(t.getExpireTime())).map(SysModuleTenant::getModuleId) + .collect(Collectors.toList()); + } + + @Cacheable(value = SysModuleTenant.CACHE_NAME, key = "#tenantId", unless = "#result == null or #result.isEmpty()") + @Override + public List getByTenantId(Integer tenantId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysModuleTenant.class) + .eq(SysModuleTenant::getTenantId, tenantId); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysModuleTenantVo vo) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysModuleTenant.class) + .eq(SysModuleTenant::getTenantId, vo.getTenantId()); + this.remove(queryWrapper); + + if (CollectionUtil.isNotEmpty(vo.getModules())) { + List records = vo.getModules().stream().map(t -> { + + SysModule sysModule = sysModuleService.getById(t.getModuleId()); + + if (sysModule.getIsPlatform()) { + Tenant tenant = tenantService.findById(vo.getTenantId()); + if (!tenant.getIsPlatform()) { + throw new DefaultClientException( + "租户【" + tenant.getName() + "】不是平台管理租户,不允许授权【" + sysModule.getName() + + "】模块!"); + } + } + SysModuleTenant record = new SysModuleTenant(); + record.setId(IdUtil.getId()); + record.setModuleId(t.getModuleId()); + record.setTenantId(vo.getTenantId()); + record.setExpireTime(t.getExpireTime()); + + return record; + }).collect(Collectors.toList()); + + this.saveBatch(records); + } + } + + @CacheEvict(value = SysModuleTenant.CACHE_NAME, key = "#key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/TenantServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/TenantServiceImpl.java new file mode 100644 index 0000000..4deae73 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/TenantServiceImpl.java @@ -0,0 +1,182 @@ +package com.lframework.starter.web.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.DataSourceUtil; +import com.lframework.starter.web.core.utils.EncryptUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.mappers.TenantMapper; +import com.lframework.starter.web.inner.service.TenantService; +import com.lframework.starter.web.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.starter.web.inner.vo.system.tenant.UpdateTenantVo; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@DS("master") +@Service +public class TenantServiceImpl extends BaseMpServiceImpl implements + TenantService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryTenantVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, TenantSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = Tenant.CACHE_NAME, key = "#id", unless = "#result == null") + @Override + public Tenant findById(Integer id) { + return getById(id); + } + + @Cacheable(value = Tenant.CACHE_NAME, key = "'all'", unless = "#result == null") + @Override + public List findAll() { + Wrapper queryWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getAvailable, Boolean.TRUE); + + return list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Integer create(CreateTenantVo data) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getName, data.getName()); + if (count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + if (data.getIsPlatform()) { + checkWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getIsPlatform, Boolean.TRUE); + if (count(checkWrapper) > 0) { + throw new DefaultClientException("平台管理租户只能有一个!"); + } + } + + if (!DataSourceUtil.validConnection(data.getJdbcUrl(), data.getJdbcUsername(), + data.getJdbcPassword())) { + throw new DefaultClientException("数据库连接失败,请检查数据库配置!"); + } + + Tenant record = new Tenant(); + record.setName(data.getName()); + if (StringUtil.isNotBlank(data.getServerName())) { + record.setServerName(data.getServerName()); + } + record.setJdbcUrl(data.getJdbcUrl()); + record.setJdbcUsername(data.getJdbcUsername()); + record.setJdbcPassword(EncryptUtil.encrypt(data.getJdbcPassword())); + record.setAvailable(Boolean.TRUE); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateTenantVo data) { + + Tenant record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("租户不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getName, data.getName()).ne(Tenant::getId, data.getId()); + if (count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + if (data.getIsPlatform()) { + checkWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getIsPlatform, Boolean.TRUE).ne(Tenant::getId, data.getId()); + if (count(checkWrapper) > 0) { + throw new DefaultClientException("平台管理租户只能有一个!"); + } + } + + if (!data.getAvailable() && data.getIsPlatform()) { + throw new DefaultClientException("平台管理租户不允许停用!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Tenant.class) + .eq(Tenant::getId, data.getId()).set(Tenant::getName, data.getName()) + .set(Tenant::getServerName, data.getServerName()) + .set(Tenant::getAvailable, data.getAvailable()); + + boolean validConnection = false; + if (StringUtil.isNotBlank(data.getJdbcUrl())) { + updateWrapper.set(Tenant::getJdbcUrl, data.getJdbcUrl()); + + validConnection = true; + } + if (StringUtil.isNotBlank(data.getJdbcUsername())) { + updateWrapper.set(Tenant::getJdbcUsername, data.getJdbcUsername()); + + validConnection = true; + } + if (StringUtil.isNotBlank(data.getJdbcPassword())) { + updateWrapper.set(Tenant::getJdbcPassword, EncryptUtil.encrypt(data.getJdbcPassword())); + + validConnection = true; + } + + this.update(updateWrapper); + + Tenant tenant = this.getById(data.getId()); + + if (validConnection) { + if (!DataSourceUtil.validConnection(tenant.getJdbcUrl(), tenant.getJdbcUsername(), + EncryptUtil.decrypt(tenant.getJdbcPassword()))) { + throw new DefaultClientException("数据库连接失败,请检查数据库配置!"); + } + } + } + + @Caching(evict = { + @CacheEvict(value = Tenant.CACHE_NAME, key = "#key"), + @CacheEvict(value = Tenant.CACHE_NAME, key = "'all'") + }) + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicCategoryServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicCategoryServiceImpl.java new file mode 100644 index 0000000..ccf85f5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicCategoryServiceImpl.java @@ -0,0 +1,131 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.mappers.system.SysDataDicCategoryMapper; +import com.lframework.starter.web.inner.service.system.SysDataDicCategoryService; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import com.lframework.starter.web.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.starter.web.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysDataDicCategoryServiceImpl extends + BaseMpServiceImpl implements + SysDataDicCategoryService { + + @Autowired + private SysDataDicService sysDataDicService; + + @Cacheable(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDicCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicCategory record = new SysDataDicCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getCode, vo.getCode()).ne(SysDataDicCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getName, vo.getName()).ne(SysDataDicCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryDicWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCategoryId, id); + if (sysDataDicService.count(queryDicWrapper) > 0) { + throw new DefaultClientException("此分类下存在数据字典,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicItemServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicItemServiceImpl.java new file mode 100644 index 0000000..190ae3b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicItemServiceImpl.java @@ -0,0 +1,157 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.mappers.system.SysDataDicItemMapper; +import com.lframework.starter.web.inner.service.system.SysDataDicItemService; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import com.lframework.starter.web.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.UpdateSysDataDicItemVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysDataDicItemServiceImpl extends + BaseMpServiceImpl implements SysDataDicItemService { + + @Autowired + private SysDataDicService sysDataDicService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysDataDicItemVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysDataDicItemVo vo) { + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDicItem findById(String id) { + return getBaseMapper().selectById(id); + } + + @Override + public SysDataDicItem findByCode(String dicCode, String code) { + SysDataDicItemService thisService = getThis(getClass()); + List items = thisService.findByDicCode(dicCode); + if (CollectionUtil.isEmpty(items)) { + return null; + } + + return items.stream().filter(t -> t.getCode().equals(code)).findFirst().orElse(null); + } + + @Cacheable(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #dicCode") + @Override + public List findByDicCode(String dicCode) { + Wrapper queryDicWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, dicCode); + SysDataDic dic = sysDataDicService.getOne(queryDicWrapper); + if (dic == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, dic.getId()).orderByAsc(SysDataDicItem::getOrderNo); + List datas = this.list(queryWrapper); + + return datas; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicItemVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, vo.getDicId()) + .eq(SysDataDicItem::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, vo.getDicId()) + .eq(SysDataDicItem::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicItem record = new SysDataDicItem(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setDicId(vo.getDicId()); + record.setOrderNo(vo.getOrderNo()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicItemVo vo) { + + SysDataDicItem record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典值不存在!"); + } + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, record.getDicId()) + .eq(SysDataDicItem::getCode, vo.getCode()).ne(SysDataDicItem::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, record.getDicId()) + .eq(SysDataDicItem::getName, vo.getName()).ne(SysDataDicItem::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDataDicItem.class) + .set(SysDataDicItem::getCode, vo.getCode()).set(SysDataDicItem::getName, vo.getName()) + .set(SysDataDicItem::getOrderNo, vo.getOrderNo()).eq(SysDataDicItem::getId, vo.getId()); + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + this.removeById(id); + } + + @CacheEvict(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicServiceImpl.java new file mode 100644 index 0000000..e3d5232 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataDicServiceImpl.java @@ -0,0 +1,146 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.mappers.system.SysDataDicMapper; +import com.lframework.starter.web.inner.service.system.SysDataDicItemService; +import com.lframework.starter.web.inner.service.system.SysDataDicService; +import com.lframework.starter.web.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.UpdateSysDataDicVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysDataDicServiceImpl extends + BaseMpServiceImpl implements + SysDataDicService { + + @Autowired + private SysDataDicItemService sysDataDicItemService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysDataDicVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysDataDic.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDic findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDic record = new SysDataDic(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getCategoryId())) { + record.setCategoryId(vo.getCategoryId()); + } + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, vo.getCode()).ne(SysDataDic::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getName, vo.getName()).ne(SysDataDic::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDic record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDataDic.class) + .set(SysDataDic::getCode, vo.getCode()).set(SysDataDic::getName, vo.getName()) + .set(SysDataDic::getCategoryId, + StringUtil.isBlank(vo.getCategoryId()) ? null : vo.getCategoryId()) + .eq(SysDataDic::getId, vo.getId()); + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + this.removeById(id); + + Wrapper deleteItemWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, id); + sysDataDicItemService.remove(deleteItemWrapper); + } + + @CacheEvict(value = SysDataDic.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionDataServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionDataServiceImpl.java new file mode 100644 index 0000000..19b840f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionDataServiceImpl.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; +import com.lframework.starter.web.inner.mappers.system.SysDataPermissionDataMapper; +import com.lframework.starter.web.inner.service.system.SysDataPermissionDataService; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SysDataPermissionDataServiceImpl extends + BaseMpServiceImpl implements + SysDataPermissionDataService { + + @Override + public List getByBizId(String bizId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataPermissionData.class) + .eq(SysDataPermissionData::getBizId, bizId); + + return this.list(queryWrapper); + } + + @Override + public SysDataPermissionData getByBizId(String bizId, Integer bizType, Integer permissionType) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataPermissionData.class) + .eq(SysDataPermissionData::getBizId, bizId).eq(SysDataPermissionData::getBizType, bizType) + .eq(SysDataPermissionData::getPermissionType, permissionType); + + return this.getOne(queryWrapper); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionModelDetailServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionModelDetailServiceImpl.java new file mode 100644 index 0000000..7b12c5a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDataPermissionModelDetailServiceImpl.java @@ -0,0 +1,146 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.EnumUtil; +import com.lframework.starter.web.inner.entity.SysDataPermissionModelDetail; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailCalcType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailConditionType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailInputType; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionModelDetailNodeType; +import com.lframework.starter.web.inner.mappers.system.SysDataPermissionModelDetailMapper; +import com.lframework.starter.web.inner.service.system.SysDataPermissionModelDetailService; +import com.lframework.starter.web.inner.vo.system.permission.SysDataPermissionModelDetailVo; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class SysDataPermissionModelDetailServiceImpl extends + BaseMpServiceImpl implements + SysDataPermissionModelDetailService { + + @Override + public String toSql(List models) { + if (CollectionUtil.isEmpty(models)) { + return null; + } + + StringBuilder builder = new StringBuilder(); + + for (SysDataPermissionModelDetailVo model : models) { + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, model.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, model.getCalcType()); + if (CollectionUtil.isNotEmpty(model.getChildren())) { + builder.append(" ("); + builder.append(this.buildChildrenSql(model.getChildren(), calcType.getOperation())); + builder.append(") "); + } + builder.append("AND "); + } else { + throw new DefaultSysException("nodeType有误,请检查!"); + } + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 4); + } + return builder.toString(); + } + + @Override + public String formatSql(String sqlTemplate, Map params) { + return StringUtil.format(sqlTemplate, params); + } + + private String buildChildrenSql(List children, String operation) { + if (CollectionUtil.isEmpty(children)) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + for (SysDataPermissionModelDetailVo child : children) { + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, child.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, child.getCalcType()); + if (CollectionUtil.isNotEmpty(child.getChildren())) { + builder.append(" ("); + builder.append(this.buildChildrenSql(child.getChildren(), calcType.getOperation())); + builder.append(")"); + builder.append(operation).append(" "); + } + } else { + SysDataPermissionModelDetailConditionType conditionType = EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, child.getConditionType()); + SysDataPermissionModelDetail record = this.getById(child.getDetailId()); + builder.append("{").append(record.getTableName()).append("}.") + .append(record.getColumnName()).append(" ").append(conditionType.getOperation()) + .append(" ").append(this.buildLeft(conditionType)) + .append(this.buildValue(child, record)) + .append(this.buildRight(conditionType)).append(" ").append(operation).append(" "); + } + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - operation.length() - 1); + } + + return builder.toString(); + } + + private String buildLeft(SysDataPermissionModelDetailConditionType conditionType) { + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + return "("; + } else if (conditionType == SysDataPermissionModelDetailConditionType.LEFT_LIKE) { + return "CONCAT('%',"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.RIGHT_LIKE) { + return "CONCAT("; + } else if (conditionType == SysDataPermissionModelDetailConditionType.AROUND_LIKE) { + return "CONCAT('%',"; + } + + return ""; + } + + private String buildRight(SysDataPermissionModelDetailConditionType conditionType) { + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + return ")"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.LEFT_LIKE) { + return ")"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.RIGHT_LIKE) { + return ",'%')"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.AROUND_LIKE) { + return ",'%')"; + } + + return ""; + } + + private String buildValue(SysDataPermissionModelDetailVo child, + SysDataPermissionModelDetail record) { + SysDataPermissionModelDetailConditionType conditionType = EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, child.getConditionType()); + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + if (record.getInputType() == SysDataPermissionModelDetailInputType.SQL) { + return record.getSqlValue(); + } else { + return CollectionUtil.join( + child.getValues().stream().map(t -> "'" + t + "'").collect(Collectors.toList()), ","); + } + } + + return "'" + child.getValue() + "'"; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDeptServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDeptServiceImpl.java new file mode 100644 index 0000000..76dcbdf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysDeptServiceImpl.java @@ -0,0 +1,285 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.event.DataChangeEventBuilder; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysDept; +import com.lframework.starter.web.inner.enums.system.SysDeptNodeType; +import com.lframework.starter.web.inner.events.system.DeleteSysDeptEvent; +import com.lframework.starter.web.inner.mappers.system.SysDeptMapper; +import com.lframework.starter.web.inner.service.RecursionMappingService; +import com.lframework.starter.web.inner.service.system.SysDeptService; +import com.lframework.starter.web.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.starter.web.inner.vo.system.dept.SysDeptSelectorVo; +import com.lframework.starter.web.inner.vo.system.dept.UpdateSysDeptVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysDeptServiceImpl extends BaseMpServiceImpl implements + SysDeptService { + + @Autowired + private RecursionMappingService recursionMappingService; + + @Override + public List selector(SysDeptSelectorVo vo) { + + return this.doSelector(vo); + } + + @Cacheable(value = SysDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDept findById(String id) { + + return this.doGetById(id); + } + + @Override + public SysDept findByCode(String code) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDept.class).eq(SysDept::getCode, code); + return getOne(queryWrapper); + } + + @OpLog(type = SystemOpLogType.class, name = "删除部门,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + List batchIds = new ArrayList<>(); + batchIds.add(id); + List nodeChildIds = recursionMappingService.getNodeChildIds(id, + SysDeptNodeType.class); + if (CollectionUtil.isNotEmpty(nodeChildIds)) { + batchIds.addAll(nodeChildIds); + } + + this.doBatchDelete(batchIds); + + for (String batchId : batchIds) { + SysDept dept = this.findById(batchId); + + DataChangeEventBuilder.publishLogicDelete(this, DeleteSysDeptEvent.class, dept); + } + } + + @OpLog(type = SystemOpLogType.class, name = "新增部门,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDeptVo vo) { + + SysDept data = this.doCreate(vo); + + this.saveRecursion(true, data.getId(), data.getParentId()); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改部门,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDeptVo vo) { + + SysDept oldData = this.findById(vo.getId()); + + this.doUpdate(vo); + + if (!StringUtil.equals(oldData.getParentId(), vo.getParentId())) { + this.saveRecursion(false, vo.getId(), vo.getParentId()); + } + + OpLogUtil.setVariable("id", vo.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + protected List doSelector(SysDeptSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected SysDept doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doBatchDelete(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDept.class) + .set(SysDept::getAvailable, Boolean.FALSE).in(SysDept::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected SysDept doCreate(CreateSysDeptVo vo) { + + //查询Code是否重复 + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getCode, vo.getCode()).eq(SysDept::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getName, vo.getName()).eq(SysDept::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDept parentDept = null; + //如果parentId不为空,查询上级部门是否存在 + if (!StringUtil.isBlank(vo.getParentId())) { + Wrapper queryParentWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getId, vo.getParentId()).eq(SysDept::getAvailable, true); + parentDept = this.getOne(queryParentWrapper); + if (parentDept == null) { + throw new DefaultClientException("上级部门不存在,请检查!"); + } + } + + SysDept data = new SysDept(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setShortName(vo.getShortName()); + if (!StringUtil.isBlank(vo.getParentId())) { + data.setParentId(vo.getParentId()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription(vo.getDescription()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doUpdate(UpdateSysDeptVo vo) { + + SysDept data = this.findById(vo.getId()); + if (data == null || !data.getAvailable()) { + throw new DefaultClientException("部门不存在!"); + } + + //查询Code是否重复 + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getCode, vo.getCode()).ne(SysDept::getId, data.getId()) + .eq(SysDept::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getName, vo.getName()) + .ne(SysDept::getId, data.getId()).eq(SysDept::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + //如果parentId不为空,查询上级部门是否存在 + if (!StringUtil.isBlank(vo.getParentId())) { + if (ObjectUtil.equals(vo.getParentId(), data.getId())) { + throw new DefaultClientException("上级部门不能是当前部门!"); + } + Wrapper checkParentWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getId, vo.getParentId()).eq(SysDept::getAvailable, true); + if (getBaseMapper().selectCount(checkParentWrapper) == 0) { + throw new DefaultClientException("上级部门不存在,请检查!"); + } + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDept.class) + .set(SysDept::getCode, vo.getCode()).set(SysDept::getName, vo.getName()) + .set(SysDept::getShortName, vo.getShortName()) + .set(SysDept::getParentId, + StringUtil.isBlank(vo.getParentId()) ? null : vo.getParentId()) + .set(SysDept::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SysDept::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + } + + /** + * 保存递归信息 + * + * @param deptId + * @param parentId + */ + protected void saveRecursion(boolean isCreate, String deptId, String parentId) { + + if (!isCreate) { + recursionMappingService.deleteNode(deptId, SysDeptNodeType.class); + } + + if (!StringUtil.isBlank(parentId)) { + List parentIds = recursionMappingService.getNodeParentIds(parentId, + SysDeptNodeType.class); + if (CollectionUtil.isEmpty(parentIds)) { + parentIds = new ArrayList<>(); + } + parentIds.add(parentId); + + recursionMappingService.saveNode(deptId, SysDeptNodeType.class, + parentIds); + } else { + recursionMappingService.saveNode(deptId, SysDeptNodeType.class); + } + + // 还要更新这个节点的子节点 + List childIds = recursionMappingService.getNodeChildIds(deptId, + SysDeptNodeType.class); + + for (String childId : childIds) { + List parentDeptList = new ArrayList<>(); + SysDept sysDept = this.findById(childId); + if (!sysDept.getAvailable()) { + continue; + } + + while (StringUtil.isNotBlank(sysDept.getParentId())) { + sysDept = this.findById(sysDept.getParentId()); + if (sysDept == null) { + break; + } + parentDeptList.add(sysDept); + } + + parentDeptList = CollectionUtil.reverse(parentDeptList); + recursionMappingService.deleteNode(childId, SysDeptNodeType.class); + recursionMappingService.saveNode(childId, SysDeptNodeType.class, + parentDeptList.stream().map(SysDept::getId).collect(Collectors.toList())); + } + } + + @CacheEvict(value = {SysDept.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysGenerateCodeServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysGenerateCodeServiceImpl.java new file mode 100644 index 0000000..c74b432 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysGenerateCodeServiceImpl.java @@ -0,0 +1,142 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.dto.GenerateCodeDto; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import com.lframework.starter.web.inner.mappers.system.SysGenerateCodeMapper; +import com.lframework.starter.web.inner.service.system.SysGenerateCodeService; +import com.lframework.starter.web.inner.vo.system.generate.CreateSysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.QuerySysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.SettingSysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.UpdateSysGenerateCodeVo; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysGenerateCodeServiceImpl extends + BaseMpServiceImpl implements SysGenerateCodeService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysGenerateCodeVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysGenerateCodeVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysGenerateCode.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysGenerateCode findById(Integer id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SystemOpLogType.class, name = "新增编号规则,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public Integer create(CreateSysGenerateCodeVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysGenerateCode.class) + .eq(SysGenerateCode::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("规则ID重复,请重新输入!"); + } + SysGenerateCode data = new SysGenerateCode(); + data.setId(vo.getId()); + data.setName(vo.getName()); + data.setConfigStr(StringPool.EMPTY_STR); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改编号规则,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysGenerateCodeVo vo) { + + SysGenerateCode data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("编号规则不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + SysGenerateCode.class) + .set(SysGenerateCode::getName, vo.getName()) + .eq(SysGenerateCode::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SystemOpLogType.class, name = "删除编号规则,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(Integer id) { + + getBaseMapper().deleteById(id); + } + + @OpLog(type = SystemOpLogType.class, name = "设置编号规则,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SettingSysGenerateCodeVo vo) { + SysGenerateCode data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("编号规则不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + SysGenerateCode.class) + .set(SysGenerateCode::getConfigStr, vo.getConfigStr()) + .eq(SysGenerateCode::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = {SysGenerateCode.CACHE_NAME, + GenerateCodeDto.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMailMessageServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMailMessageServiceImpl.java new file mode 100644 index 0000000..c9e3350 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMailMessageServiceImpl.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import com.lframework.starter.web.inner.mappers.system.SysMailMessageMapper; +import com.lframework.starter.web.inner.service.system.SysMailMessageService; +import com.lframework.starter.web.inner.vo.system.message.mail.QuerySysMailMessageVo; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SysMailMessageServiceImpl extends + BaseMpServiceImpl + implements SysMailMessageService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysMailMessageVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysMailMessageVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public SysMailMessage findById(String id) { + return getById(id); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMenuServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMenuServiceImpl.java new file mode 100644 index 0000000..e8c3d36 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysMenuServiceImpl.java @@ -0,0 +1,484 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.security.SecurityConstants; +import com.lframework.starter.web.core.components.security.UserTokenResolver; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.*; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.dto.system.MenuDto; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.enums.system.SysMenuComponentType; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.inner.mappers.system.SysMenuMapper; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import com.lframework.starter.web.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.starter.web.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.starter.web.inner.vo.system.menu.UpdateSysMenuVo; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + *

+ * 系统菜单 服务实现类 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +@Service +public class SysMenuServiceImpl extends BaseMpServiceImpl implements + SysMenuService { + + private String tokenKey = "X-Auth-Token"; + + @Autowired + private UserTokenResolver userTokenResolver; + + @Override + public List queryList(List moduleIds) { + + return this.doQuery(moduleIds); + } + + @Override + public List getByRoleId(String roleId, List moduleIds) { + + return this.doGetByRoleId(roleId, moduleIds); + } + + @Cacheable(value = SysMenu.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysMenu findById(@NonNull String id) { + + return this.doGetById(id); + } + + @OpLog(type = SystemOpLogType.class, name = "新增菜单,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(@NonNull CreateSysMenuVo vo) { + + SysMenu data = this.doCreate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改菜单,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(@NonNull UpdateSysMenuVo vo) { + + SysMenu oriMenu = this.findById(vo.getId()); + + if (!ObjectUtil.equals(vo.getDisplay(), oriMenu.getDisplay().getCode())) { + throw new DefaultClientException("菜单【" + oriMenu.getTitle() + "】" + "不允许更改类型!"); + } + + SysMenu data = this.doUpdate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SystemOpLogType.class, name = "删除菜单,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(@NonNull String id) { + + SysMenu oriMenu = this.findById(id); + + List children = this.doGetChildrenById(id); + if (CollectionUtil.isNotEmpty(children)) { + //如果子节点不为空 + throw new DefaultClientException("菜单【" + oriMenu.getTitle() + "】存在子菜单,无法删除!"); + } + + this.doDeleteById(id); + } + + @Override + public List selector(SysMenuSelectorVo vo, List moduleIds) { + + return this.doSelector(vo, moduleIds); + } + + @OpLog(type = SystemOpLogType.class, name = "启用菜单,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void enable(@NonNull String id) { + + this.doEnable(id); + } + + @OpLog(type = SystemOpLogType.class, name = "停用菜单,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void unable(@NonNull String id) { + + this.doUnable(id); + } + + @Override + public Boolean existPermission(String permission) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysMenu.class) + .eq(SysMenu::getPermission, permission); + return this.count(queryWrapper) > 0; + } + + protected List doQuery(List moduleIds) { + + return getBaseMapper().query(moduleIds); + } + + protected List doGetByRoleId(String roleId, List moduleIds) { + + return getBaseMapper().getByRoleId(roleId, moduleIds); + } + + protected SysMenu doGetById(@NonNull String id) { + + return getBaseMapper().findById(id); + } + + protected SysMenu doCreate(@NonNull CreateSysMenuVo vo) { + + SysMenu data = new SysMenu(); + + data.setId(IdUtil.getId()); + this.setDataForCreate(vo, data); + + getBaseMapper().insert(data); + + return data; + } + + protected SysMenu doUpdate(@NonNull UpdateSysMenuVo vo) { + + SysMenu data = new SysMenu(); + + data.setId(vo.getId()); + + this.setDataForCreate(vo, data); + + data.setAvailable(vo.getAvailable()); + + SysMenuService thisService = getThis(this.getClass()); + + SysMenu record = thisService.findById(vo.getId()); + + data.setIsSpecial(record.getIsSpecial()); + + getBaseMapper().deleteById(vo.getId()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doDeleteById(@NonNull String id) { + + getBaseMapper().deleteById(id); + } + + protected List doSelector(SysMenuSelectorVo vo, List moduleIds) { + + return getBaseMapper().selector(vo, moduleIds); + } + + protected void doEnable(@NonNull String id) { + + List ids = new ArrayList<>(); + // 启用时,需要将父级菜单也启用 + ids.add(id); + + String tmpId = id; + while (!StringUtil.isBlank(tmpId)) { + SysMenu sysMenu = getById(tmpId); + if (sysMenu == null) { + break; + } + if (StringUtil.isBlank(sysMenu.getParentId())) { + break; + } + + ids.add(sysMenu.getParentId()); + + tmpId = sysMenu.getParentId(); + } + Wrapper wrapper = Wrappers.lambdaUpdate(SysMenu.class) + .set(SysMenu::getAvailable, Boolean.TRUE).in(SysMenu::getId, ids); + getBaseMapper().update(new SysMenu(), wrapper); + } + + protected void doUnable(@NonNull String id) { + + Set ids = new HashSet<>(); + // 停用时,需要将子级菜单也停用 + ids.add(id); + while (true) { + List sysMenuList = list(Wrappers.lambdaQuery(SysMenu.class) + .in(SysMenu::getParentId, ids)); + + int oldSize = ids.size(); + if (CollectionUtil.isNotEmpty(sysMenuList)) { + ids.addAll(sysMenuList.stream().map(SysMenu::getId).collect(Collectors.toList())); + } + if (oldSize == ids.size()) { + break; + } + } + + Wrapper wrapper = Wrappers.lambdaUpdate(SysMenu.class) + .set(SysMenu::getAvailable, Boolean.FALSE).in(SysMenu::getId, ids); + getBaseMapper().update(new SysMenu(), wrapper); + } + + protected void setDataForCreate(@NonNull CreateSysMenuVo vo, @NonNull SysMenu data) { + + SysMenuDisplay sysMenuDisplay = EnumUtil.getByCode(SysMenuDisplay.class, vo.getDisplay()); + + SysMenu parentMenu = null; + if (!StringUtil.isBlank(vo.getParentId())) { + parentMenu = this.findById(vo.getParentId()); + if (parentMenu == null) { + throw new DefaultClientException("父级菜单不存在!"); + } + if (parentMenu.getId().equals(data.getId())) { + throw new DefaultClientException("父级菜单不能是当前菜单!"); + } + } + data.setCode(vo.getCode()); + data.setTitle(vo.getTitle()); + // fix 这里需要用null代替空字符串 + data.setParentId(parentMenu == null ? null : parentMenu.getId()); + data.setDisplay(sysMenuDisplay); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + if (sysMenuDisplay == SysMenuDisplay.CATALOG || sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (parentMenu != null) { + //父级菜单必须是目录 + if (parentMenu.getDisplay() != SysMenuDisplay.CATALOG) { + throw new DefaultClientException( + "父级菜单类型必须是【" + SysMenuDisplay.CATALOG.getDesc() + "】!"); + } + } + + data.setName(vo.getName()); + data.setIcon(vo.getIcon()); + data.setPath(vo.getPath()); + data.setHidden(vo.getHidden()); + + if (sysMenuDisplay == SysMenuDisplay.FUNCTION) { + // 功能必须有parentId + if (parentMenu == null) { + throw new DefaultClientException( + "此菜单类型是【" + SysMenuDisplay.FUNCTION.getDesc() + "】,父级菜单不能为空!"); + } + data.setComponent(vo.getComponent()); + data.setComponentType( + EnumUtil.getByCode(SysMenuComponentType.class, vo.getComponentType())); + data.setNoCache(vo.getNoCache()); + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + data.setPermission(vo.getPermission()); + } + } else if (sysMenuDisplay == SysMenuDisplay.PERMISSION) { + + if (parentMenu != null) { + //父级菜单必须是目录 + if (parentMenu.getDisplay() != SysMenuDisplay.FUNCTION) { + throw new DefaultClientException( + "父级菜单类型必须是【" + SysMenuDisplay.FUNCTION.getDesc() + "】!"); + } + } else { + throw new DefaultClientException( + "此菜单类型是【" + SysMenuDisplay.PERMISSION.getDesc() + "】,父级菜单不能为空!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + data.setPermission(vo.getPermission()); + } + } + + protected List doGetChildrenById(String id) { + + return getBaseMapper().getChildrenById(id); + } + + @Override + public List getMenuByUserId(String userId, boolean isAdmin, List moduleIds) { + + List menus = this.doGetMenus(userId, isAdmin, moduleIds); + + List collectionMenuIds = this.doGetCollectMenuIds(userId); + + if (!CollectionUtil.isEmpty(menus)) { + // 用env渲染${xxx}属性 + menus.forEach(menu -> { + menu.setPath(ApplicationUtil.resolvePlaceholders(menu.getPath())); + }); + + // 渲染spel表达式 + Map vars = getDefaultVars(); + menus.stream().filter(menu -> this.hasSpecExpression(menu.getPath())).forEach(menu -> { + List expressions = this.getAllExpressions(menu.getPath()); + if (!CollectionUtil.isEmpty(expressions)) { + String oriPath = menu.getPath(); + for (String expression : expressions) { + Object parsed = SpelUtil.parse(expression.replaceAll("\\{", "").replaceAll("}", ""), + vars); + oriPath = oriPath.replace(expression, parsed == null ? "" : String.valueOf(parsed)); + } + + menu.setPath(oriPath); + } + }); + + if (!CollectionUtil.isEmpty(collectionMenuIds)) { + menus.forEach(menu -> { + menu.setIsCollect(collectionMenuIds.contains(menu.getId())); + }); + } + } + + return menus; + } + + @Override + public Set getPermissionsByUserId(String userId, boolean isAdmin, + List moduleIds) { + + return getBaseMapper().getPermissionsByUserId(userId, isAdmin, moduleIds); + } + + @Override + public Set getRolePermissionByUserId(String userId) { + return getBaseMapper().getRolePermissionByUserId(userId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void collect(String userId, String menuId) { + + if (StringUtil.isBlank(userId) || StringUtil.isBlank(menuId)) { + return; + } + + this.cancelCollect(userId, menuId); + + getBaseMapper().collectMenu(IdUtil.getId(), userId, menuId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void cancelCollect(String userId, String menuId) { + + if (StringUtil.isBlank(userId) || StringUtil.isBlank(menuId)) { + return; + } + + getBaseMapper().cancelCollectMenu(userId, menuId); + } + + @Override + public List getParentMenuIds(String menuId) { + List results = new ArrayList<>(); + + String tmpMenuId = menuId; + while (tmpMenuId != null) { + SysMenu menu = getThis(this.getClass()).findById(tmpMenuId); + if (menu != null && StringUtil.isNotBlank(menu.getParentId())) { + results.add(menu.getParentId()); + tmpMenuId = menu.getParentId(); + } else { + break; + } + } + + return results; + } + + private List getAllExpressions(String s) { + + if (!this.hasSpecExpression(s)) { + return null; + } + + List results = new ArrayList<>(); + String[] arr = s.split("#\\{"); + for (int i = 1; i < arr.length; i++) { + if (!arr[i].contains("}")) { + continue; + } + results.add("#{" + arr[i].substring(0, arr[i].indexOf("}")) + "}"); + } + + return results; + } + + private boolean hasSpecExpression(String s) { + + return RegUtil.isMatch(Pattern.compile("^.*#\\{.*}.*$"), s); + } + + protected Map getDefaultVars() { + + Map vars = new HashMap<>(); + + vars.put("_token", userTokenResolver.getToken()); + vars.put("_fullToken", userTokenResolver.getFullToken()); + vars.put("_tokenKey", tokenKey); + + return vars; + } + + protected List doGetMenus(String userId, boolean isAdmin, List moduleIds) { + + return getBaseMapper().getMenuByUserId(userId, isAdmin, moduleIds); + } + + protected List doGetCollectMenuIds(String userId) { + + return getBaseMapper().getCollectMenuIds(userId); + } + + @CacheEvict(value = SysMenu.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeLogServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeLogServiceImpl.java new file mode 100644 index 0000000..dfae51b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeLogServiceImpl.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysNoticeLog; +import com.lframework.starter.web.inner.mappers.system.SysNoticeLogMapper; +import com.lframework.starter.web.inner.service.system.SysNoticeLogService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Service +public class SysNoticeLogServiceImpl extends + BaseMpServiceImpl implements SysNoticeLogService { + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean setReaded(String noticeId, String userId) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, noticeId).eq(SysNoticeLog::getUserId, userId) + .eq(SysNoticeLog::getReaded, Boolean.FALSE).set(SysNoticeLog::getReaded, Boolean.TRUE) + .set(SysNoticeLog::getReadTime, + LocalDateTime.now()); + + return this.update(updateWrapper); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeServiceImpl.java new file mode 100644 index 0000000..05b3fbe --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNoticeServiceImpl.java @@ -0,0 +1,259 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.threads.DefaultRunnable; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.inner.dto.system.notice.SysNoticeDto; +import com.lframework.starter.web.inner.entity.SysNotice; +import com.lframework.starter.web.inner.entity.SysNoticeLog; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.mappers.system.SysNoticeMapper; +import com.lframework.starter.web.inner.service.system.SysNoticeLogService; +import com.lframework.starter.web.inner.service.system.SysNoticeService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import com.lframework.starter.web.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.UpdateSysNoticeVo; +import com.lframework.starter.web.inner.vo.system.user.QuerySysUserVo; +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.events.UserConnectEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysNoticeServiceImpl extends BaseMpServiceImpl implements + SysNoticeService { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysNoticeLogService sysNoticeLogService; + + @Autowired + private WsDataPusher wsDataPusher; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySysNoticeVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysNoticeVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysNoticeByUserVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryByUser(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysNotice.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysNoticeDto getContent(String id) { + SysNotice record = getBaseMapper().selectById(id); + if (record == null) { + return null; + } + + return new SysNoticeDto(record); + } + + @Override + public SysNotice findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SystemOpLogType.class, name = "新增系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysNoticeVo vo) { + + SysNotice data = new SysNotice(); + data.setId(IdUtil.getId()); + data.setTitle(vo.getTitle()); + data.setContent(vo.getContent()); + data.setPublished(vo.getPublished()); + + getBaseMapper().insert(data); + + if (vo.getPublished()) { + ThreadUtil.execAsync(new DefaultRunnable(() -> { + SysNoticeService thisService = getThis(getClass()); + thisService.publish(data.getId()); + })); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysNoticeVo vo) { + + SysNotice data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("系统通知不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysNotice.class) + .set(SysNotice::getTitle, vo.getTitle()).set(SysNotice::getContent, vo.getContent()) + .set(SysNotice::getAvailable, vo.getAvailable()) + .set(SysNotice::getPublished, vo.getPublished()).set(SysNotice::getPublishTime, null) + .set(SysNotice::getReadedNum, 0).set(SysNotice::getUnReadNum, 0) + .eq(SysNotice::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + // 无论发布还是不发布 都要删除 + Wrapper deleteLogWrapper = Wrappers.lambdaQuery(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, data.getId()); + sysNoticeLogService.remove(deleteLogWrapper); + + if (vo.getPublished()) { + ThreadUtil.execAsync(new DefaultRunnable(() -> { + SysNoticeService thisService = getThis(getClass()); + thisService.publish(data.getId()); + })); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SystemOpLogType.class, name = "发布系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void publish(String id) { + + // 查询所有用户 + QuerySysUserVo querySysUserVo = new QuerySysUserVo(); + List users = sysUserService.query(querySysUserVo); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysNotice.class) + .eq(SysNotice::getId, id).set(SysNotice::getReadedNum, 0) + .set(SysNotice::getUnReadNum, users.size()).set(SysNotice::getPublished, Boolean.TRUE) + .set(SysNotice::getPublishTime, LocalDateTime.now()); + this.update(updateWrapper); + + Wrapper deleteLogWrapper = Wrappers.lambdaQuery(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, id); + sysNoticeLogService.remove(deleteLogWrapper); + + if (!CollectionUtil.isEmpty(users)) { + List logs = users.stream().map(t -> { + SysNoticeLog log = new SysNoticeLog(); + log.setId(IdUtil.getId()); + log.setNoticeId(id); + log.setUserId(t.getId()); + log.setReaded(Boolean.FALSE); + + return log; + }).collect(Collectors.toList()); + + sysNoticeLogService.saveBatch(logs); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setReaded(String id, String userId) { + if (sysNoticeLogService.setReaded(id, userId)) { + getBaseMapper().setReaded(id); + } + } + + @Override + public void noticeForWs() { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setAll(Boolean.TRUE); + + wsDataPusher.push(pushData); + } + + @Override + public void noticeForWs(String userId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setIncludeUserId(userId); + + wsDataPusher.push(pushData); + } + + @Override + public void noticeForWsWithSessionId(String sessionId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setIncludeSessionIds(Collections.singletonList(sessionId)); + + wsDataPusher.push(pushData); + } + + @CacheEvict(value = SysNotice.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } + + @Component + public static class ReloadNoticeListener implements ApplicationListener { + + @Autowired + private SysNoticeService sysNoticeService; + + @Override + public void onApplicationEvent(UserConnectEvent event) { + sysNoticeService.noticeForWsWithSessionId(event.getSessionId()); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupReceiverServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupReceiverServiceImpl.java new file mode 100644 index 0000000..4147215 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupReceiverServiceImpl.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysNotifyGroupReceiver; +import com.lframework.starter.web.inner.mappers.system.SysNotifyGroupReceiverMapper; +import com.lframework.starter.web.inner.service.system.SysNotifyGroupReceiverService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysNotifyGroupReceiverServiceImpl extends + BaseMpServiceImpl + implements SysNotifyGroupReceiverService { + + @Override + public List getReceiverIdsByGroupId(String groupId) { + Wrapper queryWrapper = Wrappers.lambdaQuery( + SysNotifyGroupReceiver.class).select(SysNotifyGroupReceiver::getReceiverId) + .eq(SysNotifyGroupReceiver::getGroupId, groupId); + return this.list(queryWrapper).stream().map(SysNotifyGroupReceiver::getReceiverId) + .collect(Collectors.toList()); + } + + @Override + public Boolean hasUserGroup(String userGroupId) { + return getBaseMapper().hasUserGroup(userGroupId); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupServiceImpl.java new file mode 100644 index 0000000..aff2f6a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysNotifyGroupServiceImpl.java @@ -0,0 +1,271 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.event.DataChangeEventBuilder; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.*; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.*; +import com.lframework.starter.web.inner.enums.system.SysDeptNodeType; +import com.lframework.starter.web.inner.enums.system.SysNotifyReceiverType; +import com.lframework.starter.web.inner.events.system.DeleteSysNotifyGroupEvent; +import com.lframework.starter.web.inner.mappers.system.SysNotifyGroupMapper; +import com.lframework.starter.web.inner.service.RecursionMappingService; +import com.lframework.starter.web.inner.service.system.*; +import com.lframework.starter.web.inner.vo.system.notify.CreateSysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.QuerySysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.SysNotifyGroupSelectorVo; +import com.lframework.starter.web.inner.vo.system.notify.UpdateSysNotifyGroupVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; + +@Service +public class SysNotifyGroupServiceImpl extends + BaseMpServiceImpl implements + SysNotifyGroupService { + + @Autowired + private SysNotifyGroupReceiverService sysNotifyGroupReceiverService; + + @Autowired + private RecursionMappingService recursionMappingService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private SysUserGroupDetailService sysUserGroupDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysNotifyGroupVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysNotifyGroupVo vo) { + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysNotifyGroup.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysNotifyGroup findById(String id) { + return this.getById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysNotifyGroupSelectorVo vo) { + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = SystemOpLogType.class, name = "创建消息通知组,ID:{}", params = "#_result", autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysNotifyGroupVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysNotifyGroup.class) + .eq(SysNotifyGroup::getName, vo.getName()).eq(SysNotifyGroup::getAvailable, true); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称不允许重复!"); + } + + SysNotifyGroup record = new SysNotifyGroup(); + record.setId(IdUtil.getId()); + record.setName(vo.getName()); + record.setReceiverType(EnumUtil.getByCode(SysNotifyReceiverType.class, vo.getReceiverType())); + record.setMessageType(StringUtil.join(StringPool.STR_SPLIT, vo.getMessageType())); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + this.save(record); + + List receiverList = vo.getReceiverIds().stream().map(t -> { + SysNotifyGroupReceiver r = new SysNotifyGroupReceiver(); + r.setId(IdUtil.getId()); + r.setGroupId(record.getId()); + r.setReceiverId(t); + + return r; + }).collect(Collectors.toList()); + + sysNotifyGroupReceiverService.saveBatch(receiverList); + + return record.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改消息通知组,ID:{}", params = "#vo.id", autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysNotifyGroupVo vo) { + + SysNotifyGroup record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("消息通知组不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysNotifyGroup.class) + .eq(SysNotifyGroup::getName, vo.getName()) + .eq(SysNotifyGroup::getAvailable, true) + .ne(SysNotifyGroup::getId, record.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称不允许重复!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysNotifyGroup.class) + .eq(SysNotifyGroup::getId, vo.getId()) + .set(SysNotifyGroup::getName, vo.getName()) + .set(SysNotifyGroup::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(SysNotifyGroup::getReceiverType, + EnumUtil.getByCode(SysNotifyReceiverType.class, vo.getReceiverType())) + .set(SysNotifyGroup::getMessageType, + StringUtil.join(StringPool.STR_SPLIT, vo.getMessageType())); + this.update(updateWrapper); + + Wrapper deleteReceiverWrapper = Wrappers.lambdaQuery( + SysNotifyGroupReceiver.class).eq(SysNotifyGroupReceiver::getGroupId, record.getId()); + sysNotifyGroupReceiverService.remove(deleteReceiverWrapper); + + List receiverList = vo.getReceiverIds().stream().map(t -> { + SysNotifyGroupReceiver r = new SysNotifyGroupReceiver(); + r.setId(IdUtil.getId()); + r.setGroupId(record.getId()); + r.setReceiverId(t); + + return r; + }).collect(Collectors.toList()); + + sysNotifyGroupReceiverService.saveBatch(receiverList); + } + + @Override + public Set getReceiveUserIds(String id) { + SysNotifyGroupService thisService = ApplicationUtil.getBean(SysNotifyGroupService.class); + SysNotifyGroup notifyGroup = thisService.findById(id); + if (notifyGroup == null) { + throw new DefaultClientException("消息通知组不存在!"); + } + if (!notifyGroup.getAvailable()) { + return Collections.emptySet(); + } + + Set userIds = new HashSet<>(); + switch (notifyGroup.getReceiverType()) { + case USER: { + List receiverIds = sysNotifyGroupReceiverService.getReceiverIdsByGroupId( + notifyGroup.getId()); + userIds.addAll(receiverIds); + break; + } + + case DEPT: { + List deptIds = sysNotifyGroupReceiverService.getReceiverIdsByGroupId( + notifyGroup.getId()); + List allDeptIds = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(deptIds)) { + for (String deptId : deptIds) { + List childDeptIds = recursionMappingService.getNodeChildIds(deptId, + SysDeptNodeType.class); + allDeptIds.addAll(childDeptIds); + } + allDeptIds.addAll(deptIds); + } + + if (CollectionUtil.isNotEmpty(allDeptIds)) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUserDept.class) + .select(SysUserDept::getUserId) + .in(SysUserDept::getDeptId, allDeptIds); + List sysUserDeptList = sysUserDeptService.list(queryWrapper); + userIds.addAll( + sysUserDeptList.stream().map(SysUserDept::getUserId).collect(Collectors.toList())); + } + + break; + } + + case ROLE: { + List roleIds = sysNotifyGroupReceiverService.getReceiverIdsByGroupId( + notifyGroup.getId()); + if (CollectionUtil.isNotEmpty(roleIds)) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUserRole.class) + .select(SysUserRole::getUserId) + .in(SysUserRole::getRoleId, roleIds); + List sysUserRoleList = sysUserRoleService.list(queryWrapper); + userIds.addAll( + sysUserRoleList.stream().map(SysUserRole::getUserId).collect(Collectors.toList())); + } + + break; + } + + case USER_GROUP: { + List userGroupIds = sysNotifyGroupReceiverService.getReceiverIdsByGroupId( + notifyGroup.getId()); + if (CollectionUtil.isNotEmpty(userGroupIds)) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUserGroupDetail.class) + .select(SysUserGroupDetail::getUserId) + .in(SysUserGroupDetail::getGroupId, userGroupIds); + List sysUserRoleList = sysUserGroupDetailService.list(queryWrapper); + userIds.addAll( + sysUserRoleList.stream().map(SysUserGroupDetail::getUserId) + .collect(Collectors.toList())); + } + + break; + } + default: + throw new DefaultClientException("消息通知组接收者类型错误!"); + } + + return userIds; + } + + @Transactional(rollbackFor = Exception.class) + @OpLog(type = SystemOpLogType.class, name = "删除消息通知组,ID:{}", params = "#id") + @Override + public void deleteById(String id) { + Wrapper deleteWrapper = Wrappers.lambdaUpdate(SysNotifyGroup.class) + .eq(SysNotifyGroup::getId, id).set(SysNotifyGroup::getAvailable, false); + this.update(deleteWrapper); + + SysNotifyGroup record = this.findById(id); + DataChangeEventBuilder.publishLogicDelete(this, DeleteSysNotifyGroupEvent.class, record); + } + + @CacheEvict(value = SysNotifyGroup.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysOpenDomainServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysOpenDomainServiceImpl.java new file mode 100644 index 0000000..516becc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysOpenDomainServiceImpl.java @@ -0,0 +1,108 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import com.lframework.starter.web.inner.mappers.system.SysOpenDomainMapper; +import com.lframework.starter.web.inner.service.system.SysOpenDomainService; +import com.lframework.starter.web.inner.vo.system.open.*; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@DS("master") +@Service +public class SysOpenDomainServiceImpl extends + BaseMpServiceImpl + implements SysOpenDomainService { + + @Override + public PageResult query(QuerySysOpenDomainVo vo) { + PageHelperUtil.startPage(vo); + List datas = getBaseMapper().query(vo); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult selector(SysOpenDomainSelectorVo vo) { + PageHelperUtil.startPage(vo); + List datas = getBaseMapper().selector(vo); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysOpenDomain.CACHE_NAME, key = "#id", unless = "#result == null") + @Override + public SysOpenDomain findById(Integer id) { + return this.getById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysOpenDomainVo vo) { + SysOpenDomain data = new SysOpenDomain(); + data.setName(vo.getName()); + data.setApiSecret(vo.getApiSecret()); + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + data.setTenantId(vo.getTenantId()); + + this.save(data); + + return data.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysOpenDomainVo vo) { + + SysOpenDomain record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("开放域不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysOpenDomain.class) + .set(SysOpenDomain::getName, vo.getName()) + .set(SysOpenDomain::getAvailable, vo.getAvailable()) + .set(SysOpenDomain::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(SysOpenDomain::getTenantId, vo.getTenantId()) + .eq(SysOpenDomain::getId, vo.getId()); + + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateApiSecret(UpdateSysOpenDomainSecretVo vo) { + SysOpenDomain record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("开放域不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysOpenDomain.class) + .set(SysOpenDomain::getApiSecret, vo.getApiSecret()) + .eq(SysOpenDomain::getId, vo.getId()); + + this.update(updateWrapper); + } + + @CacheEvict(value = SysOpenDomain.CACHE_NAME, key = "#key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysParameterServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysParameterServiceImpl.java new file mode 100644 index 0000000..b793b19 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysParameterServiceImpl.java @@ -0,0 +1,221 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.ParameterNotFoundException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysParameter; +import com.lframework.starter.web.inner.mappers.system.SysParameterMapper; +import com.lframework.starter.web.inner.service.SysConfService; +import com.lframework.starter.web.inner.service.system.SysParameterService; +import com.lframework.starter.web.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.UpdateSysParameterVo; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysParameterServiceImpl extends + BaseMpServiceImpl implements SysParameterService, + SysConfService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysParameterVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysParameterVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysParameter findById(Long id) { + + return getBaseMapper().selectById(id); + } + + @Cacheable(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #key", unless = "#result == null") + @Override + public String findByKey(String key) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysParameter.class) + .eq(SysParameter::getPmKey, key); + SysParameter data = getBaseMapper().selectOne(queryWrapper); + + return data == null ? null : data.getPmValue(); + } + + @Override + public String findRequiredByKey(String key) throws ParameterNotFoundException { + SysConfService thisService = getThis(this.getClass()); + String data = thisService.findByKey(key); + if (data == null) { + throw new ParameterNotFoundException(); + } + + return data; + } + + @Override + public String findByKey(String key, String defaultValue) { + SysConfService thisService = getThis(this.getClass()); + String data = thisService.findByKey(key); + if (data == null) { + return defaultValue; + } + + return data; + } + + @OpLog(type = SystemOpLogType.class, name = "新增系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public Long create(CreateSysParameterVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysParameter.class) + .eq(SysParameter::getPmKey, vo.getPmKey()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("键重复,请重新输入!"); + } + SysParameter data = new SysParameter(); + data.setPmKey(vo.getPmKey()); + if (!StringUtil.isEmpty(vo.getPmValue())) { + data.setPmValue(vo.getPmValue()); + } + if (!StringUtil.isBlank(vo.getDescription())) { + data.setDescription(vo.getDescription()); + } + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysParameterVo vo) { + + SysParameter data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("系统参数不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysParameter.class) + .set(SysParameter::getPmValue, StringUtil.isBlank(vo.getPmValue()) ? null : vo.getPmValue()) + .set(SysParameter::getDescription, + StringUtil.isBlank(vo.getDescription()) ? null : vo.getDescription()) + .eq(SysParameter::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SystemOpLogType.class, name = "删除系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(Long id) { + + getBaseMapper().deleteById(id); + } + + @Override + public Boolean getBoolean(String key) { + SysConfService thisService = getThis(getClass()); + String value = thisService.findByKey(key); + return value == null ? null : "true".equalsIgnoreCase(value); + } + + @Override + public Boolean getBoolean(String key, Boolean defaultValue) { + Boolean value = getBoolean(key); + if (value == null) { + return defaultValue; + } + + return value; + } + + @Override + public Integer getInteger(String key) { + SysConfService thisService = getThis(getClass()); + String value = thisService.findByKey(key); + try { + return value == null ? null : Integer.valueOf(value); + } catch (NumberFormatException e) { + // 转换失败 + return null; + } + } + + @Override + public Integer getInteger(String key, Integer defaultValue) { + Integer value = getInteger(key); + if (value == null) { + return defaultValue; + } + + return value; + } + + @Override + public Long getLong(String key) { + SysConfService thisService = getThis(getClass()); + String value = thisService.findByKey(key); + try { + return value == null ? null : Long.valueOf(value); + } catch (NumberFormatException e) { + // 转换失败 + return null; + } + } + + @Override + public Long getLong(String key, Long defaultValue) { + Long value = getLong(key); + if (value == null) { + return defaultValue; + } + + return value; + } + + @CacheEvict(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleCategoryServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleCategoryServiceImpl.java new file mode 100644 index 0000000..1dcdc6f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleCategoryServiceImpl.java @@ -0,0 +1,133 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import com.lframework.starter.web.inner.mappers.system.SysRoleCategoryMapper; +import com.lframework.starter.web.inner.service.system.SysRoleCategoryService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.vo.system.role.category.CreateSysRoleCategoryVo; +import com.lframework.starter.web.inner.vo.system.role.category.SysRoleCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.role.category.UpdateSysRoleCategoryVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysRoleCategoryServiceImpl extends + BaseMpServiceImpl implements + SysRoleCategoryService { + + @Autowired + private SysRoleService sysRoleService; + + @Cacheable(value = SysRoleCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysRoleCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysRoleCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysRoleCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysRoleCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRoleCategory.class) + .eq(SysRoleCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRoleCategory.class) + .eq(SysRoleCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysRoleCategory record = new SysRoleCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysRoleCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRoleCategory.class) + .eq(SysRoleCategory::getCode, vo.getCode()) + .ne(SysRoleCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRoleCategory.class) + .eq(SysRoleCategory::getName, vo.getName()) + .ne(SysRoleCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysRoleCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("角色分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getCategoryId, id).eq(SysRole::getAvailable, true); + if (sysRoleService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类下存在角色,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = SysRoleCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleMenuServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleMenuServiceImpl.java new file mode 100644 index 0000000..b1f917e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleMenuServiceImpl.java @@ -0,0 +1,123 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.security.SecurityConstants; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.entity.SysRoleMenu; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.inner.mappers.system.SysRoleMenuMapper; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import com.lframework.starter.web.inner.service.system.SysRoleMenuService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.vo.system.role.SysRoleMenuSettingVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SysRoleMenuServiceImpl extends + BaseMpServiceImpl implements SysRoleMenuService { + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private SysMenuService sysMenuService; + + @OpLog(type = SystemOpLogType.class, name = "角色授权菜单,角色ID:{},菜单ID:{}", params = { + "#vo.roleIds", + "#vo.menuIds"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysRoleMenuSettingVo vo) { + + for (String roleId : vo.getRoleIds()) { + SysRole role = sysRoleService.findById(roleId); + if (ObjectUtil.isNull(role)) { + throw new DefaultClientException("角色不存在!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(role.getPermission())) { + throw new DefaultClientException( + "角色【" + role.getName() + "】的权限为【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】,不允许授权!"); + } + + this.doSetting(roleId, vo.getMenuIds()); + } + } + + protected void doSetting(String roleId, List menuIds) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysRoleMenu.class) + .eq(SysRoleMenu::getRoleId, roleId); + getBaseMapper().delete(deleteWrapper); + + List records = new ArrayList<>(); + if (!CollectionUtil.isEmpty(menuIds)) { + Set menuIdSet = new HashSet<>(menuIds); + + // 根据所有的menuIds查询父级ID,父级ID需要添加 + for (String menuId : menuIds) { + menuIdSet.addAll(sysMenuService.getParentMenuIds(menuId)); + } + + List allMenus = menuIdSet.stream().map(sysMenuService::findById).collect( + Collectors.toList()); + // 需要判断每一个类型是目录的菜单是否都包含菜单或权限的子菜单 + for (SysMenu menu : allMenus) { + if (menu.getDisplay() != SysMenuDisplay.CATALOG) { + continue; + } + + List parentIds = new ArrayList<>(); + parentIds.add(menu.getId()); + List childrenMenus = new ArrayList<>(); + while (true) { + List children = allMenus.stream() + .filter(t -> parentIds.contains(t.getParentId())).collect( + Collectors.toList()); + if (CollectionUtil.isEmpty(children)) { + break; + } + childrenMenus.addAll(children); + parentIds.clear(); + parentIds.addAll(children.stream().map(SysMenu::getId).collect(Collectors.toList())); + } + + if (childrenMenus.stream().noneMatch(t -> t.getDisplay() == SysMenuDisplay.FUNCTION + || t.getDisplay() == SysMenuDisplay.PERMISSION)) { + throw new DefaultClientException("菜单:“" + menu.getTitle() + "”授权失败,该菜单的类型是“" + + SysMenuDisplay.CATALOG.getDesc() + "”,必须包含子菜单!"); + } + } + for (String menuId : menuIdSet) { + SysRoleMenu record = new SysRoleMenu(); + record.setId(IdUtil.getId()); + record.setRoleId(roleId); + record.setMenuId(menuId); + + records.add(record); + } + } + + if (CollectionUtil.isNotEmpty(records)) { + this.saveBatch(records); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleServiceImpl.java new file mode 100644 index 0000000..c6cb97c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysRoleServiceImpl.java @@ -0,0 +1,273 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.SecurityConstants; +import com.lframework.starter.web.core.event.DataChangeEventBuilder; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.OpLogUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.events.system.DeleteSysRoleEvent; +import com.lframework.starter.web.inner.mappers.system.SysRoleMapper; +import com.lframework.starter.web.inner.service.system.SysMenuService; +import com.lframework.starter.web.inner.service.system.SysRoleService; +import com.lframework.starter.web.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.starter.web.inner.vo.system.role.UpdateSysRoleVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; + +@Service +public class SysRoleServiceImpl extends BaseMpServiceImpl implements + SysRoleService { + + @Autowired + private SysMenuService sysMenuService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysRoleVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysRoleVo vo) { + + return this.doQuery(vo); + } + + @Cacheable(value = SysRole.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysRole findById(String id) { + + return this.doGetById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysRoleSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.doSelector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = SystemOpLogType.class, name = "删除角色,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + SysRole role = this.findById(id); + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(role.getPermission())) { + throw new DefaultClientException( + "角色【" + role.getName() + "】的权限为【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】,不允许删除!"); + } + + this.doDelete(id); + + DataChangeEventBuilder.publishLogicDelete(this, DeleteSysRoleEvent.class, role); + } + + @OpLog(type = SystemOpLogType.class, name = "新增角色,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysRoleVo vo) { + + if (!StringUtil.isBlank(vo.getPermission())) { + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + // 这里的权限不能与菜单权限重复 + if (sysMenuService.existPermission(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + vo.getPermission() + "】为菜单权限,请修改!"); + } + } + + SysRole data = this.doCreate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改角色,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysRoleVo vo) { + + SysRole data = this.findById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("角色不存在!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(data.getPermission())) { + throw new DefaultClientException("角色【" + data.getName() + "】为内置角色,不允许修改!"); + } + + if (!StringUtil.isBlank(vo.getPermission())) { + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + // 这里的权限不能与菜单权限重复 + if (sysMenuService.existPermission(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + vo.getPermission() + "】为菜单权限,请修改!"); + } + } + + this.doUpdate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public List getByUserId(String userId) { + + return this.doGetByUserId(userId); + } + + protected List doQuery(QuerySysRoleVo vo) { + + return getBaseMapper().query(vo); + } + + protected SysRole doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected List doSelector(SysRoleSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected void doDelete(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysRole.class) + .set(SysRole::getAvailable, Boolean.FALSE).eq(SysRole::getId, id); + getBaseMapper().update(updateWrapper); + } + + protected SysRole doCreate(CreateSysRoleVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getCode, vo.getCode()).eq(SysRole::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getName, vo.getName()).eq(SysRole::getAvailable, true); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysRole data = new SysRole(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setCategoryId(vo.getCategoryId()); + + if (!StringUtil.isBlank(vo.getPermission())) { + + data.setPermission(vo.getPermission()); + } + + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doUpdate(UpdateSysRoleVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getCode, vo.getCode()).eq(SysRole::getAvailable, true) + .ne(SysRole::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getName, vo.getName()) + .eq(SysRole::getAvailable, true) + .ne(SysRole::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysRole.class) + .set(SysRole::getCode, vo.getCode()).set(SysRole::getName, vo.getName()) + .set(SysRole::getPermission, null) + .set(SysRole::getCategoryId, vo.getCategoryId()) + .set(SysRole::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SysRole::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getPermission())) { + + updateWrapper.set(SysRole::getPermission, vo.getPermission()); + } + + getBaseMapper().update(updateWrapper); + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } + + @CacheEvict(value = SysRole.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysSiteMessageServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysSiteMessageServiceImpl.java new file mode 100644 index 0000000..280713f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysSiteMessageServiceImpl.java @@ -0,0 +1,121 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.dto.message.site.SiteMessageDto; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.mappers.system.SysSiteMessageMapper; +import com.lframework.starter.web.inner.service.system.SysSiteMessageService; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageByUserVo; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageVo; +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.events.UserConnectEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +@Service +public class SysSiteMessageServiceImpl extends + BaseMpServiceImpl + implements SysSiteMessageService { + + @Autowired + private WsDataPusher wsDataPusher; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysSiteMessageVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysSiteMessageVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysSiteMessageByUserVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryByUser(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public SiteMessageDto getContent(String id) { + SysSiteMessage data = getById(id); + if (data == null) { + return null; + } + return new SiteMessageDto(data); + } + + @Override + public SysSiteMessage findById(String id) { + return getById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean setReaded(String id) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysSiteMessage.class) + .set(SysSiteMessage::getReaded, true) + .set(SysSiteMessage::getReadTime, LocalDateTime.now()) + .eq(SysSiteMessage::getId, id).eq(SysSiteMessage::getReaded, false); + return update(updateWrapper); + } + + @Override + public void noticeForWs(String userId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("siteMessage"); + pushData.setIncludeUserId(userId); + + wsDataPusher.push(pushData); + } + + @Override + public void noticeForWsWithSessionId(String sessionId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("siteMessage"); + pushData.setIncludeSessionIds(Collections.singletonList(sessionId)); + + wsDataPusher.push(pushData); + } + + @Component + public static class ReloadSiteMessageListener implements ApplicationListener { + + @Autowired + private SysSiteMessageService sysSiteMessageService; + + @Override + public void onApplicationEvent(UserConnectEvent event) { + sysSiteMessageService.noticeForWsWithSessionId(event.getSessionId()); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserDeptServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserDeptServiceImpl.java new file mode 100644 index 0000000..a7c3f10 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserDeptServiceImpl.java @@ -0,0 +1,128 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysUserDept; +import com.lframework.starter.web.inner.mappers.system.SysUserDeptMapper; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.vo.system.dept.SysUserDeptSettingVo; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Service +public class SysUserDeptServiceImpl extends + BaseMpServiceImpl implements SysUserDeptService { + + @OpLog(type = SystemOpLogType.class, name = "用户设置部门,用户ID:{},部门ID:{},操作类型:{}", params = { + "#vo.userIds", "#vo.deptIds", "#vo.handleType"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysUserDeptSettingVo vo) { + + this.doSetting(vo); + + SysUserDeptService thisService = getThis(this.getClass()); + thisService.cleanCacheByKeys(vo.getUserIds()); + } + + @Cacheable(value = SysUserDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #userId") + @Override + public List getByUserId(String userId) { + + return doGetByUserId(userId); + } + + @Override + public List getByDeptId(String deptId) { + + return doGetByDeptId(deptId); + } + + @Override + public Boolean hasByDeptId(String deptId) { + + return doHasByDeptId(deptId); + } + + protected void doSetting(SysUserDeptSettingVo vo) { + List records = new ArrayList<>(); + if (vo.getHandleType() == 1) { + // 新增 + if (CollectionUtil.isNotEmpty(vo.getDeptIds())) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserDept.class) + .in(SysUserDept::getUserId, vo.getUserIds()) + .in(SysUserDept::getDeptId, vo.getDeptIds()); + getBaseMapper().delete(deleteWrapper); + for (String userId : vo.getUserIds()) { + for (String deptId : vo.getDeptIds()) { + SysUserDept record = new SysUserDept(); + record.setId(IdUtil.getId()); + record.setUserId(userId); + record.setDeptId(deptId); + records.add(record); + } + } + } + } else if (vo.getHandleType() == 2) { + // 替换 + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserDept.class) + .in(SysUserDept::getUserId, vo.getUserIds()); + getBaseMapper().delete(deleteWrapper); + if (CollectionUtil.isNotEmpty(vo.getDeptIds())) { + for (String userId : vo.getUserIds()) { + for (String deptId : vo.getDeptIds()) { + SysUserDept record = new SysUserDept(); + record.setId(IdUtil.getId()); + record.setUserId(userId); + record.setDeptId(deptId); + records.add(record); + } + } + } + } else if (vo.getHandleType() == 3) { + // 删除 + if (CollectionUtil.isNotEmpty(vo.getDeptIds())) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserDept.class) + .in(SysUserDept::getUserId, vo.getUserIds()) + .in(SysUserDept::getDeptId, vo.getDeptIds()); + getBaseMapper().delete(deleteWrapper); + } + } + + if (CollectionUtil.isNotEmpty(records)) { + this.saveBatch(records); + } + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } + + protected List doGetByDeptId(String deptId) { + + return getBaseMapper().getByDeptId(deptId); + } + + protected Boolean doHasByDeptId(String deptId) { + + return getBaseMapper().hasByDeptId(deptId) != null; + } + + @CacheEvict(value = SysUserDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupDetailServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupDetailServiceImpl.java new file mode 100644 index 0000000..ff3ea0b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupDetailServiceImpl.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysUserGroupDetail; +import com.lframework.starter.web.inner.mappers.system.SysUserGroupDetailMapper; +import com.lframework.starter.web.inner.service.system.SysUserGroupDetailService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysUserGroupDetailServiceImpl extends + BaseMpServiceImpl + implements SysUserGroupDetailService { + + @Override + public List getUserIdsByGroupId(String groupId) { + Wrapper queryWrapper = Wrappers.lambdaQuery( + SysUserGroupDetail.class).select(SysUserGroupDetail::getUserId) + .eq(SysUserGroupDetail::getGroupId, groupId); + return this.list(queryWrapper).stream().map(SysUserGroupDetail::getUserId) + .collect(Collectors.toList()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupServiceImpl.java new file mode 100644 index 0000000..feec1f6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserGroupServiceImpl.java @@ -0,0 +1,184 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.event.DataChangeEventBuilder; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.core.utils.PageHelperUtil; +import com.lframework.starter.web.core.utils.PageResultUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import com.lframework.starter.web.inner.entity.SysUserGroupDetail; +import com.lframework.starter.web.inner.events.system.DeleteSysUserGroupEvent; +import com.lframework.starter.web.inner.mappers.system.SysUserGroupMapper; +import com.lframework.starter.web.inner.service.system.SysUserGroupDetailService; +import com.lframework.starter.web.inner.service.system.SysUserGroupService; +import com.lframework.starter.web.inner.vo.system.user.group.CreateSysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.QuerySysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.SysUserGroupSelectorVo; +import com.lframework.starter.web.inner.vo.system.user.group.UpdateSysUserGroupVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysUserGroupServiceImpl extends + BaseMpServiceImpl implements + SysUserGroupService { + + @Autowired + private SysUserGroupDetailService sysUserGroupDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysUserGroupVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysUserGroupVo vo) { + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysUserGroup.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysUserGroup findById(String id) { + return this.getById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysUserGroupSelectorVo vo) { + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = SystemOpLogType.class, name = "创建用户组,ID:{}", params = "#_result", autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysUserGroupVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysUserGroup.class) + .eq(SysUserGroup::getCode, vo.getCode()).eq(SysUserGroup::getAvailable, true); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号不允许重复!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysUserGroup.class) + .eq(SysUserGroup::getName, vo.getName()).eq(SysUserGroup::getAvailable, true); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称不允许重复!"); + } + + SysUserGroup record = new SysUserGroup(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + this.save(record); + + List detailList = vo.getUserIds().stream().map(t -> { + SysUserGroupDetail r = new SysUserGroupDetail(); + r.setId(IdUtil.getId()); + r.setGroupId(record.getId()); + r.setUserId(t); + + return r; + }).collect(Collectors.toList()); + + sysUserGroupDetailService.saveBatch(detailList); + + return record.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改用户组,ID:{}", params = "#vo.id", autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysUserGroupVo vo) { + + SysUserGroup record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("用户组不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysUserGroup.class) + .eq(SysUserGroup::getCode, vo.getCode()).eq(SysUserGroup::getAvailable, true) + .ne(SysUserGroup::getId, record.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号不允许重复!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysUserGroup.class) + .eq(SysUserGroup::getName, vo.getName()).eq(SysUserGroup::getAvailable, true) + .ne(SysUserGroup::getId, record.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称不允许重复!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysUserGroup.class) + .eq(SysUserGroup::getId, vo.getId()) + .set(SysUserGroup::getName, vo.getName()) + .set(SysUserGroup::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + this.update(updateWrapper); + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + SysUserGroupDetail.class).eq(SysUserGroupDetail::getGroupId, record.getId()); + sysUserGroupDetailService.remove(deleteDetailWrapper); + + List receiverList = vo.getUserIds().stream().map(t -> { + SysUserGroupDetail r = new SysUserGroupDetail(); + r.setId(IdUtil.getId()); + r.setGroupId(record.getId()); + r.setUserId(t); + + return r; + }).collect(Collectors.toList()); + + sysUserGroupDetailService.saveBatch(receiverList); + } + + @OpLog(type = SystemOpLogType.class, name = "删除用户组,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + Wrapper deleteWrapper = Wrappers.lambdaUpdate(SysUserGroup.class) + .eq(SysUserGroup::getId, id).set(SysUserGroup::getAvailable, false); + this.update(deleteWrapper); + + SysUserGroup record = this.findById(id); + DataChangeEventBuilder.publishLogicDelete(this, DeleteSysUserGroupEvent.class, record); + } + + @CacheEvict(value = SysUserGroup.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserRoleServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserRoleServiceImpl.java new file mode 100644 index 0000000..e89ad6f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserRoleServiceImpl.java @@ -0,0 +1,106 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.IdUtil; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.entity.SysUserRole; +import com.lframework.starter.web.inner.mappers.system.SysUserRoleMapper; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import com.lframework.starter.web.inner.vo.system.user.SysUserRoleSettingVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class SysUserRoleServiceImpl extends + BaseMpServiceImpl + implements SysUserRoleService { + + @OpLog(type = SystemOpLogType.class, name = "用户授权角色,用户ID:{},角色ID:{},处理方式:{}", params = { + "#vo.userIds", + "#vo.roleIds", "#vo.handleType"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysUserRoleSettingVo vo) { + + this.doSetting(vo); + } + + @Override + public List getByUserId(String userId) { + + return doGetByUserId(userId); + } + + @Override + public List getByRoleId(String roleId) { + + return doGetByRoleId(roleId); + } + + protected void doSetting(SysUserRoleSettingVo vo) { + List records = new ArrayList<>(); + if (vo.getHandleType() == 1) { + // 新增 + if (CollectionUtil.isNotEmpty(vo.getRoleIds())) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserRole.class) + .in(SysUserRole::getUserId, vo.getUserIds()) + .in(SysUserRole::getRoleId, vo.getRoleIds()); + getBaseMapper().delete(deleteWrapper); + for (String userId : vo.getUserIds()) { + for (String roleId : vo.getRoleIds()) { + SysUserRole record = new SysUserRole(); + record.setId(IdUtil.getId()); + record.setUserId(userId); + record.setRoleId(roleId); + records.add(record); + } + } + } + } else if (vo.getHandleType() == 2) { + // 替换 + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserRole.class) + .in(SysUserRole::getUserId, vo.getUserIds()); + getBaseMapper().delete(deleteWrapper); + if (CollectionUtil.isNotEmpty(vo.getRoleIds())) { + for (String userId : vo.getUserIds()) { + for (String roleId : vo.getRoleIds()) { + SysUserRole record = new SysUserRole(); + record.setId(IdUtil.getId()); + record.setUserId(userId); + record.setRoleId(roleId); + records.add(record); + } + } + } + } else if (vo.getHandleType() == 3) { + // 删除 + if (CollectionUtil.isNotEmpty(vo.getRoleIds())) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserRole.class) + .in(SysUserRole::getUserId, vo.getUserIds()) + .in(SysUserRole::getRoleId, vo.getRoleIds()); + getBaseMapper().delete(deleteWrapper); + } + } + + if (CollectionUtil.isNotEmpty(records)) { + this.saveBatch(records); + } + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } + + protected List doGetByRoleId(String roleId) { + + return getBaseMapper().getByRoleId(roleId); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserServiceImpl.java new file mode 100644 index 0000000..4be1a02 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserServiceImpl.java @@ -0,0 +1,400 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.annotations.oplog.OpLog; +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.components.security.PasswordEncoderWrapper; +import com.lframework.starter.web.core.event.DataChangeEventBuilder; +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.core.utils.*; +import com.lframework.starter.web.inner.components.oplog.SystemOpLogType; +import com.lframework.starter.web.inner.dto.system.UserInfoDto; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.enums.system.Gender; +import com.lframework.starter.web.inner.events.system.DeleteSysUserEvent; +import com.lframework.starter.web.inner.mappers.system.SysUserMapper; +import com.lframework.starter.web.inner.service.GenerateCodeService; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import com.lframework.starter.web.inner.service.system.SysUserService; +import com.lframework.starter.web.inner.vo.system.dept.SysUserDeptSettingVo; +import com.lframework.starter.web.inner.vo.system.user.*; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +@Service +public class SysUserServiceImpl extends BaseMpServiceImpl implements + SysUserService { + + @Autowired + private PasswordEncoderWrapper encoderWrapper; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private GenerateCodeService generateCodeService; + + private static final Integer CODE_KEY = 1; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysUserVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doQuery(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysUserVo vo) { + + return this.doQuery(vo); + } + + @Cacheable(value = SysUser.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysUser findById(String id) { + + return this.doGetById(id); + } + + @Override + public SysUser findByCode(String code) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getCode, code); + return getOne(queryWrapper); + } + + @OpLog(type = SystemOpLogType.class, name = "删除用户,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + this.doDelete(id); + + SysUser user = this.findById(id); + + DataChangeEventBuilder.publishLogicDelete(this, DeleteSysUserEvent.class, user); + } + + @OpLog(type = SystemOpLogType.class, name = "新增用户,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysUserVo vo) { + + SysUser record = this.doCreate(vo); + + SysUserDeptSettingVo deptSettingVo = new SysUserDeptSettingVo(); + deptSettingVo.setHandleType(1); + deptSettingVo.setUserIds(Collections.singletonList(record.getId())); + deptSettingVo.setDeptIds(vo.getDeptIds()); + sysUserDeptService.setting(deptSettingVo); + + SysUserRoleSettingVo roleSettingVo = new SysUserRoleSettingVo(); + roleSettingVo.setUserIds(Collections.singletonList(record.getId())); + roleSettingVo.setRoleIds(vo.getRoleIds()); + roleSettingVo.setHandleType(1); + sysUserRoleService.setting(roleSettingVo); + + OpLogUtil.setVariable("id", record.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return record.getId(); + } + + @OpLog(type = SystemOpLogType.class, name = "修改用户,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysUserVo vo) { + + SysUser data = this.findById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("用户不存在!"); + } + + if (!StringUtil.isBlank(vo.getPassword())) { + if (!RegUtil.isMatch(PatternPool.PATTERN_PASSWORD, vo.getPassword())) { + throw new DefaultClientException( + "密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线!"); + } + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + if (!RegUtil.isMatch(PatternPool.PATTERN_CN_TEL, vo.getTelephone())) { + throw new DefaultClientException("联系电话格式不正确!"); + } + } + + this.doUpdate(vo); + + SysUserDeptSettingVo deptSettingVo = new SysUserDeptSettingVo(); + deptSettingVo.setHandleType(2); + deptSettingVo.setUserIds(Collections.singletonList(vo.getId())); + deptSettingVo.setDeptIds(vo.getDeptIds()); + sysUserDeptService.setting(deptSettingVo); + + SysUserRoleSettingVo roleSettingVo = new SysUserRoleSettingVo(); + roleSettingVo.setUserIds(Collections.singletonList(vo.getId())); + roleSettingVo.setRoleIds(vo.getRoleIds()); + roleSettingVo.setHandleType(2); + sysUserRoleService.setting(roleSettingVo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysUserSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doSelector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void regist(RegistUserVo vo) { + + this.doRegist(vo); + } + + protected List doQuery(QuerySysUserVo vo) { + + return getBaseMapper().query(vo); + } + + protected SysUser doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doDelete(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysUser.class) + .set(SysUser::getAvailable, Boolean.FALSE).eq(SysUser::getId, id); + getBaseMapper().update(updateWrapper); + } + + protected SysUser doCreate(CreateSysUserVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getCode, vo.getCode()).eq(SysUser::getAvailable, true); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkUsernameWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()).eq(SysUser::getAvailable, true); + if (getBaseMapper().selectCount(checkUsernameWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + SysUser record = new SysUser(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setUsername(vo.getUsername()); + record.setPassword(encoderWrapper.getEncoder().encode(vo.getPassword())); + if (!StringUtil.isBlank(vo.getEmail())) { + record.setEmail(vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + record.setTelephone(vo.getTelephone()); + } + + record.setGender(EnumUtil.getByCode(Gender.class, vo.getGender())); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(record); + + return record; + } + + protected void doUpdate(UpdateSysUserVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getCode, vo.getCode()).eq(SysUser::getAvailable, true) + .ne(SysUser::getId, vo.getId()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkUsernameWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()).eq(SysUser::getAvailable, true) + .ne(SysUser::getId, vo.getId()); + if (getBaseMapper().selectCount(checkUsernameWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysUser.class) + .eq(SysUser::getId, vo.getId()).set(SysUser::getCode, vo.getCode()) + .set(SysUser::getUsername, vo.getUsername()) + .set(SysUser::getName, vo.getName()) + .set(SysUser::getEmail, null).set(SysUser::getTelephone, null) + .set(SysUser::getGender, EnumUtil.getByCode(Gender.class, vo.getGender())) + .set(SysUser::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + if (!StringUtil.isBlank(vo.getPassword())) { + updateWrapper.set(SysUser::getPassword, + encoderWrapper.getEncoder().encode(vo.getPassword())); + } + + if (!StringUtil.isBlank(vo.getEmail())) { + updateWrapper.set(SysUser::getEmail, vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + updateWrapper.set(SysUser::getTelephone, vo.getTelephone()); + } + + getBaseMapper().update(updateWrapper); + } + + protected List doSelector(SysUserSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected void doRegist(RegistUserVo vo) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()); + if (getBaseMapper().selectCount(queryWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + SysUser record = new SysUser(); + record.setId(IdUtil.getId()); + record.setCode(generateCodeService.generate(CODE_KEY)); + record.setName(vo.getName()); + record.setUsername(vo.getUsername()); + record.setPassword(encoderWrapper.getEncoder().encode(vo.getPassword())); + if (!StringUtil.isBlank(vo.getEmail())) { + record.setEmail(vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + record.setTelephone(vo.getTelephone()); + } + + record.setGender(Gender.UNKNOWN); + record.setAvailable(Boolean.TRUE); + record.setDescription(StringPool.EMPTY_STR); + + getBaseMapper().insert(record); + } + + @Cacheable(value = UserInfoDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #userId", unless = "#result == null") + @Override + public UserInfoDto getInfo(@NonNull String userId) { + + return this.doGetInfo(userId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updatePassword(@NonNull String userId, @NonNull String password) { + + this.doUpdatePassword(userId, this.encodePassword(password)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateEmail(@NonNull String userId, @NonNull String email) { + + this.doUpdateEmail(userId, email); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateTelephone(@NonNull String userId, @NonNull String telephone) { + + this.doUpdateTelephone(userId, telephone); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void lockById(String id) { + + getBaseMapper().lockById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void unlockById(String id) { + + getBaseMapper().unlockById(id); + } + + protected UserInfoDto doGetInfo(@NonNull String userId) { + + return getBaseMapper().getInfo(userId); + } + + protected void doUpdatePassword(@NonNull String userId, @NonNull String password) { + + getBaseMapper().updatePassword(userId, password); + } + + protected void doUpdateEmail(@NonNull String userId, @NonNull String email) { + + getBaseMapper().updateEmail(userId, email); + } + + protected void doUpdateTelephone(@NonNull String userId, @NonNull String telephone) { + + getBaseMapper().updateTelephone(userId, telephone); + } + + protected String encodePassword(String password) { + + return encoderWrapper.getEncoder().encode(password); + } + + @CacheEvict(value = {UserInfoDto.CACHE_NAME, + SysUser.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserTelephoneServiceImpl.java b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserTelephoneServiceImpl.java new file mode 100644 index 0000000..2ef3b0d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/impl/system/SysUserTelephoneServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.starter.web.inner.impl.system; + +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; +import com.lframework.starter.web.inner.entity.SysUserTelephone; +import com.lframework.starter.web.inner.mappers.system.SysUserTelephoneMapper; +import com.lframework.starter.web.inner.service.system.SysUserTelephoneService; +import org.springframework.stereotype.Service; + +@Service +public class SysUserTelephoneServiceImpl extends + BaseMpServiceImpl implements + SysUserTelephoneService { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/OpLogTimerListener.java b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/OpLogTimerListener.java new file mode 100644 index 0000000..4944af4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/OpLogTimerListener.java @@ -0,0 +1,87 @@ +package com.lframework.starter.web.inner.listeners; + +import com.lframework.starter.web.core.components.qrtz.QrtzHandler; +import com.lframework.starter.web.core.components.qrtz.QrtzJob; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.service.OpLogsService; +import com.lframework.starter.web.inner.service.TenantService; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +@Component +public class OpLogTimerListener implements ApplicationListener { + + private static final String JOB_NAME = "OP_LOG_TIMER"; + + private static final String JOB_GROUP_NAME = "OP_LOG_TIMER_GROUP"; + + private static final String TRIGGER_NAME = "OP_LOG_TIMER_TRIGGER"; + + private static final String TRIGGER_GROUP_NAME = "OP_LOG_TIMER_TRIGGER_GROUP"; + + @Value("${op-logs.enabled:'true'}") + private Boolean enabled; + + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + + // 没有使用@Bean的配置方式是因为当enabled==false时,需要移除定时任务 + JobDetail jobDetail = QrtzHandler.getJob(JOB_NAME, JOB_GROUP_NAME); + if (jobDetail == null) { + // 没有任务 + if (!this.enabled) { + return; + } + + QrtzHandler.addJob(JOB_NAME, JOB_GROUP_NAME, OpLogClearJob.class, TRIGGER_NAME, + TRIGGER_GROUP_NAME, + "0 0 * * * ? *"); + } else { + if (!this.enabled) { + QrtzHandler.deleteJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME); + } + } + } + + public static class OpLogClearJob extends QrtzJob { + + @Autowired + private OpLogsService opLogsService; + + @Autowired + private TenantService tenantService; + + /** + * 操作日志保留天数 + */ + @Value("${op-logs.retain-days:7}") + private Integer retainDays; + + @Override + public void onExecute(JobExecutionContext context) { + + LocalDateTime now = LocalDateTime.now(); + LocalDateTime endTime = now.minusDays(retainDays); + + if (TenantUtil.enableTenant()) { + List tenants = tenantService.list(); + for (Tenant tenant : tenants) { + TenantContextHolder.setTenantId(tenant.getId()); + opLogsService.clearLogs(endTime); + } + } else { + opLogsService.clearLogs(endTime); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysNotifyGroupForDeleteSysUserGroupListener.java b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysNotifyGroupForDeleteSysUserGroupListener.java new file mode 100644 index 0000000..4484ec1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysNotifyGroupForDeleteSysUserGroupListener.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.inner.listeners.app; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.inner.events.system.DeleteSysUserGroupEvent; +import com.lframework.starter.web.inner.service.system.SysNotifyGroupReceiverService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class SysNotifyGroupForDeleteSysUserGroupListener implements + ApplicationListener { + + @Autowired + private SysNotifyGroupReceiverService sysNotifyGroupReceiverService; + + @Override + public void onApplicationEvent(DeleteSysUserGroupEvent event) { + if (sysNotifyGroupReceiverService.hasUserGroup(event.getEntity().getId())) { + throw new DefaultClientException( + "用户分组:" + event.getEntity().getName() + "存在关联的消息通知组,请先解除关联关系!"); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserDeptForDeleteSysDeptListener.java b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserDeptForDeleteSysDeptListener.java new file mode 100644 index 0000000..d932f59 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserDeptForDeleteSysDeptListener.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.listeners.app; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.inner.events.system.DeleteSysDeptEvent; +import com.lframework.starter.web.inner.service.system.SysUserDeptService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class SysUserDeptForDeleteSysDeptListener implements + ApplicationListener { + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Override + public void onApplicationEvent(DeleteSysDeptEvent event) { + String deptId = event.getEntity().getId(); + String deptName = event.getEntity().getName(); + // 判断是否有用户关联了该部门 + Boolean result = sysUserDeptService.hasByDeptId(deptId); + if (result) { + throw new DefaultClientException("部门:" + deptName + "下存在用户,不允许删除!"); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserRoleForDeleteSysRoleListener.java b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserRoleForDeleteSysRoleListener.java new file mode 100644 index 0000000..f9d3e3c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/listeners/app/SysUserRoleForDeleteSysRoleListener.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.listeners.app; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.inner.entity.SysUserRole; +import com.lframework.starter.web.inner.events.system.DeleteSysRoleEvent; +import com.lframework.starter.web.inner.service.system.SysUserRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class SysUserRoleForDeleteSysRoleListener implements + ApplicationListener { + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Override + public void onApplicationEvent(DeleteSysRoleEvent event) { + String roleId = event.getEntity().getId(); + String roleName = event.getEntity().getName(); + // 判断是否有用户关联了该角色 + List result = sysUserRoleService.getByRoleId(roleId); + if (CollectionUtil.isNotEmpty(result)) { + throw new DefaultClientException("角色:" + roleName + "下存在用户,不允许删除!"); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/DicCityMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/DicCityMapper.java new file mode 100644 index 0000000..829e284 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/DicCityMapper.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.dto.dic.city.DicCityDto; +import com.lframework.starter.web.inner.entity.DicCity; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-07 + */ +public interface DicCityMapper extends BaseMapper { + + /** + * 查询所有数据 + * + * @return + */ + List getAll(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + DicCityDto findById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/GenerateCodeMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/GenerateCodeMapper.java new file mode 100644 index 0000000..30263ab --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/GenerateCodeMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.dto.GenerateCodeDto; + +public interface GenerateCodeMapper { + + GenerateCodeDto findById(Integer id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OpLogsMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OpLogsMapper.java new file mode 100644 index 0000000..385ffe6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OpLogsMapper.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.OpLogs; +import com.lframework.starter.web.inner.vo.oplogs.QueryOpLogsVo; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * 操作日志 Mapper + *

+ * + * @author zmj + */ +public interface OpLogsMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryOpLogsVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + OpLogs findById(String id); + + /** + * 根据截止时间删除日志 + * + * @param endTime + */ + void clearLogs(@Param("endTime") LocalDateTime endTime); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OrderTimeLineMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OrderTimeLineMapper.java new file mode 100644 index 0000000..6c4582d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/OrderTimeLineMapper.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.OrderTimeLine; + +/** + * @author zmj + * @since 2022/8/10 + */ +public interface OrderTimeLineMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/QrtzMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/QrtzMapper.java new file mode 100644 index 0000000..6d1170c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/QrtzMapper.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.inner.vo.qrtz.QueryQrtzVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author zmj + * @since 2022/8/20 + */ +public interface QrtzMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryQrtzVo vo); + + /** + * 根据ID查询 + * + * @param name + * @param group + * @return + */ + QrtzDto findById(@Param("name") String name, @Param("group") String group); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/RecursionMappingMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/RecursionMappingMapper.java new file mode 100644 index 0000000..1ba9a5d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/RecursionMappingMapper.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.RecursionMapping; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 递归映射 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-06-27 + */ +public interface RecursionMappingMapper extends BaseMapper { + + List getNodeChildIds(@Param("nodeId") String nodeId, @Param("nodeType") Integer nodeType); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SecurityUploadRecordMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SecurityUploadRecordMapper.java new file mode 100644 index 0000000..f03c7b7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SecurityUploadRecordMapper.java @@ -0,0 +1,13 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SecurityUploadRecord; + +/** + *

+ * 安全上传记录 Mapper 接口 + *

+ */ +public interface SecurityUploadRecordMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleMapper.java new file mode 100644 index 0000000..f92bb1a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysModule; + +public interface SysModuleMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleTenantMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleTenantMapper.java new file mode 100644 index 0000000..0f9479c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/SysModuleTenantMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysModuleTenant; + +public interface SysModuleTenantMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/TenantMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/TenantMapper.java new file mode 100644 index 0000000..b58de0a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/TenantMapper.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.TenantSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TenantMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "id", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QueryTenantVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") TenantSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/UserDetailsMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/UserDetailsMapper.java new file mode 100644 index 0000000..41d672c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/UserDetailsMapper.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.inner.mappers; + +import com.lframework.starter.web.core.components.security.DefaultUserDetails; +import com.lframework.starter.web.core.mapper.BaseMapper; + +/** + * 用于登录的用户信息查询Mapper + * + * @author zmj + */ +public interface UserDetailsMapper extends BaseMapper { + + /** + * 根据登录名查询 + * + * @param username + * @return + */ + DefaultUserDetails findByUsername(String username); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicCategoryMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicCategoryMapper.java new file mode 100644 index 0000000..500f9a3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicCategoryMapper.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 数据字典分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysDataDicCategorySelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicItemMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicItemMapper.java new file mode 100644 index 0000000..c11272a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicItemMapper.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 数据字典值 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicItemMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysDataDicItemVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicMapper.java new file mode 100644 index 0000000..2a5c131 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataDicMapper.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.SysDataDicSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 数据字典 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysDataDicVo vo); + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") SysDataDicSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionDataMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionDataMapper.java new file mode 100644 index 0000000..ee490fd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionDataMapper.java @@ -0,0 +1,9 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; + +public interface SysDataPermissionDataMapper extends + BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionModelDetailMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionModelDetailMapper.java new file mode 100644 index 0000000..d8c8e97 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDataPermissionModelDetailMapper.java @@ -0,0 +1,9 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDataPermissionModelDetail; + +public interface SysDataPermissionModelDetailMapper extends + BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDeptMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDeptMapper.java new file mode 100644 index 0000000..f2e6b87 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysDeptMapper.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysDept; +import com.lframework.starter.web.inner.vo.system.dept.SysDeptSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 部门 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-06-26 + */ +public interface SysDeptMapper extends BaseMapper { + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") SysDeptSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDept findById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysGenerateCodeMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysGenerateCodeMapper.java new file mode 100644 index 0000000..7218f55 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysGenerateCodeMapper.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import com.lframework.starter.web.inner.vo.system.generate.QuerySysGenerateCodeVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface SysGenerateCodeMapper extends + BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "id", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysGenerateCodeVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMailMessageMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMailMessageMapper.java new file mode 100644 index 0000000..3e8fb02 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMailMessageMapper.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import com.lframework.starter.web.inner.vo.system.message.mail.QuerySysMailMessageVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 邮件消息 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysMailMessageMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySysMailMessageVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMenuMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMenuMapper.java new file mode 100644 index 0000000..80bd053 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysMenuMapper.java @@ -0,0 +1,114 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.dto.system.MenuDto; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.vo.system.menu.SysMenuSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + *

+ * 系统菜单 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +public interface SysMenuMapper extends BaseMapper { + + /** + * 系统菜单列表 + * + * @return + */ + List query(@Param("moduleIds") List moduleIds); + + /** + * 根据角色ID查询已授权的菜单 + * + * @param roleId + * @return + */ + List getByRoleId(@Param("roleId") String roleId, + @Param("moduleIds") List moduleIds); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysMenu findById(String id); + + /** + * 系统菜单选择器数据 + * + * @return + */ + List selector(@Param("vo") SysMenuSelectorVo vo, @Param("moduleIds") List moduleIds); + + /** + * 根据ID查询子节点 + * + * @param id + * @return + */ + List getChildrenById(String id); + + /** + * 根据用户ID查询菜单 + * + * @param userId + * @param isAdmin 是否为管理员 + * @return + */ + List getMenuByUserId(@Param("userId") String userId, @Param("isAdmin") boolean isAdmin, + @Param("moduleIds") List moduleIds); + + /** + * 根据用户ID查询收藏的菜单 + * + * @param userId + * @return + */ + List getCollectMenuIds(@Param("userId") String userId); + + /** + * 根据用户ID查询权限 + * + * @param userId + * @return + */ + Set getPermissionsByUserId(@Param("userId") String userId, + @Param("isAdmin") boolean isAdmin, + @Param("moduleIds") List moduleIds); + + /** + * 根据用户ID查询角色权限 + * + * @param userId + * @return + */ + Set getRolePermissionByUserId(@Param("userId") String userId); + + /** + * 收藏菜单 + * + * @param id + * @param userId + * @param menuId + */ + void collectMenu(@Param("id") String id, @Param("userId") String userId, + @Param("menuId") String menuId); + + /** + * 取消收藏菜单 + * + * @param userId + * @param menuId + */ + void cancelCollectMenu(@Param("userId") String userId, @Param("menuId") String menuId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeLogMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeLogMapper.java new file mode 100644 index 0000000..895490c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeLogMapper.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysNoticeLog; + +/** + *

+ * 系统通知记录 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNoticeLogMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeMapper.java new file mode 100644 index 0000000..c485187 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNoticeMapper.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.inner.entity.SysNotice; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统通知 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNoticeMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySysNoticeVo vo); + + /** + * 设置已读 + * + * @param id + */ + void setReaded(String id); + + /** + * 根据用户查询 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + List queryByUser(@Param("vo") QuerySysNoticeByUserVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupMapper.java new file mode 100644 index 0000000..ae5cfd5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupMapper.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.vo.system.notify.QuerySysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.SysNotifyGroupSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 消息通知组 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNotifyGroupMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "name", alias = "tb.name"), + @Sort(value = "createTime", alias = "tb.create_time"), + }) + List query(@Param("vo") QuerySysNotifyGroupVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysNotifyGroupSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupReceiverMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupReceiverMapper.java new file mode 100644 index 0000000..e6eeb64 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysNotifyGroupReceiverMapper.java @@ -0,0 +1,22 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysNotifyGroupReceiver; + +/** + *

+ * 消息通知组-接收者关系表 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNotifyGroupReceiverMapper extends BaseMapper { + + /** + * 判断是否存在用户组 + * + * @param userGroupId + * @return + */ + Boolean hasUserGroup(String userGroupId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysOpenDomainMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysOpenDomainMapper.java new file mode 100644 index 0000000..bd8a376 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysOpenDomainMapper.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import com.lframework.starter.web.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.starter.web.inner.vo.system.open.SysOpenDomainSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +public interface SysOpenDomainMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "id", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "tenantId", autoParse = true), + }) + List query(@Param("vo") QuerySysOpenDomainVo vo); + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") SysOpenDomainSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysParameterMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysParameterMapper.java new file mode 100644 index 0000000..fcd965c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysParameterMapper.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysParameter; +import com.lframework.starter.web.inner.vo.system.parameter.QuerySysParameterVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统参数 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysParameterMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "pmKey", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysParameterVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleCategoryMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleCategoryMapper.java new file mode 100644 index 0000000..b60c0ce --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleCategoryMapper.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import com.lframework.starter.web.inner.vo.system.role.category.SysRoleCategorySelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 角色分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysRoleCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysRoleCategorySelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMapper.java new file mode 100644 index 0000000..b94f67d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMapper.java @@ -0,0 +1,60 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.SysRoleSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +public interface SysRoleMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QuerySysRoleVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysRole findById(String id); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysRoleSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMenuMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMenuMapper.java new file mode 100644 index 0000000..4879966 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysRoleMenuMapper.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysRoleMenu; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysRoleMenuMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysSiteMessageMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysSiteMessageMapper.java new file mode 100644 index 0000000..15701ba --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysSiteMessageMapper.java @@ -0,0 +1,35 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageByUserVo; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 站内信 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysSiteMessageMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySysSiteMessageVo vo); + + /** + * 根据用户查询 + * + * @param vo + * @return + */ + List queryByUser(@Param("vo") QuerySysSiteMessageByUserVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserDeptMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserDeptMapper.java new file mode 100644 index 0000000..0dd86f6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserDeptMapper.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysUserDept; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserDeptMapper extends BaseMapper { + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据部门ID查询 + * + * @param deptId + * @return + */ + List getByDeptId(String deptId); + + /** + * 根据部门ID查询是否存在 + * + * @param deptId + * @return + */ + SysUserDept hasByDeptId(String deptId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupDetailMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupDetailMapper.java new file mode 100644 index 0000000..8df8b27 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysUserGroupDetail; + +/** + *

+ * 用户与用户组关系表 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysUserGroupDetailMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupMapper.java new file mode 100644 index 0000000..02dd2d6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserGroupMapper.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import com.lframework.starter.web.inner.vo.system.user.group.QuerySysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.SysUserGroupSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户组 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysUserGroupMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb.code"), + @Sort(value = "name", alias = "tb.name"), + @Sort(value = "createTime", alias = "tb.create_time"), + }) + List query(@Param("vo") QuerySysUserGroupVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysUserGroupSelectorVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserMapper.java new file mode 100644 index 0000000..4f39b1f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserMapper.java @@ -0,0 +1,100 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.annotations.sort.Sort; +import com.lframework.starter.web.core.annotations.sort.Sorts; +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.dto.system.UserInfoDto; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.vo.system.user.QuerySysUserVo; +import com.lframework.starter.web.inner.vo.system.user.SysUserSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "u", autoParse = true), + @Sort(value = "username", alias = "u", autoParse = true), + @Sort(value = "name", alias = "u", autoParse = true), + @Sort(value = "createTime", alias = "u", autoParse = true), + @Sort(value = "updateTime", alias = "u", autoParse = true), + }) + List query(@Param("vo") QuerySysUserVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysUser findById(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysUserSelectorVo vo); + + /** + * 获取用户信息 + * + * @param userId 用户ID + * @return + */ + UserInfoDto getInfo(String userId); + + /** + * 修改用户密码 + * + * @param userId 用户ID + * @param password 新密码(密文) + */ + void updatePassword(@Param("userId") String userId, @Param("password") String password); + + /** + * 修改邮箱 + * + * @param userId 用户ID + * @param email 邮箱 + */ + void updateEmail(@Param("userId") String userId, @Param("email") String email); + + /** + * 修改联系电话 + * + * @param userId 用户ID + * @param telephone 联系电话 + */ + void updateTelephone(@Param("userId") String userId, @Param("telephone") String telephone); + + /** + * 根据ID锁定 + * + * @param id + */ + void lockById(String id); + + /** + * 根据ID解锁 + * + * @param id + */ + void unlockById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserRoleMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserRoleMapper.java new file mode 100644 index 0000000..7f26b8d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserRoleMapper.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysUserRole; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserRoleMapper extends BaseMapper { + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据角色ID查询 + * + * @param roleId + * @return + */ + List getByRoleId(String roleId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserTelephoneMapper.java b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserTelephoneMapper.java new file mode 100644 index 0000000..f926b43 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/mappers/system/SysUserTelephoneMapper.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.inner.mappers.system; + +import com.lframework.starter.web.core.mapper.BaseMapper; +import com.lframework.starter.web.inner.entity.SysUserTelephone; + +public interface SysUserTelephoneMapper extends BaseMapper { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/DicCityService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/DicCityService.java new file mode 100644 index 0000000..524da75 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/DicCityService.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.dto.dic.city.DicCityDto; +import com.lframework.starter.web.inner.entity.DicCity; + +import java.util.List; + +public interface DicCityService extends BaseMpService { + + /** + * 查询所有数据 + * + * @return + */ + List getAll(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + DicCityDto findById(String id); + + /** + * 根据ID查询链路数据 + * + * @param id 末级ID + * @return 返回值顺序:省、市、区 + */ + List getChainById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/GenerateCodeService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/GenerateCodeService.java new file mode 100644 index 0000000..b239906 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/GenerateCodeService.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.components.generator.rule.GenerateCodeRule; +import com.lframework.starter.web.core.dto.GenerateCodeDto; +import com.lframework.starter.web.core.service.BaseService; + +import java.util.List; + +/** + * 生成单号Service + * + * @author zmj + */ +public interface GenerateCodeService extends BaseService { + + /** + * 生成code + * + * @param id + * @return + */ + String generate(Integer id); + + /** + * 根据实体类获取编号规则 + * + * @param entity + * @return + */ + List getRules(GenerateCodeDto entity); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/GroovySupportService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/GroovySupportService.java new file mode 100644 index 0000000..2efe3f4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/GroovySupportService.java @@ -0,0 +1,10 @@ +package com.lframework.starter.web.inner.service; + +/** + * 支持groovy脚本调用的service + *

+ * 在GroovyUtil#getShell中使用 + */ +public interface GroovySupportService { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/MailService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/MailService.java new file mode 100644 index 0000000..d9c5c6d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/MailService.java @@ -0,0 +1,75 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseService; + +import java.io.File; +import java.util.List; + +public interface MailService extends BaseService { + + /** + * 发送邮件 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @return message-id + */ + String send(String to, String subject, String content); + + /** + * 发送邮件 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param isHtml – 是否为HTML格式 + * @return message-id + */ + String send(String to, String subject, String content, boolean isHtml); + + /** + * 发送邮件 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param isHtml – 是否为HTML格式 + * @param files – 附件列表 + * @return message-id + */ + String send(String to, String subject, String content, boolean isHtml, File... files); + + /** + * 发送邮件 + * + * @param tos 收件人 + * @param subject 标题 + * @param content 正文 + * @return message-id + */ + String send(List tos, String subject, String content); + + /** + * 发送邮件 + * + * @param tos 收件人 + * @param subject 标题 + * @param content 正文 + * @param isHtml – 是否为HTML格式 + * @return message-id + */ + String send(List tos, String subject, String content, boolean isHtml); + + /** + * 发送邮件 + * + * @param tos 收件人 + * @param subject 标题 + * @param content 正文 + * @param isHtml – 是否为HTML格式 + * @param files – 附件列表 + * @return message-id + */ + String send(List tos, String subject, String content, boolean isHtml, File... files); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/OpLogsService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/OpLogsService.java new file mode 100644 index 0000000..383726e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/OpLogsService.java @@ -0,0 +1,59 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.OpLogs; +import com.lframework.starter.web.inner.vo.oplogs.CreateOpLogsVo; +import com.lframework.starter.web.inner.vo.oplogs.QueryOpLogsVo; + +import java.time.LocalDateTime; +import java.util.Collection; + +/** + * 操作日志Service + * + * @author zmj + */ +public interface OpLogsService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateOpLogsVo vo); + + /** + * 创建 + * + * @param list + * @return + */ + void create(Collection list); + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryOpLogsVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + OpLogs findById(String id); + + /** + * 根据截止时间删除日志 + * + * @param endTime + */ + void clearLogs(LocalDateTime endTime); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/OrderTimeLineService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/OrderTimeLineService.java new file mode 100644 index 0000000..6966c64 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/OrderTimeLineService.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.OrderTimeLine; + +import java.util.List; + +/** + * @author zmj + * @since 2022/8/10 + */ +public interface OrderTimeLineService extends BaseMpService { + + /** + * 根据订单查询 + * @param orderId + * @return + */ + List getByOrder(String orderId); + + /** + * 根据订单删除 + * @param orderId + */ + void deleteByOrder(String orderId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/QrtzService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/QrtzService.java new file mode 100644 index 0000000..118d098 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/QrtzService.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseService; +import com.lframework.starter.web.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.starter.web.inner.vo.qrtz.UpdateQrtzVo; + +/** + * @author zmj + * @since 2022/8/20 + */ +public interface QrtzService extends BaseService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryQrtzVo vo); + + /** + * 根据ID查询 + * + * @param name + * @param group + * @return + */ + QrtzDto findById(String name, String group); + + /** + * 创建 + * + * @param vo + */ + void create(CreateQrtzVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateQrtzVo vo); + + /** + * 恢复 + * + * @param name + * @param group + */ + void resume(String name, String group); + + /** + * 暂停 + * + * @param name + * @param group + */ + void pause(String name, String group); + + /** + * 触发 + * + * @param name + * @param group + */ + void trigger(String name, String group); + + /** + * 删除 + * + * @param name + * @param group + */ + void delete(String name, String group); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/RecursionMappingService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/RecursionMappingService.java new file mode 100644 index 0000000..6185f94 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/RecursionMappingService.java @@ -0,0 +1,63 @@ +package com.lframework.starter.web.inner.service; + + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.RecursionMapping; +import com.lframework.starter.web.inner.enums.system.NodeType; + +import java.util.List; + +public interface RecursionMappingService extends BaseMpService { + + /** + * 查询节点的父节点ID + * + * @param nodeId + * @param nodeTypeClazz + * @return + */ + List getNodeParentIds(String nodeId, Class nodeTypeClazz); + + /** + * 查询节点的子节点ID + * + * @param nodeId + * @param nodeTypeClazz + * @return + */ + List getNodeChildIds(String nodeId, Class nodeTypeClazz); + + + /** + * 保存节点递归信息 + * + * @param nodeId + * @param nodeTypeClazz + * @param parentIds 顺序有意义,需要从顶点到终点的顺序排列 + */ + void saveNode(String nodeId, Class nodeTypeClazz, List parentIds); + + /** + * 保存节点递归信息 + * + * @param nodeId + * @param nodeTypeClazz + */ + void saveNode(String nodeId, Class nodeTypeClazz); + + /** + * 根据节点ID删除 + * + * @param nodeId + * @param nodeTypeClazz + */ + void deleteNode(String nodeId, Class nodeTypeClazz); + + /** + * 根据节点ID删除以及子节点 + * + * @param nodeId + * @param nodeTypeClazz + */ + void deleteNodeAndChildren(String nodeId, Class nodeTypeClazz); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/SecurityUploadRecordService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SecurityUploadRecordService.java new file mode 100644 index 0000000..d5b60ba --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SecurityUploadRecordService.java @@ -0,0 +1,19 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SecurityUploadRecord; + +/** + * 安全上传记录 Service + */ +public interface SecurityUploadRecordService extends BaseMpService { + + /** + * 新增 + * + * @param uploadType + * @param filePath + * @return + */ + String create(String uploadType, String filePath); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysConfService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysConfService.java new file mode 100644 index 0000000..b5dd130 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysConfService.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.common.exceptions.impl.ParameterNotFoundException; +import com.lframework.starter.web.core.service.BaseService; + +public interface SysConfService extends BaseService { + + /** + * 根据Key查询 + * + * @param key + * @return 如果不存在则返回null + */ + String findByKey(String key); + + /** + * 根据Key查询 + * + * @param key + * @return 如果不存在则抛异常 + */ + String findRequiredByKey(String key) throws ParameterNotFoundException; + + /** + * 根据Key查询 如果value不存在则返回defaultValue + * + * @param key + * @param defaultValue + * @return + */ + String findByKey(String key, String defaultValue); + + /** + * 根据Key查询Boolean + * + * @param key + * @return + */ + Boolean getBoolean(String key); + + /** + * 根据Key查询Boolean + * + * @param key + * @return + */ + Boolean getBoolean(String key, Boolean defaultValue); + + /** + * 根据Key查询Integer + * + * @param key + * @return + */ + Integer getInteger(String key); + + /** + * 根据Key查询Integer + * + * @param key + * @return + */ + Integer getInteger(String key, Integer defaultValue); + + /** + * 根据Key查询Long + * + * @param key + * @return + */ + Long getLong(String key); + + /** + * 根据Key查询Long + * + * @param key + * @return + */ + Long getLong(String key, Long defaultValue); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleService.java new file mode 100644 index 0000000..9e7c217 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleService.java @@ -0,0 +1,7 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysModule; + +public interface SysModuleService extends BaseMpService { +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleTenantService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleTenantService.java new file mode 100644 index 0000000..ac10424 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/SysModuleTenantService.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysModuleTenant; +import com.lframework.starter.web.inner.vo.system.module.SysModuleTenantVo; + +import java.util.List; + +public interface SysModuleTenantService extends BaseMpService { + + /** + * 根据租户ID查询可用模块ID + * + * @param tenantId + * @return + */ + List getAvailableModuleIdsByTenantId(Integer tenantId); + + /** + * 根据租户ID查询 + * @param tenantId + * @return + */ + List getByTenantId(Integer tenantId); + + /** + * 设置模块 + * @param vo + */ + void setting(SysModuleTenantVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/TenantService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/TenantService.java new file mode 100644 index 0000000..37f7943 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/TenantService.java @@ -0,0 +1,69 @@ +package com.lframework.starter.web.inner.service; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.Tenant; +import com.lframework.starter.web.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.starter.web.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.starter.web.inner.vo.system.tenant.UpdateTenantVo; + +import java.util.List; + +/** + * 租户Service + * + * @author zmj + */ +public interface TenantService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryTenantVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, TenantSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Tenant findById(Integer id); + + /** + * 查询所有租户信息 + * + * @return + */ + List findAll(); + + /** + * 新增 + * + * @param data + * @return + */ + Integer create(CreateTenantVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateTenantVo data); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicCategoryService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicCategoryService.java new file mode 100644 index 0000000..ad1debf --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicCategoryService.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.starter.web.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; + +import java.util.List; + +/** + * 数据字典分类 Service + * + * @author zmj + */ +public interface SysDataDicCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDicCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicItemService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicItemService.java new file mode 100644 index 0000000..9bebc53 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicItemService.java @@ -0,0 +1,82 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDataDicItem; +import com.lframework.starter.web.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.starter.web.inner.vo.system.dic.item.UpdateSysDataDicItemVo; + +import java.util.List; + +/** + * 数据字典值 Service + * + * @author zmj + */ +public interface SysDataDicItemService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicItemVo vo); + + /** + * 查询列表 + * + * @return + */ + List query(QuerySysDataDicItemVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDicItem findById(String id); + + /** + * 根据字典Code、字典值Code查询 + * + * @param dicCode + * @param code + * @return + */ + SysDataDicItem findByCode(String dicCode, String code); + + /** + * 根据字典编号查询 + * + * @param dicCode + * @return + */ + List findByDicCode(String dicCode); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicItemVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicItemVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicService.java new file mode 100644 index 0000000..2e3c0d4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataDicService.java @@ -0,0 +1,76 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDataDic; +import com.lframework.starter.web.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.starter.web.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.starter.web.inner.vo.system.dic.UpdateSysDataDicVo; + +import java.util.List; + +/** + * 数据字典 Service + * + * @author zmj + */ +public interface SysDataDicService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicVo vo); + + /** + * 查询列表 + * + * @return + */ + List query(QuerySysDataDicVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysDataDicSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDic findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionDataService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionDataService.java new file mode 100644 index 0000000..e1be11d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionDataService.java @@ -0,0 +1,27 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDataPermissionData; + +import java.util.List; + +public interface SysDataPermissionDataService extends + BaseMpService { + + /** + * 根据业务ID查询 + * + * @param bizId + * @return + */ + List getByBizId(String bizId); + + /** + * 根据业务ID查询 + * + * @param bizId + * @param bizType + * @return + */ + SysDataPermissionData getByBizId(String bizId, Integer bizType, Integer permissionType); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionModelDetailService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionModelDetailService.java new file mode 100644 index 0000000..808ff25 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDataPermissionModelDetailService.java @@ -0,0 +1,30 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDataPermissionModelDetail; +import com.lframework.starter.web.inner.vo.system.permission.SysDataPermissionModelDetailVo; + +import java.util.List; +import java.util.Map; + +public interface SysDataPermissionModelDetailService extends + BaseMpService { + + /** + * 解析SQL + * + * @param models + * @return + */ + String toSql(List models); + + /** + * 格式化SQL + * + * @param sqlTemplate + * @param params 表别名Map Key:表名占位符,具体定义数据表中的table_name Value:具体SQL的别名 + * @return + */ + String formatSql(String sqlTemplate, Map params); + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDeptService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDeptService.java new file mode 100644 index 0000000..0d44827 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysDeptService.java @@ -0,0 +1,57 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysDept; +import com.lframework.starter.web.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.starter.web.inner.vo.system.dept.SysDeptSelectorVo; +import com.lframework.starter.web.inner.vo.system.dept.UpdateSysDeptVo; + +import java.util.List; + +public interface SysDeptService extends BaseMpService { + + /** + * 选择器 + * + * @return + */ + List selector(SysDeptSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDept findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + SysDept findByCode(String code); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDeptVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDeptVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysGenerateCodeService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysGenerateCodeService.java new file mode 100644 index 0000000..baab69d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysGenerateCodeService.java @@ -0,0 +1,72 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysGenerateCode; +import com.lframework.starter.web.inner.vo.system.generate.CreateSysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.QuerySysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.SettingSysGenerateCodeVo; +import com.lframework.starter.web.inner.vo.system.generate.UpdateSysGenerateCodeVo; + +import java.util.List; + +/** + * 编号规则 Service + * + * @author zmj + */ +public interface SysGenerateCodeService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysGenerateCodeVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysGenerateCodeVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysGenerateCode findById(Integer id); + + /** + * 创建 + * + * @param vo + * @return + */ + Integer create(CreateSysGenerateCodeVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysGenerateCodeVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(Integer id); + + /** + * 设置 + * + * @param vo + */ + void setting(SettingSysGenerateCodeVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMailMessageService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMailMessageService.java new file mode 100644 index 0000000..5d8bdca --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMailMessageService.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysMailMessage; +import com.lframework.starter.web.inner.vo.system.message.mail.QuerySysMailMessageVo; + +import java.util.List; + +public interface SysMailMessageService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysMailMessageVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysMailMessageVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysMailMessage findById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMenuService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMenuService.java new file mode 100644 index 0000000..e800c96 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysMenuService.java @@ -0,0 +1,142 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.dto.system.MenuDto; +import com.lframework.starter.web.inner.entity.SysMenu; +import com.lframework.starter.web.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.starter.web.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.starter.web.inner.vo.system.menu.UpdateSysMenuVo; + +import java.util.List; +import java.util.Set; + +/** + *

+ * 系统菜单 服务类 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +public interface SysMenuService extends BaseMpService { + + /** + * 系统菜单列表 + * + * @return + */ + List queryList(List moduleIds); + + /** + * 根据角色ID查询已授权的菜单 + * + * @param roleId + * @return + */ + List getByRoleId(String roleId, List moduleIds); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysMenu findById(String id); + + /** + * 创建系统菜单 + * + * @param vo + */ + String create(CreateSysMenuVo vo); + + /** + * 修改系统菜单 + * + * @param vo + */ + void update(UpdateSysMenuVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 系统菜单选择器数据 + * + * @return + */ + List selector(SysMenuSelectorVo vo, List moduleIds); + + /** + * 批量启用 + * + * @param id + */ + void enable(String id); + + /** + * 停用 + * + * @param id + */ + void unable(String id); + + /** + * 是否存在权限 + * + * @param permission + * @return + */ + Boolean existPermission(String permission); + + /** + * 根据用户ID查询菜单 + * + * @param userId + * @param isAdmin 是否为管理员 + * @return + */ + List getMenuByUserId(String userId, boolean isAdmin, List moduleIds); + + /** + * 根据用户ID查询权限 + * + * @param userId + * @return + */ + Set getPermissionsByUserId(String userId, boolean isAdmin, List moduleIds); + + /** + * 根据用户ID查询角色权限 + * @param userId + * @return + */ + Set getRolePermissionByUserId(String userId); + + /** + * 收藏菜单 + * + * @param userId + * @param menuId + */ + void collect(String userId, String menuId); + + /** + * 取消收藏菜单 + * + * @param userId + * @param menuId + */ + void cancelCollect(String userId, String menuId); + + /** + * 根据菜单ID查询父级菜单ID + * @param menuId + * @return + */ + List getParentMenuIds(String menuId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeLogService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeLogService.java new file mode 100644 index 0000000..7031f7e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeLogService.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysNoticeLog; + +/** + * 系统通知记录 Service + * + * @author zmj + */ +public interface SysNoticeLogService extends BaseMpService { + + /** + * 设置已读 + * + * @param noticeId + * @param userId + */ + boolean setReaded(String noticeId, String userId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeService.java new file mode 100644 index 0000000..233a966 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNoticeService.java @@ -0,0 +1,109 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.inner.dto.system.notice.SysNoticeDto; +import com.lframework.starter.web.inner.entity.SysNotice; +import com.lframework.starter.web.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.starter.web.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.starter.web.inner.vo.system.notice.UpdateSysNoticeVo; + +import java.util.List; + +/** + * 系统通知 Service + * + * @author zmj + */ +public interface SysNoticeService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysNoticeVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysNoticeVo vo); + + /** + * 根据用户查询 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysNoticeByUserVo vo); + + /** + * 根据ID查询内容 + * + * @param id + * @return + */ + SysNoticeDto getContent(String id); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysNotice findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysNoticeVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysNoticeVo vo); + + /** + * 发布 + * + * @param id + */ + void publish(String id); + + /** + * 设置已读 + * + * @param id + * @param userId + */ + void setReaded(String id, String userId); + + /** + * 发送通知 + */ + void noticeForWs(); + + /** + * 发送通知 + */ + void noticeForWs(String userId); + + /** + * 发送通知 + */ + void noticeForWsWithSessionId(String sessionId); + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupReceiverService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupReceiverService.java new file mode 100644 index 0000000..babd2bc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupReceiverService.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysNotifyGroupReceiver; + +import java.util.List; + +public interface SysNotifyGroupReceiverService extends BaseMpService { + + /** + * 根据组ID查询接收方ID + * + * @param groupId + * @return + */ + List getReceiverIdsByGroupId(String groupId); + + /** + * 是否存在用户组 + * + * @param userGroupId + * @return + */ + Boolean hasUserGroup(String userGroupId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupService.java new file mode 100644 index 0000000..6f7f57d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysNotifyGroupService.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysNotifyGroup; +import com.lframework.starter.web.inner.vo.system.notify.CreateSysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.QuerySysNotifyGroupVo; +import com.lframework.starter.web.inner.vo.system.notify.SysNotifyGroupSelectorVo; +import com.lframework.starter.web.inner.vo.system.notify.UpdateSysNotifyGroupVo; + +import java.util.List; +import java.util.Set; + +public interface SysNotifyGroupService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QuerySysNotifyGroupVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysNotifyGroupVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysNotifyGroup findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysNotifyGroupSelectorVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysNotifyGroupVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysNotifyGroupVo vo); + + /** + * 根据ID查询接收人ID + * + * @param id + * @return + */ + Set getReceiveUserIds(String id); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysOpenDomainService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysOpenDomainService.java new file mode 100644 index 0000000..7f09d0d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysOpenDomainService.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysOpenDomain; +import com.lframework.starter.web.inner.vo.system.open.*; + +public interface SysOpenDomainService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(QuerySysOpenDomainVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(SysOpenDomainSelectorVo vo); + + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysOpenDomain findById(Integer id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysOpenDomainVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysOpenDomainVo vo); + + /** + * 修改Api密钥 + * + * @param vo + */ + void updateApiSecret(UpdateSysOpenDomainSecretVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysParameterService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysParameterService.java new file mode 100644 index 0000000..897d004 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysParameterService.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysParameter; +import com.lframework.starter.web.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.starter.web.inner.vo.system.parameter.UpdateSysParameterVo; + +import java.util.List; + +/** + * 系统参数 Service + * + * @author zmj + */ +public interface SysParameterService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysParameterVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysParameterVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysParameter findById(Long id); + + /** + * 创建 + * + * @param vo + * @return + */ + Long create(CreateSysParameterVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysParameterVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(Long id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleCategoryService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleCategoryService.java new file mode 100644 index 0000000..ffd6e93 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleCategoryService.java @@ -0,0 +1,64 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysRoleCategory; +import com.lframework.starter.web.inner.vo.system.role.category.CreateSysRoleCategoryVo; +import com.lframework.starter.web.inner.vo.system.role.category.SysRoleCategorySelectorVo; +import com.lframework.starter.web.inner.vo.system.role.category.UpdateSysRoleCategoryVo; + +import java.util.List; + +/** + * 角色分类 Service + * + * @author zmj + */ +public interface SysRoleCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysRoleCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysRoleCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysRoleCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysRoleCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleMenuService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleMenuService.java new file mode 100644 index 0000000..8aa2887 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleMenuService.java @@ -0,0 +1,15 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysRoleMenu; +import com.lframework.starter.web.inner.vo.system.role.SysRoleMenuSettingVo; + +public interface SysRoleMenuService extends BaseMpService { + + /** + * 授权角色菜单 + * + * @param vo + */ + void setting(SysRoleMenuSettingVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleService.java new file mode 100644 index 0000000..bd571c0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysRoleService.java @@ -0,0 +1,74 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysRole; +import com.lframework.starter.web.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.starter.web.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.starter.web.inner.vo.system.role.UpdateSysRoleVo; + +import java.util.List; + +public interface SysRoleService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysRoleVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysRoleVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysRole findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysRoleSelectorVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysRoleVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysRoleVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysSiteMessageService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysSiteMessageService.java new file mode 100644 index 0000000..f6b3a93 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysSiteMessageService.java @@ -0,0 +1,77 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.dto.message.site.SiteMessageDto; +import com.lframework.starter.web.inner.entity.SysSiteMessage; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageByUserVo; +import com.lframework.starter.web.inner.vo.system.message.site.QuerySysSiteMessageVo; + +import java.util.List; + +public interface SysSiteMessageService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysSiteMessageVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysSiteMessageVo vo); + + /** + * 根据用户查询 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysSiteMessageByUserVo vo); + + /** + * 查询内容 + * + * @param id + * @return + */ + SiteMessageDto getContent(String id); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysSiteMessage findById(String id); + + /** + * 设置已读 + * + * @param id + */ + boolean setReaded(String id); + + /** + * WS通知 + * + * @param userId + */ + void noticeForWs(String userId); + + /** + * 发送通知 + */ + void noticeForWsWithSessionId(String sessionId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserDeptService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserDeptService.java new file mode 100644 index 0000000..2f7031b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserDeptService.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysUserDept; +import com.lframework.starter.web.inner.vo.system.dept.SysUserDeptSettingVo; + +import java.util.List; + +public interface SysUserDeptService extends BaseMpService { + + /** + * 设置部门 + * + * @param vo + */ + void setting(SysUserDeptSettingVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据部门ID查询 + * + * @param deptId + * @return + */ + List getByDeptId(String deptId); + + /** + * 根据部门ID查询是否存在 + * + * @param deptId + * @return + */ + Boolean hasByDeptId(String deptId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupDetailService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupDetailService.java new file mode 100644 index 0000000..d46c219 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupDetailService.java @@ -0,0 +1,17 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysUserGroupDetail; + +import java.util.List; + +public interface SysUserGroupDetailService extends BaseMpService { + + /** + * 根据组ID查询用户ID + * + * @param groupId + * @return + */ + List getUserIdsByGroupId(String groupId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupService.java new file mode 100644 index 0000000..0275901 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserGroupService.java @@ -0,0 +1,71 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysUserGroup; +import com.lframework.starter.web.inner.vo.system.user.group.CreateSysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.QuerySysUserGroupVo; +import com.lframework.starter.web.inner.vo.system.user.group.SysUserGroupSelectorVo; +import com.lframework.starter.web.inner.vo.system.user.group.UpdateSysUserGroupVo; + +import java.util.List; + +public interface SysUserGroupService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QuerySysUserGroupVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysUserGroupVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysUserGroup findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysUserGroupSelectorVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysUserGroupVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysUserGroupVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserRoleService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserRoleService.java new file mode 100644 index 0000000..06a0908 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserRoleService.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysUserRole; +import com.lframework.starter.web.inner.vo.system.user.SysUserRoleSettingVo; + +import java.util.List; + +public interface SysUserRoleService extends BaseMpService { + + /** + * 用户授权 + * + * @param vo + */ + void setting(SysUserRoleSettingVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据角色ID查询 + * @param roleId + * @return + */ + List getByRoleId(String roleId); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserService.java new file mode 100644 index 0000000..f403030 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserService.java @@ -0,0 +1,131 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.components.resp.PageResult; +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.dto.system.UserInfoDto; +import com.lframework.starter.web.inner.entity.SysUser; +import com.lframework.starter.web.inner.vo.system.user.*; + +import java.util.List; + +public interface SysUserService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysUserVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysUserVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysUser findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + SysUser findByCode(String code); + + /** + * 停用 + * + * @param id + */ + void deleteById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysUserVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysUserVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysUserSelectorVo vo); + + /** + * 注册 + * + * @param vo + */ + void regist(RegistUserVo vo); + + /** + * 获取用户信息 + * + * @param userId 用户ID + * @return + */ + UserInfoDto getInfo(String userId); + + /** + * 修改用户密码 + * + * @param userId 用户ID + * @param password 新密码(明文) + */ + void updatePassword(String userId, String password); + + /** + * 修改邮箱 + * + * @param userId 用户ID + * @param email 邮箱 + */ + void updateEmail(String userId, String email); + + /** + * 修改联系电话 + * + * @param userId 用户ID + * @param telephone 联系电话 + */ + void updateTelephone(String userId, String telephone); + + /** + * 根据ID锁定 + * + * @param id + */ + void lockById(String id); + + /** + * 根据ID解锁 + * + * @param id + */ + void unlockById(String id); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserTelephoneService.java b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserTelephoneService.java new file mode 100644 index 0000000..e2895d4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/service/system/SysUserTelephoneService.java @@ -0,0 +1,8 @@ +package com.lframework.starter.web.inner.service.system; + +import com.lframework.starter.web.core.service.BaseMpService; +import com.lframework.starter.web.inner.entity.SysUserTelephone; + +public interface SysUserTelephoneService extends BaseMpService { + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/openapi/OpenApiReqVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/openapi/OpenApiReqVo.java new file mode 100644 index 0000000..96513cc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/openapi/OpenApiReqVo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.vo.openapi; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class OpenApiReqVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户端ID + */ + @Schema(description = "客户端ID") + private Integer clientId; + + /** + * 时间戳 + */ + @Schema(description = "时间戳") + private String timestamp; + + /** + * 随机数 + */ + @Schema(description = "随机数") + private String nonceStr; + + /** + * 签名 + */ + @Schema(description = "签名") + private String sign; + + /** + * 请求参数 + */ + @Schema(description = "请求参数") + private String params; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/CreateOpLogsVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/CreateOpLogsVo.java new file mode 100644 index 0000000..7f0ed4b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/CreateOpLogsVo.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.inner.vo.oplogs; + +import com.lframework.starter.web.core.vo.BaseVo; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +/** + * 新增操作日志Vo + * + * @author zmj + */ +@Data +public class CreateOpLogsVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 日志名称 + */ + @NotBlank(message = "日志名称不能为空!") + private String name; + + /** + * 类型 + */ + @NotNull(message = "日志类型不能为空!") + private Integer logType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建人ID + */ + private String createById; + + /** + * IP地址 + */ + @NotBlank(message = "IP地址不能为空!") + private String ip; + + /** + * 补充信息 + */ + private String extra; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/QueryOpLogsVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/QueryOpLogsVo.java new file mode 100644 index 0000000..66b4b9d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/oplogs/QueryOpLogsVo.java @@ -0,0 +1,48 @@ +package com.lframework.starter.web.inner.vo.oplogs; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 查询操作日志Vo + * + * @author zmj + */ +@Data +public class QueryOpLogsVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 日志名称 + */ + @Schema(description = "日志名称") + private String name; + + /** + * 创建人ID + */ + @Schema(description = "创建人ID") + private String createBy; + + /** + * 日志类别 + */ + @Schema(description = "日志类别") + private Integer logType; + + /** + * 创建起始时间 + */ + @Schema(description = "创建起始时间") + private LocalDateTime startTime; + + /** + * 创建截止时间 + */ + @Schema(description = "创建截止时间") + private LocalDateTime endTime; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/CreateQrtzVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/CreateQrtzVo.java new file mode 100644 index 0000000..8abccf7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/CreateQrtzVo.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.inner.vo.qrtz; + +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.QrtzJobType; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class CreateQrtzVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分组 + */ + @Schema(description = "分组", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "分组不能为空!") + private String group; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 执行类名 + */ + @Schema(description = "执行类名") + private String targetClassName; + + /** + * 执行方法名 + */ + @Schema(description = "执行方法名") + private String targetMethodName; + + /** + * 执行参数类型 + */ + @Schema(description = "执行参数类型") + private List targetParamTypes; + + /** + * 执行参数 + */ + @Schema(description = "执行参数") + private List targetParams; + + /** + * Cron表达式 + */ + @Schema(description = "Cron表达式") + @NotBlank(message = "Cron表达式不能为空!") + private String cron; + + /** + * 任务类型 + */ + @NotNull(message = "任务类型不能为空!") + @IsEnum(message = "任务类型不能为空!", enumClass = QrtzJobType.class) + private Integer jobType; + + /** + * 脚本 + */ + @Schema(description = "脚本") + private String script; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/QueryQrtzVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/QueryQrtzVo.java new file mode 100644 index 0000000..26944fd --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/QueryQrtzVo.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.inner.vo.qrtz; + +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.PageVo; +import com.lframework.starter.web.inner.enums.system.TriggerState; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class QueryQrtzVo extends PageVo { + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 组 + */ + @Schema(description = "组") + private String group; + + /** + * 状态 + */ + @Schema(description = "状态") + @IsEnum(message = "状态格式错误!", enumClass = TriggerState.class) + private String state; + + /** + * 任务类 + */ + @Schema(hidden = true) + private List jobClasses; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/UpdateQrtzVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/UpdateQrtzVo.java new file mode 100644 index 0000000..df942d1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/qrtz/UpdateQrtzVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.qrtz; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class UpdateQrtzVo extends CreateQrtzVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 原始任务名称 + */ + @Schema(description = "原始任务名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "原始任务名称不能为空!") + private String oriName; + + /** + * 原始任务分组 + */ + @Schema(description = "原始任务分组", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "原始任务分组不能为空!") + private String oriGroup; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/config/UpdateSysConfigVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/config/UpdateSysConfigVo.java new file mode 100644 index 0000000..2059302 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/config/UpdateSysConfigVo.java @@ -0,0 +1,97 @@ +package com.lframework.starter.web.inner.vo.system.config; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 是否允许注册 + */ + @Schema(description = "是否允许注册", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否允许注册!") + @TypeMismatch(message = "是否允许注册格式错误!") + private Boolean allowRegist; + + /** + * 是否允许手机号登录 + */ + @Schema(description = "是否允许手机号登录", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否允许手机号登录!") + @TypeMismatch(message = "是否允许手机号登录格式错误!") + private Boolean allowTelephoneLogin; + + /** + * 手机号登录时的signName + */ + private String telephoneLoginSignName; + + /** + * 手机号登录时的templateCode + */ + private String telephoneLoginTemplateCode; + + /** + * 是否允许锁定用户 + */ + @Schema(description = "是否允许锁定用户", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否允许锁定用户!") + @TypeMismatch(message = "是否允许锁定用户格式错误!") + private Boolean allowLock; + + /** + * 登录失败次数 + */ + @Schema(description = "登录失败次数") + private Integer failNum; + + /** + * 是否允许验证码 + */ + @Schema(description = "是否允许验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否允许验证码!") + @TypeMismatch(message = "是否允许验证码格式错误!") + private Boolean allowCaptcha; + + /** + * 是否开启忘记密码 + */ + @Schema(description = "是否开启忘记密码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否开启忘记密码!") + @TypeMismatch(message = "是否开启忘记密码格式错误!") + private Boolean allowForgetPsw; + + /** + * 忘记密码是否使用邮箱 + */ + @Schema(description = "忘记密码是否使用邮箱,allowForgetPsw == true时必填") + @TypeMismatch(message = "忘记密码是否使用邮箱格式错误!") + private Boolean forgetPswRequireMail; + + /** + * 忘记密码是否使用短信 + */ + @Schema(description = "忘记密码是否使用短信,allowForgetPsw == true时必填") + @TypeMismatch(message = "忘记密码是否使用短信格式错误!") + private Boolean forgetPswRequireSms; + + /** + * signName + */ + @Schema(description = "signName,forgetPswRequireSms == true时必填") + private String signName; + + /** + * templateCode + */ + @Schema(description = "templateCode,forgetPswRequireSms == true时必填") + private String templateCode; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/CreateSysDeptVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/CreateSysDeptVo.java new file mode 100644 index 0000000..f314b40 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/CreateSysDeptVo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.web.inner.vo.system.dept; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysDeptVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 简称 + */ + @Schema(description = "简称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "简称不能为空!") + private String shortName; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysDeptSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysDeptSelectorVo.java new file mode 100644 index 0000000..72185c7 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysDeptSelectorVo.java @@ -0,0 +1,12 @@ +package com.lframework.starter.web.inner.vo.system.dept; + +import com.lframework.starter.web.core.vo.BaseVo; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysDeptSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysUserDeptSettingVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysUserDeptSettingVo.java new file mode 100644 index 0000000..748c383 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/SysUserDeptSettingVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.dept; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class SysUserDeptSettingVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @NotEmpty(message = "用户ID不能为空!") + private List userIds; + + /** + * 部门ID + */ + private List deptIds; + + /** + * 处理方式 1:新增 2:替换 3:删除 + */ + @Schema(description = "处理方式", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer handleType; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/UpdateSysDeptVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/UpdateSysDeptVo.java new file mode 100644 index 0000000..e78ed7d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dept/UpdateSysDeptVo.java @@ -0,0 +1,56 @@ +package com.lframework.starter.web.inner.vo.system.dept; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysDeptVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 简称 + */ + @Schema(description = "简称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "简称不能为空!") + private String shortName; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/CreateSysDataDicVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/CreateSysDataDicVo.java new file mode 100644 index 0000000..b5699f3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/CreateSysDataDicVo.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.inner.vo.system.dic; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysDataDicVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/QuerySysDataDicVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/QuerySysDataDicVo.java new file mode 100644 index 0000000..73132b0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/QuerySysDataDicVo.java @@ -0,0 +1,37 @@ +package com.lframework.starter.web.inner.vo.system.dic; + +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QuerySysDataDicVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/SysDataDicSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/SysDataDicSelectorVo.java new file mode 100644 index 0000000..ee57e8e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/SysDataDicSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.vo.system.dic; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataDicSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/UpdateSysDataDicVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/UpdateSysDataDicVo.java new file mode 100644 index 0000000..4838521 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/UpdateSysDataDicVo.java @@ -0,0 +1,51 @@ +package com.lframework.starter.web.inner.vo.system.dic; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysDataDicVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java new file mode 100644 index 0000000..eedbedb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.vo.system.dic.category; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysDataDicCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/QuerySysDataDicCategoryVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/QuerySysDataDicCategoryVo.java new file mode 100644 index 0000000..fe76f8f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/QuerySysDataDicCategoryVo.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.inner.vo.system.dic.category; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysDataDicCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java new file mode 100644 index 0000000..efc50f0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.inner.vo.system.dic.category; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysDataDicCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java new file mode 100644 index 0000000..6aabd65 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.vo.system.dic.category; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysDataDicCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/CreateSysDataDicItemVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/CreateSysDataDicItemVo.java new file mode 100644 index 0000000..5c29a2f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/CreateSysDataDicItemVo.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.inner.vo.system.dic.item; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysDataDicItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 字典ID + */ + @Schema(description = "字典ID") + @NotBlank(message = "字典ID不能为空!") + private String dicId; + + /** + * 排序 + */ + @Schema(description = "排序") + @NotNull(message = "请输入排序!") + private Integer orderNo; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/QuerySysDataDicItemVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/QuerySysDataDicItemVo.java new file mode 100644 index 0000000..43d9c45 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/QuerySysDataDicItemVo.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.vo.system.dic.item; + +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QuerySysDataDicItemVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 字典ID + */ + @Schema(description = "字典ID") + @NotBlank(message = "字典ID不能为空!") + private String dicId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java new file mode 100644 index 0000000..6a0710d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.inner.vo.system.dic.item; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysDataDicItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 排序 + */ + @Schema(description = "排序") + @NotNull(message = "请输入排序!") + private Integer orderNo; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/CreateSysGenerateCodeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/CreateSysGenerateCodeVo.java new file mode 100644 index 0000000..a4e170c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/CreateSysGenerateCodeVo.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.vo.system.generate; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysGenerateCodeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 规则ID + */ + @Schema(description = "规则ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请输入规则ID!") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/PreviewSysGenerateCodeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/PreviewSysGenerateCodeVo.java new file mode 100644 index 0000000..f8bbf9f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/PreviewSysGenerateCodeVo.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.inner.vo.system.generate; + +import com.lframework.starter.web.core.components.validation.IsJsonArray; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class PreviewSysGenerateCodeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 配置规则 + */ + @Schema(description = "配置规则", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "配置规则不能为空!") + @IsJsonArray(message = "配置规则格式错误!") + private String configStr; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/QuerySysGenerateCodeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/QuerySysGenerateCodeVo.java new file mode 100644 index 0000000..16c3c86 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/QuerySysGenerateCodeVo.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.inner.vo.system.generate; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysGenerateCodeVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "规则ID") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/SettingSysGenerateCodeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/SettingSysGenerateCodeVo.java new file mode 100644 index 0000000..e455db4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/SettingSysGenerateCodeVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.vo.system.generate; + +import com.lframework.starter.web.core.components.validation.IsJsonArray; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SettingSysGenerateCodeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private Integer id; + + /** + * 配置规则 + */ + @Schema(description = "配置规则", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "配置规则不能为空!") + @IsJsonArray(message = "配置规则格式错误!") + private String configStr; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/UpdateSysGenerateCodeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/UpdateSysGenerateCodeVo.java new file mode 100644 index 0000000..72145cb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/generate/UpdateSysGenerateCodeVo.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.vo.system.generate; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysGenerateCodeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/CreateSysMenuVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/CreateSysMenuVo.java new file mode 100644 index 0000000..ec3dd9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/CreateSysMenuVo.java @@ -0,0 +1,121 @@ +package com.lframework.starter.web.inner.vo.system.menu; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.SysMenuComponentType; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +/** + * 创建菜单Vo + */ +@Data +public class CreateSysMenuVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 标题 + */ + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 图标 + */ + @Schema(description = "图标") + private String icon; + + /** + * 类型 + */ + @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择类型!") + @IsEnum(message = "请选择类型!", enumClass = SysMenuDisplay.class) + private Integer display; + + /** + * 父级ID + */ + @Schema(description = "父级ID") + private String parentId; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + // 以下均为前端配置项 + + /** + * 路由名称 + */ + @Schema(description = "路由名称") + private String name; + + /** + * 组件类型 + */ + @Schema(description = "组件类型") + @IsEnum(message = "组件类型格式错误!", enumClass = SysMenuComponentType.class) + private Integer componentType; + + /** + * 组件 + */ + @Schema(description = "组件") + private String component; + + /** + * 自定义请求参数 + */ + @Schema(description = "自定义请求参数") + private String requestParam; + + /** + * 路径 + */ + @Schema(description = "路径") + private String path; + + /** + * 是否隐藏 + */ + @Schema(description = "是否隐藏") + private Boolean hidden; + + /** + * 是否不缓存 + */ + @Schema(description = "是否不缓存") + private Boolean noCache; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/QuerySysMenuVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/QuerySysMenuVo.java new file mode 100644 index 0000000..6306c4d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/QuerySysMenuVo.java @@ -0,0 +1,21 @@ +package com.lframework.starter.web.inner.vo.system.menu; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysMenuVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/SysMenuSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/SysMenuSelectorVo.java new file mode 100644 index 0000000..c9a1c71 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/SysMenuSelectorVo.java @@ -0,0 +1,30 @@ +package com.lframework.starter.web.inner.vo.system.menu; + +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.SysMenuDisplay; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysMenuSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + @Schema(description = "类型") + @IsEnum(message = "类型格式不正确!", enumClass = SysMenuDisplay.class) + private Integer display; + + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/UpdateSysMenuVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/UpdateSysMenuVo.java new file mode 100644 index 0000000..b4e0ef3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/menu/UpdateSysMenuVo.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.inner.vo.system.menu; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysMenuVo extends CreateSysMenuVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 状态 + */ + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "状态不能为空!") + @TypeMismatch(message = "状态格式有误!") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/mail/QuerySysMailMessageVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/mail/QuerySysMailMessageVo.java new file mode 100644 index 0000000..0bfd874 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/mail/QuerySysMailMessageVo.java @@ -0,0 +1,48 @@ +package com.lframework.starter.web.inner.vo.system.message.mail; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysMailMessageVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 邮箱地址 + */ + @Schema(description = "邮箱地址") + private String mail; + + /** + * 发送状态 + */ + @Schema(description = "发送状态") + private Integer sendStatus; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageByUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageByUserVo.java new file mode 100644 index 0000000..b1d2fe4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageByUserVo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.web.inner.vo.system.message.site; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysSiteMessageByUserVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 用户ID + */ + @Schema(hidden = true) + private String userId; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageVo.java new file mode 100644 index 0000000..278a817 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/message/site/QuerySysSiteMessageVo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.vo.system.message.site; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysSiteMessageVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/module/SysModuleTenantVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/module/SysModuleTenantVo.java new file mode 100644 index 0000000..618c40b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/module/SysModuleTenantVo.java @@ -0,0 +1,51 @@ +package com.lframework.starter.web.inner.vo.system.module; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class SysModuleTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @Data + public static class SysModuleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 模块ID + */ + @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "模块ID不能为空!") + private Integer moduleId; + + /** + * 过期时间 + */ + @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "过期时间不能为空!") + private LocalDateTime expireTime; + } + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 模块 + */ + @Schema(description = "模块") + @Valid + private List modules; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/CreateSysNoticeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/CreateSysNoticeVo.java new file mode 100644 index 0000000..bde87eb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/CreateSysNoticeVo.java @@ -0,0 +1,39 @@ +package com.lframework.starter.web.inner.vo.system.notice; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysNoticeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入内容!") + private String content; + + /** + * 是否发布 + */ + @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED) + @TypeMismatch(message = "是否发布格式有误!") + @NotNull(message = "请选择是否发布!") + private Boolean published; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeByUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeByUserVo.java new file mode 100644 index 0000000..e22ecda --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeByUserVo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.web.inner.vo.system.notice; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysNoticeByUserVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 用户ID + */ + @Schema(hidden = true) + private String userId; + + /** + * 是否已读 + */ + @Schema(description = "是否已读") + private Boolean readed; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeVo.java new file mode 100644 index 0000000..3ac0f61 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/QuerySysNoticeVo.java @@ -0,0 +1,43 @@ +package com.lframework.starter.web.inner.vo.system.notice; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysNoticeVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @Schema(description = "标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/UpdateSysNoticeVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/UpdateSysNoticeVo.java new file mode 100644 index 0000000..b47d810 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notice/UpdateSysNoticeVo.java @@ -0,0 +1,53 @@ +package com.lframework.starter.web.inner.vo.system.notice; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysNoticeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 标题 + */ + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 内容 + */ + @Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入内容!") + private String content; + + /** + * 状态 + */ + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) + @TypeMismatch(message = "状态格式有误!") + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 是否发布 + */ + @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED) + @TypeMismatch(message = "是否发布格式有误!") + @NotNull(message = "请选择是否发布!") + private Boolean published; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/CreateSysNotifyGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/CreateSysNotifyGroupVo.java new file mode 100644 index 0000000..0daf4b3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/CreateSysNotifyGroupVo.java @@ -0,0 +1,54 @@ +package com.lframework.starter.web.inner.vo.system.notify; + +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.SysNotifyReceiverType; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class CreateSysNotifyGroupVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 接收者类型 + */ + @Schema(description = "接收者类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "接收者类型不能为空!") + @IsEnum(enumClass = SysNotifyReceiverType.class, message = "接收者类型格式不正确!") + private Integer receiverType; + + /** + * 接收者ID + */ + @Schema(description = "接收者ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "接收者ID不能为空!") + private List receiverIds; + + /** + * 消息类型 + */ + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "消息类型不能为空!") + private List messageType; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/QuerySysNotifyGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/QuerySysNotifyGroupVo.java new file mode 100644 index 0000000..00655e0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/QuerySysNotifyGroupVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.vo.system.notify; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysNotifyGroupVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema($schema = "名称") + private String name; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/SysNotifyGroupSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/SysNotifyGroupSelectorVo.java new file mode 100644 index 0000000..da260a8 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/SysNotifyGroupSelectorVo.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.inner.vo.system.notify; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysNotifyGroupSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/UpdateSysNotifyGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/UpdateSysNotifyGroupVo.java new file mode 100644 index 0000000..0d15952 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/notify/UpdateSysNotifyGroupVo.java @@ -0,0 +1,18 @@ +package com.lframework.starter.web.inner.vo.system.notify; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateSysNotifyGroupVo extends CreateSysNotifyGroupVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/CreateSysOpenDomainVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/CreateSysOpenDomainVo.java new file mode 100644 index 0000000..e9e023b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/CreateSysOpenDomainVo.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.inner.vo.system.open; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysOpenDomainVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * API密钥 + */ + @Schema(description = "API密钥", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "API密钥不能为空!") + private String apiSecret; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/QuerySysOpenDomainVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/QuerySysOpenDomainVo.java new file mode 100644 index 0000000..6540f3d --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/QuerySysOpenDomainVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.open; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysOpenDomainVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/SysOpenDomainSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/SysOpenDomainSelectorVo.java new file mode 100644 index 0000000..23b6535 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/SysOpenDomainSelectorVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.open; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysOpenDomainSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + private String id; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java new file mode 100644 index 0000000..47770b6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java @@ -0,0 +1,29 @@ +package com.lframework.starter.web.inner.vo.system.open; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysOpenDomainSecretVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "ID不能为空!") + private Long id; + + /** + * Api密钥 + */ + @Schema(description = "Api密钥", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "Api密钥不能为空!") + private String apiSecret; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainVo.java new file mode 100644 index 0000000..9206847 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/open/UpdateSysOpenDomainVo.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.inner.vo.system.open; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysOpenDomainVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "ID不能为空!") + private Long id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 状态 + */ + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "状态不能为空!") + private Boolean available; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/CreateSysParameterVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/CreateSysParameterVo.java new file mode 100644 index 0000000..468ad34 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/CreateSysParameterVo.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.inner.vo.system.parameter; + +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysParameterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 键 + */ + @Schema(description = "键", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入键!") + @Pattern(regexp = "^[A-Za-z0-9\\.\\-_]+$", message = "键只能由大写字母、小写字母、数字或._-组成") + private String pmKey; + + /** + * 值 + */ + @Schema(description = "值") + private String pmValue; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/QuerySysParameterVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/QuerySysParameterVo.java new file mode 100644 index 0000000..41c5565 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/QuerySysParameterVo.java @@ -0,0 +1,45 @@ +package com.lframework.starter.web.inner.vo.system.parameter; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysParameterVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 键 + */ + @Schema(description = "键") + private String pmKey; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/UpdateSysParameterVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/UpdateSysParameterVo.java new file mode 100644 index 0000000..66970da --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/parameter/UpdateSysParameterVo.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.vo.system.parameter; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysParameterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private Long id; + + /** + * 值 + */ + @Schema(description = "值") + private String pmValue; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/CreateSysDataPermissionDataVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/CreateSysDataPermissionDataVo.java new file mode 100644 index 0000000..5312beb --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/CreateSysDataPermissionDataVo.java @@ -0,0 +1,46 @@ +package com.lframework.starter.web.inner.vo.system.permission; + +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.SysDataPermissionDataBizType; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class CreateSysDataPermissionDataVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务ID + */ + @Schema(description = "业务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "业务ID不能为空!") + private List bizIds; + + /** + * 业务类型 + */ + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型格式错误!", enumClass = SysDataPermissionDataBizType.class) + private Integer bizType; + + /** + * 权限类型 + */ + @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "权限类型不能为空!") + private Integer permissionType; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/SysDataPermissionModelDetailVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/SysDataPermissionModelDetailVo.java new file mode 100644 index 0000000..150ac9b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/permission/SysDataPermissionModelDetailVo.java @@ -0,0 +1,66 @@ +package com.lframework.starter.web.inner.vo.system.permission; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class SysDataPermissionModelDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + + private String id; + + /** + * 明细ID + */ + @Schema(description = "明细ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "明细ID不能为空!") + private Integer detailId; + + /** + * 节点类型 + */ + @Schema(description = "节点类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "节点类型不能为空!") + private Integer nodeType; + + /** + * 计算类型 + */ + @Schema(description = "计算类型") + private Integer calcType; + + /** + * 值 + */ + @Schema(description = "值") + private String value; + + /** + * 值 + */ + @Schema(description = "值") + private List values; + + /** + * 条件类型 + */ + @Schema(description = "条件类型") + private Integer conditionType; + + /** + * 子节点 + */ + @Schema(description = "子节点") + private List children; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/CreateSysRoleVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/CreateSysRoleVo.java new file mode 100644 index 0000000..3b53065 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/CreateSysRoleVo.java @@ -0,0 +1,49 @@ +package com.lframework.starter.web.inner.vo.system.role; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysRoleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请选择分类!") + private String categoryId; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/QuerySysRoleVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/QuerySysRoleVo.java new file mode 100644 index 0000000..40cf13c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/QuerySysRoleVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.role; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysRoleVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID") + private String categoryId; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleMenuSettingVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleMenuSettingVo.java new file mode 100644 index 0000000..a0f33d3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleMenuSettingVo.java @@ -0,0 +1,25 @@ +package com.lframework.starter.web.inner.vo.system.role; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + +@Data +public class SysRoleMenuSettingVo implements BaseVo { + + /** + * 角色ID + */ + @Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "角色ID不能为空!") + private List roleIds; + + /** + * 菜单ID + */ + @Schema(description = "菜单ID") + private List menuIds; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleSelectorVo.java new file mode 100644 index 0000000..5fc2a94 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/SysRoleSelectorVo.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.inner.vo.system.role; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysRoleSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/UpdateSysRoleVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/UpdateSysRoleVo.java new file mode 100644 index 0000000..3653322 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/UpdateSysRoleVo.java @@ -0,0 +1,56 @@ +package com.lframework.starter.web.inner.vo.system.role; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysRoleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请选择分类!") + private String categoryId; + + /** + * 权限 + */ + @Schema(description = "权限") + private String permission; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/CreateSysRoleCategoryVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/CreateSysRoleCategoryVo.java new file mode 100644 index 0000000..269a7c3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/CreateSysRoleCategoryVo.java @@ -0,0 +1,30 @@ +package com.lframework.starter.web.inner.vo.system.role.category; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateSysRoleCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/SysRoleCategorySelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/SysRoleCategorySelectorVo.java new file mode 100644 index 0000000..f09bf05 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/SysRoleCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.starter.web.inner.vo.system.role.category; + +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SysRoleCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/UpdateSysRoleCategoryVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/UpdateSysRoleCategoryVo.java new file mode 100644 index 0000000..c60fcc6 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/role/category/UpdateSysRoleCategoryVo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.vo.system.role.category; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateSysRoleCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/CreateTenantVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/CreateTenantVo.java new file mode 100644 index 0000000..1989ac4 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/CreateTenantVo.java @@ -0,0 +1,56 @@ +package com.lframework.starter.web.inner.vo.system.tenant; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class CreateTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 绑定域名 + */ + @Schema(description = "绑定域名") + private String serverName; + + /** + * JdbcUrl + */ + @Schema(description = "JdbcUrl", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入JdbcUrl!") + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @Schema(description = "Jdbc用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入Jdbc用户名!") + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @Schema(description = "Jdbc密码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入Jdbc密码!") + private String jdbcPassword; + + /** + * 是否为平台管理租户 + */ + @Schema(description = "是否为平台管理租户", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否为平台管理租户!") + private Boolean isPlatform; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/QueryTenantVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/QueryTenantVo.java new file mode 100644 index 0000000..e2e7685 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/QueryTenantVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.tenant; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryTenantVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private String tenantId; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/TenantSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/TenantSelectorVo.java new file mode 100644 index 0000000..9d654ec --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/TenantSelectorVo.java @@ -0,0 +1,32 @@ +package com.lframework.starter.web.inner.vo.system.tenant; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class TenantSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private String tenantId; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/UpdateTenantVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/UpdateTenantVo.java new file mode 100644 index 0000000..bc328db --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/tenant/UpdateTenantVo.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.inner.vo.system.tenant; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UpdateTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "ID不能为空!") + private Integer id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 绑定域名 + */ + @Schema(description = "绑定域名") + private String serverName; + + /** + * JdbcUrl + */ + @Schema(description = "JdbcUrl") + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @Schema(description = "Jdbc用户名") + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @Schema(description = "Jdbc密码") + private String jdbcPassword; + + /** + * 是否为平台管理租户 + */ + @Schema(description = "是否为平台管理租户", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择是否为平台管理租户!") + private Boolean isPlatform; + + /** + * 状态 + */ + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择状态!") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/CreateSysUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/CreateSysUserVo.java new file mode 100644 index 0000000..6d6f441 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/CreateSysUserVo.java @@ -0,0 +1,91 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.Gender; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class CreateSysUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @IsCode + @NotBlank(message = "请输入编号!") + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + private String code; + + /** + * 姓名 + */ + @NotBlank(message = "请输入姓名!") + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; + + /** + * 用户名 + */ + @NotBlank(message = "请输入用户名!") + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + private String username; + + /** + * 密码 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_PASSWORD, message = "密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线") + @NotBlank(message = "请输入密码!") + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + private String password; + + /** + * 邮箱 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_EMAIL, message = "邮箱地址格式不正确!") + @Schema(description = "邮箱") + private String email; + + /** + * 联系电话 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "联系电话格式不正确!") + @Schema(description = "联系电话") + private String telephone; + + /** + * 性别 0-未知 1-男 2-女 + */ + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + @Schema(description = "性别") + private Integer gender; + + /** + * 部门ID + */ + @Schema(description = "部门ID") + private List deptIds; + + /** + * 角色ID + */ + @Schema(description = "角色ID") + private List roleIds; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetLoginCaptchaRequireVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetLoginCaptchaRequireVo.java new file mode 100644 index 0000000..a85e11e --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetLoginCaptchaRequireVo.java @@ -0,0 +1,36 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户登录请求参数 + */ +@Data +public class GetLoginCaptchaRequireVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 租户名称 + */ + @Schema(description = "租户名称") + private String tenantName; + + /** + * 用户名 + */ + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "用户名不能为空!") + private String username; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java new file mode 100644 index 0000000..20e5f95 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java @@ -0,0 +1,24 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class GetTelephoneLoginCaptchaVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/LoginVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/LoginVo.java new file mode 100644 index 0000000..9d08eb0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/LoginVo.java @@ -0,0 +1,55 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户登录请求参数 + */ +@Data +public class LoginVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @Schema(description = "租户ID") + private Integer tenantId; + + /** + * 租户名称 + */ + @Schema(description = "租户名称") + private String tenantName; + + /** + * 用户名 + */ + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "密码不能为空!") + private String password; + + /** + * sn + */ + @Schema(description = "sn,验证码流水号", requiredMode = Schema.RequiredMode.REQUIRED) + private String sn; + + /** + * 验证码 + */ + @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + private String captcha; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/QuerySysUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/QuerySysUserVo.java new file mode 100644 index 0000000..8b6661c --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/QuerySysUserVo.java @@ -0,0 +1,50 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QuerySysUserVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 用户名 + */ + @Schema(description = "用户名") + private String username; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 部门ID + */ + @Schema(description = "部门ID") + private String deptId; + + /** + * 角色ID + */ + @Schema(description = "角色ID") + private String roleId; + + /** + * 是否锁定 + */ + @Schema(description = "是否锁定") + private Boolean lockStatus; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/RegistUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/RegistUserVo.java new file mode 100644 index 0000000..4f5af99 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/RegistUserVo.java @@ -0,0 +1,52 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class RegistUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户名 + */ + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + @Pattern(regexp = PatternPool.PATTERN_STR_PASSWORD, message = "密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线") + @NotBlank(message = "密码不能为空!") + private String password; + + /** + * 姓名 + */ + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "姓名不能为空!") + private String name; + + /** + * 邮箱 + */ + @Schema(description = "邮箱") + @Pattern(regexp = PatternPool.PATTERN_STR_EMAIL, message = "邮箱地址格式不正确!") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话") + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "联系电话格式不正确!") + private String telephone; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserRoleSettingVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserRoleSettingVo.java new file mode 100644 index 0000000..958a576 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserRoleSettingVo.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class SysUserRoleSettingVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "用户ID不能为空!") + private List userIds; + + /** + * 角色ID + */ + @Schema(description = "角色ID") + private List roleIds; + + /** + * 处理方式 1:新增 2:替换 3:删除 + */ + @Schema(description = "处理方式", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer handleType; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserSelectorVo.java new file mode 100644 index 0000000..3484dea --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/SysUserSelectorVo.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysUserSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名") + private String name; + + /** + * 用户名 + */ + @Schema(description = "用户名") + private String username; + + /** + * 状态 + */ + @Schema(description = "状态") + private Boolean available; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneBindUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneBindUserVo.java new file mode 100644 index 0000000..1694930 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneBindUserVo.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 手机号绑定用户 + * + * @author zmj + * @since 2022/4/25 + */ +@Data +public class TelephoneBindUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 用户名 + */ + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "密码不能为空!") + private String password; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneLoginVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneLoginVo.java new file mode 100644 index 0000000..d1947d3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/TelephoneLoginVo.java @@ -0,0 +1,34 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.core.components.validation.Pattern; +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 手机号登录请求参数 + */ +@Data +public class TelephoneLoginVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 验证码 + */ + @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "验证码不能为空!") + private String captcha; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/UpdateSysUserVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/UpdateSysUserVo.java new file mode 100644 index 0000000..ef46c27 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/UpdateSysUserVo.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.inner.vo.system.user; + +import com.lframework.starter.web.core.components.validation.IsCode; +import com.lframework.starter.web.core.components.validation.IsEnum; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.inner.enums.system.Gender; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class UpdateSysUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 姓名 + */ + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入姓名!") + private String name; + + /** + * 用户名 + */ + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请输入用户名!") + private String username; + + /** + * 密码 如果不为空则为修改密码 + */ + @Schema(description = "密码 如果不为空则为修改密码") + private String password; + + /** + * 邮箱 + */ + @Schema(description = "邮箱") + private String email; + + /** + * 联系电话 + */ + @Schema(description = "联系电话") + private String telephone; + + /** + * 性别 + */ + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + private Integer gender; + + /** + * 角色ID + */ + @Schema(description = "角色ID") + private List roleIds; + + /** + * 部门ID + */ + @Schema(description = "部门ID") + private List deptIds; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/CreateSysUserGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/CreateSysUserGroupVo.java new file mode 100644 index 0000000..99aac68 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/CreateSysUserGroupVo.java @@ -0,0 +1,41 @@ +package com.lframework.starter.web.inner.vo.system.user.group; + +import com.lframework.starter.web.core.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class CreateSysUserGroupVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 备注 + */ + @Schema(description = "备注") + private String description; + + /** + * 用户ID + */ + @Schema(description = "用户ID") + private List userIds; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/QuerySysUserGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/QuerySysUserGroupVo.java new file mode 100644 index 0000000..dda0670 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/QuerySysUserGroupVo.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.inner.vo.system.user.group; + +import com.lframework.starter.web.core.components.validation.TypeMismatch; +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.SortPageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class QuerySysUserGroupVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 创建时间 起始时间 + */ + @Schema(description = "创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @Schema(description = "创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/SysUserGroupSelectorVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/SysUserGroupSelectorVo.java new file mode 100644 index 0000000..7b9863f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/SysUserGroupSelectorVo.java @@ -0,0 +1,26 @@ +package com.lframework.starter.web.inner.vo.system.user.group; + +import com.lframework.starter.web.core.vo.BaseVo; +import com.lframework.starter.web.core.vo.PageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SysUserGroupSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private String code; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/UpdateSysUserGroupVo.java b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/UpdateSysUserGroupVo.java new file mode 100644 index 0000000..a5d54a3 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/inner/vo/system/user/group/UpdateSysUserGroupVo.java @@ -0,0 +1,18 @@ +package com.lframework.starter.web.inner.vo.system.user.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateSysUserGroupVo extends CreateSysUserGroupVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPushWorker.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPushWorker.java new file mode 100644 index 0000000..3c3b0af --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPushWorker.java @@ -0,0 +1,92 @@ +package com.lframework.starter.web.websocket.components; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.entity.WsSession; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketMessage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class WsDataPushWorker { + + public static void push(WsPushData data) { + if (log.isDebugEnabled()) { + log.debug("开始推送消息,data = {}", data); + } + if (data == null) { + return; + } + + if (data.getAll()) { + if (log.isDebugEnabled()) { + log.debug("全员广播"); + } + // 全员广播 + WsSessionManager.getAllAvailableSessions(data.getTenantId(), data.getIncludeSessionIds(), + data.getExcludeSessionIds()) + .stream().forEach(t -> { + Map obj = new HashMap(2, 1); + obj.put("bizType", data.getBizType()); + obj.put("data", data.getData()); + sendMessage(t, new TextMessage(JsonUtil.toJsonString(obj))); + }); + } else { + List userIds = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(data.getIncludeUserIds())) { + userIds.addAll(data.getIncludeUserIds()); + } + + if (StringUtil.isNotBlank(data.getIncludeUserId())) { + userIds.add(data.getIncludeUserId()); + } + + if (log.isDebugEnabled()) { + log.debug("部分成员接收消息"); + } + + WsSessionManager.getAvailableSessionsByUserIds(data.getTenantId(), userIds, + data.getIncludeSessionIds(), + data.getExcludeSessionIds()).forEach(t -> { + Map obj = new HashMap(2, 1); + obj.put("bizType", data.getBizType()); + obj.put("data", data.getData()); + sendMessage(t, new TextMessage(JsonUtil.toJsonString(obj))); + }); + } + } + + private static void sendMessage(WsSession session, WebSocketMessage message) { + int retryCount = 5; + int currentRetryCount = retryCount; + while (currentRetryCount > 0) { + try { + if (log.isDebugEnabled()) { + log.debug("准备向sessionId {} 推送消息 {}", session.getWebSocketSession().getId(), message.getPayload()); + } + session.getWebSocketSession().sendMessage(message); + break; + } catch (IllegalStateException e) { + currentRetryCount--; + if (currentRetryCount > 0) { + log.warn("推送WS消息失败,休眠一秒,重试第{}次", (retryCount - currentRetryCount)); + } else { + log.error(e.getMessage(), e); + } + // 休眠200毫秒再重试 + ThreadUtil.safeSleep(1000); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusher.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusher.java new file mode 100644 index 0000000..b53f74f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusher.java @@ -0,0 +1,13 @@ +package com.lframework.starter.web.websocket.components; + +import com.lframework.starter.web.websocket.dto.WsPushData; + +public interface WsDataPusher { + + /** + * 推送数据 + * + * @param data + */ + void push(WsPushData data); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusherImpl.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusherImpl.java new file mode 100644 index 0000000..61b497b --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsDataPusherImpl.java @@ -0,0 +1,80 @@ +package com.lframework.starter.web.websocket.components; + +import com.lframework.starter.web.config.properties.WsProperties; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.websocket.dto.WsPushData; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class WsDataPusherImpl implements WsDataPusher { + + private RedisTemplate redisTemplate; + + private WsProperties properties; + + public WsDataPusherImpl(RedisTemplate redisTemplate, WsProperties properties) { + this.redisTemplate = redisTemplate; + this.properties = properties; + } + + public void push(WsPushData data) { + if (TenantUtil.enableTenant()) { + if (data.getTenantId() == null) { + data.setTenantId(TenantContextHolder.getTenantId()); + } + } + if (log.isDebugEnabled()) { + log.debug("准备推送消息,data = {}", data); + } + List parameters = new ArrayList<>(); + parameters.add(properties.getTopic()); + parameters.add(JsonUtil.toJsonString(data)); + this.redisTemplate.execute(connection -> { + Object result; + byte[][] params = new byte[parameters.size()][]; + for (int i = 0; i < params.length; i++) { + params[i] = serializer(parameters.get(i)); + } + result = connection.execute("publish", params); + return deserialize(result); + }, this.redisTemplate.isExposeConnection()); + } + + private byte[] serializer(Object value) { + if (value == null || value instanceof String) { + return redisTemplate.getStringSerializer().serialize((String) value); + } + return serializer(value.toString()); + } + + private Object deserialize(Object value) { + if (value != null) { + if (value instanceof byte[]) { + return this.redisTemplate.getStringSerializer().deserialize((byte[]) value); + } + if (value instanceof List) { + List valueList = (List) value; + List resultList = new ArrayList<>(valueList.size()); + for (Object val : valueList) { + resultList.add(deserialize(val)); + } + return resultList; + } + if (value instanceof Map) { + Map map = (Map) value; + LinkedHashMap newMap = new LinkedHashMap<>(map.size()); + map.forEach((key, val) -> newMap.put(deserialize(key), deserialize(val))); + return newMap; + } + } + return value; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsSessionManager.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsSessionManager.java new file mode 100644 index 0000000..c2313c5 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/components/WsSessionManager.java @@ -0,0 +1,82 @@ +package com.lframework.starter.web.websocket.components; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.websocket.entity.WsSession; +import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class WsSessionManager { + + private static final Map POOL; + + static { + POOL = new ConcurrentHashMap<>(); + } + + public static WsSession getSession(String id) { + return POOL.get(id); + } + + public static void addSession(WsSession session) { + if (session == null) { + throw new DefaultSysException("session is null"); + } + + if (session.getWebSocketSession() == null) { + throw new DefaultSysException("webSocketSession is null"); + } + + POOL.put(session.getWebSocketSession().getId(), session); + } + + public static void removeSession(String id) { + POOL.remove(id); + } + + public static List getAllAvailableSessions(Integer tenantId, + List includeSessionIds, List excludeSessionIds) { + boolean enableTenant = TenantUtil.enableTenant(); + if (enableTenant) { + if (tenantId == null) { + return Collections.emptyList(); + } + } + + return POOL.values().stream() + .filter(t -> t.getWebSocketSession() != null && t.getWebSocketSession().isOpen() + && t.getUser() != null && (!enableTenant || tenantId.equals(t.getUser().getTenantId()))) + .filter(t -> CollectionUtil.isEmpty(includeSessionIds) || includeSessionIds.contains( + t.getWebSocketSession().getId())) + .filter(t -> CollectionUtil.isEmpty(excludeSessionIds) || !excludeSessionIds.contains( + t.getWebSocketSession().getId())) + .collect(Collectors.toList()); + } + + public static List getAvailableSessionsByUserIds(Integer tenantId, + List userIds, List includeSessionIds, List excludeSessionIds) { + + boolean enableTenant = TenantUtil.enableTenant(); + if (enableTenant) { + if (tenantId == null) { + return Collections.emptyList(); + } + } + + return POOL.values().stream() + .filter(t -> t.getWebSocketSession() != null && t.getWebSocketSession().isOpen() + && t.getUser() != null && (CollectionUtil.isEmpty(userIds) || userIds.contains( + t.getUser().getId())) && (!enableTenant + || tenantId.equals(t.getUser().getTenantId()))) + .filter(t -> CollectionUtil.isEmpty(includeSessionIds) || includeSessionIds.contains( + t.getWebSocketSession().getId())) + .filter(t -> CollectionUtil.isEmpty(excludeSessionIds) || !excludeSessionIds.contains( + t.getWebSocketSession().getId())) + .collect(Collectors.toList()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/constants/WsPool.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/constants/WsPool.java new file mode 100644 index 0000000..5100ebc --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/constants/WsPool.java @@ -0,0 +1,20 @@ +package com.lframework.starter.web.websocket.constants; + +public interface WsPool { + + /** + * WS接收的数据处理器的Bean名称后缀 + */ + String WS_RECEIVE_BEAN_SUFFIX = "WsReceiveBean"; + + String TOKEN_KEY = "__token"; + + String USER_KEY = "__user"; + + // 自定义消息业务类型 + // 用户连接 + String PUSH_CONNECT = "connect"; + + // 用户断开连接 + String PUSH_DISCONNECT = "disconnect"; +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/dto/WsPushData.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/dto/WsPushData.java new file mode 100644 index 0000000..06488df --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/dto/WsPushData.java @@ -0,0 +1,67 @@ +package com.lframework.starter.web.websocket.dto; + +import com.lframework.starter.web.core.dto.BaseDto; +import com.lframework.starter.web.core.utils.JsonUtil; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * WS推送数据 + */ +@Data +public class WsPushData implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型 + */ + private String bizType; + + /** + * 是否全员广播 + */ + private Boolean all = Boolean.FALSE; + + /** + * 接收用户ID集合 all=true时,此值无效 + */ + private List includeUserIds; + + /** + * 接收用户ID all=true时,此值无效 + */ + private String includeUserId; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 指定SessionId集合 + */ + private List includeSessionIds; + + /** + * 需要排除的SessionId + */ + private List excludeSessionIds; + + /** + * 推送数据 + */ + private String data; + + public void setDataObj(Object obj) { + if (obj == null) { + this.data = null; + } else if (obj instanceof CharSequence) { + this.data = obj.toString(); + } else { + this.data = JsonUtil.toJsonString(obj); + } + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/entity/WsSession.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/entity/WsSession.java new file mode 100644 index 0000000..6f371d1 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/entity/WsSession.java @@ -0,0 +1,33 @@ +package com.lframework.starter.web.websocket.entity; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.websocket.components.WsSessionManager; +import com.lframework.starter.web.websocket.constants.WsPool; +import lombok.Data; +import org.springframework.web.socket.WebSocketSession; + +@Data +public class WsSession { + + private String token; + + private WebSocketSession webSocketSession; + + private AbstractUserDetails user; + + + public static WsSession get(WebSocketSession webSocketSession) { + WsSession wsSession = WsSessionManager.getSession(webSocketSession.getId()); + if (wsSession == null) { + wsSession = new WsSession(); + wsSession.setWebSocketSession(webSocketSession); + wsSession.setToken(String.valueOf(webSocketSession.getAttributes().get(WsPool.TOKEN_KEY))); + + AbstractUserDetails currentUser = (AbstractUserDetails) webSocketSession.getAttributes().get(WsPool.USER_KEY); + wsSession.setUser(currentUser); + WsSessionManager.addSession(wsSession); + } + + return wsSession; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserConnectEvent.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserConnectEvent.java new file mode 100644 index 0000000..c604d1a --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserConnectEvent.java @@ -0,0 +1,31 @@ +package com.lframework.starter.web.websocket.events; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import org.springframework.context.ApplicationEvent; + +/** + * 用户连接事件 区别于LoginEvent:LoginEvent用于表示用户登录系统后的事件;而连接事件表示用户与后台WS连接成功事件 + */ +public class UserConnectEvent extends ApplicationEvent { + + /** + * SessionId + */ + private String sessionId; + + private AbstractUserDetails user; + + public UserConnectEvent(Object source, String sessionId, AbstractUserDetails user) { + super(source); + this.sessionId = sessionId; + this.user = user; + } + + public String getSessionId() { + return sessionId; + } + + public AbstractUserDetails getUser() { + return user; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserDisConnectEvent.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserDisConnectEvent.java new file mode 100644 index 0000000..b87d39f --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/events/UserDisConnectEvent.java @@ -0,0 +1,28 @@ +package com.lframework.starter.web.websocket.events; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import org.springframework.context.ApplicationEvent; + +/** + * 用户连接断开事件 区别于LogoutEvent:LogoutEvent用于表示用户退出登录系统后的事件;而连接断开事件表示用户与后台WS断开连接事件 + */ +public class UserDisConnectEvent extends ApplicationEvent { + + private String sessionId; + + private AbstractUserDetails user; + + public UserDisConnectEvent(Object source, String sessionId, AbstractUserDetails user) { + super(source); + this.sessionId = sessionId; + this.user = user; + } + + public String getSessionId() { + return sessionId; + } + + public AbstractUserDetails getUser() { + return user; + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/handler/WsHandler.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/handler/WsHandler.java new file mode 100644 index 0000000..9cf4e03 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/handler/WsHandler.java @@ -0,0 +1,113 @@ +package com.lframework.starter.web.websocket.handler; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.core.components.tenant.TenantContextHolder; +import com.lframework.starter.web.core.utils.ApplicationUtil; +import com.lframework.starter.web.core.utils.JsonUtil; +import com.lframework.starter.web.core.utils.TenantUtil; +import com.lframework.starter.web.websocket.components.WsSessionManager; +import com.lframework.starter.web.websocket.constants.WsPool; +import com.lframework.starter.web.websocket.entity.WsSession; +import com.lframework.starter.web.websocket.events.UserConnectEvent; +import com.lframework.starter.web.websocket.events.UserDisConnectEvent; +import com.lframework.starter.web.websocket.service.WsDataProcessService; +import com.lframework.starter.web.websocket.vo.WsVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +@Slf4j +public class WsHandler extends TextWebSocketHandler { + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + WsSession wsSession = WsSession.get(session); + AbstractUserDetails currentUser = wsSession.getUser(); + + try { + if (TenantUtil.enableTenant()) { + TenantContextHolder.setTenantId(currentUser.getTenantId()); + } + + SecurityUtil.setCurrentUser(currentUser); + + ApplicationUtil.publishEvent(new UserConnectEvent(this, session.getId(), currentUser)); + } finally { + TenantContextHolder.clearTenantId(); + SecurityUtil.removeCurrentUser(); + } + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + WsSession wsSession = WsSessionManager.getSession(session.getId()); + AbstractUserDetails currentUser = wsSession.getUser(); + + try { + if (TenantUtil.enableTenant()) { + TenantContextHolder.setTenantId(currentUser.getTenantId()); + } + + SecurityUtil.setCurrentUser(currentUser); + + ApplicationUtil.publishEvent(new UserDisConnectEvent(this, session.getId(), currentUser)); + } finally { + TenantContextHolder.clearTenantId(); + SecurityUtil.removeCurrentUser(); + } + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) { + WsSession wsSession = WsSessionManager.getSession(session.getId()); + AbstractUserDetails currentUser = wsSession.getUser(); + + if (currentUser == null) { + // 没有用户信息,过滤 + return; + } + + WsVo vo = parseVo(message.getPayload()); + if (vo == null) { + // 如果接收到空消息,过滤 + return; + } + + if (StringUtil.isBlank(vo.getBizType())) { + // 如果业务类型为空,过滤 + return; + } + + try { + if (TenantUtil.enableTenant()) { + TenantContextHolder.setTenantId(currentUser.getTenantId()); + } + + SecurityUtil.setCurrentUser(currentUser); + + try { + WsDataProcessService bean = (WsDataProcessService) ApplicationUtil.getBean( + vo.getBizType() + WsPool.WS_RECEIVE_BEAN_SUFFIX); + bean.process(vo); + } catch (Exception e) { + log.error(e.getMessage(), e); + return; + } + } finally { + TenantContextHolder.clearTenantId(); + SecurityUtil.removeCurrentUser(); + } + } + + private WsVo parseVo(String str) { + if (StringUtil.isBlank(str)) { + return null; + } + + return JsonUtil.parseObject(str, WsVo.class); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/interceptor/WsHandshakeInterceptor.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/interceptor/WsHandshakeInterceptor.java new file mode 100644 index 0000000..e89a218 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/interceptor/WsHandshakeInterceptor.java @@ -0,0 +1,38 @@ +package com.lframework.starter.web.websocket.interceptor; + +import com.lframework.starter.web.core.components.security.AbstractUserDetails; +import com.lframework.starter.web.core.components.security.SecurityUtil; +import com.lframework.starter.web.websocket.constants.WsPool; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.Map; + +public class WsHandshakeInterceptor implements HandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest request, + ServerHttpResponse response, WebSocketHandler wsHandler, + Map attributes) throws Exception { + + String token = ((ServletServerHttpRequest) request).getServletRequest() + .getParameter("X-Auth-Token"); + + AbstractUserDetails currentUser = SecurityUtil.getUserByToken(token); + if (currentUser == null) { + return false; + } + + attributes.put(WsPool.TOKEN_KEY, token); + attributes.put(WsPool.USER_KEY, currentUser); + return true; + } + + @Override + public void afterHandshake(ServerHttpRequest request, + ServerHttpResponse response, WebSocketHandler wsHandler, Exception e) { + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserConnectListener.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserConnectListener.java new file mode 100644 index 0000000..db6a0e2 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserConnectListener.java @@ -0,0 +1,42 @@ +package com.lframework.starter.web.websocket.listener; + +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.constants.WsPool; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.events.UserConnectEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class WsUserConnectListener implements ApplicationListener { + + @Autowired + private WsDataPusher wsDataPusher; + + @Override + public void onApplicationEvent(UserConnectEvent event) { + if (log.isDebugEnabled()) { + log.debug("监听到用户建立连接事件,event={}", event); + } + WsPushData data = new WsPushData(); + data.setBizType(WsPool.PUSH_CONNECT); + data.setAll(Boolean.TRUE); + data.setTenantId(event.getUser().getTenantId()); + data.setExcludeSessionIds(Collections.singletonList(event.getSessionId())); + + // 这里直接用map了,不构建bo了 + Map map = new HashMap<>(); + map.put("name", event.getUser().getName()); + map.put("ip", event.getUser().getIp()); + map.put("createTime", LocalDateTime.now()); + data.setDataObj(map); + + wsDataPusher.push(data); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserDisConnectListener.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserDisConnectListener.java new file mode 100644 index 0000000..b952de0 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/listener/WsUserDisConnectListener.java @@ -0,0 +1,44 @@ +package com.lframework.starter.web.websocket.listener; + +import com.lframework.starter.web.websocket.components.WsDataPusher; +import com.lframework.starter.web.websocket.components.WsSessionManager; +import com.lframework.starter.web.websocket.constants.WsPool; +import com.lframework.starter.web.websocket.dto.WsPushData; +import com.lframework.starter.web.websocket.events.UserDisConnectEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class WsUserDisConnectListener implements ApplicationListener { + + @Autowired + private WsDataPusher wsDataPusher; + + @Override + public void onApplicationEvent(UserDisConnectEvent event) { + + if (log.isDebugEnabled()) { + log.debug("监听到用户断开连接事件,event={}", event); + } + WsPushData data = new WsPushData(); + data.setBizType(WsPool.PUSH_DISCONNECT); + data.setAll(Boolean.TRUE); + data.setTenantId(event.getUser().getTenantId()); + + // 这里直接用map了,不构建bo了 + Map map = new HashMap<>(); + map.put("name", event.getUser().getName()); + map.put("ip", event.getUser().getIp()); + map.put("createTime", LocalDateTime.now()); + data.setDataObj(map); + + wsDataPusher.push(data); + + WsSessionManager.removeSession(event.getSessionId()); + } +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/service/WsDataProcessService.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/service/WsDataProcessService.java new file mode 100644 index 0000000..e6e5604 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/service/WsDataProcessService.java @@ -0,0 +1,16 @@ +package com.lframework.starter.web.websocket.service; + +import com.lframework.starter.web.websocket.vo.WsVo; + +/** + * WS处理数据Service + */ +public interface WsDataProcessService { + + /** + * 处理 + * + * @param vo + */ + void process(WsVo vo); +} diff --git a/web-starter/src/main/java/com/lframework/starter/web/websocket/vo/WsVo.java b/web-starter/src/main/java/com/lframework/starter/web/websocket/vo/WsVo.java new file mode 100644 index 0000000..013c042 --- /dev/null +++ b/web-starter/src/main/java/com/lframework/starter/web/websocket/vo/WsVo.java @@ -0,0 +1,22 @@ +package com.lframework.starter.web.websocket.vo; + +import com.lframework.starter.web.core.vo.BaseVo; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class WsVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型 + */ + private String bizType; + + /** + * 数据 + */ + private String data; +} diff --git a/web-starter/src/main/java/lombok.config b/web-starter/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/web-starter/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/web-starter/src/main/resources/META-INF/spring.factories b/web-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..abb5c05 --- /dev/null +++ b/web-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,23 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.lframework.starter.web.config.MybatisAutoConfiguration,\ + com.lframework.starter.web.config.MybatisBeanAutoConfiguration,\ + com.lframework.starter.web.config.TransactionAutoConfiguration,\ + com.lframework.starter.web.config.TenantAutoConfiguration,\ + com.lframework.starter.web.config.CacheAutoConfiguration,\ + com.lframework.starter.web.config.KaptchaAutoConfiguration,\ + com.lframework.starter.web.config.LettuceAutoConfiguration,\ + com.lframework.starter.web.config.MailAutoConfiguration,\ + com.lframework.starter.web.config.PasswordEncoderAutoConfiguration,\ + com.lframework.starter.web.config.RedisAutoConfiguration,\ + com.lframework.starter.web.config.SecurityAutoConfiguration,\ + com.lframework.starter.web.config.SwaggerAutoConfiguration,\ + com.lframework.starter.web.config.UploadAutoConfiguration,\ + com.lframework.starter.web.config.WebAutoConfiguration,\ + com.lframework.starter.web.config.WebBeanAutoConfiguration,\ + com.lframework.starter.web.config.WebMvcAutoConfiguration,\ + com.lframework.starter.web.config.WebCommonAutoConfiguration,\ + com.lframework.starter.web.config.TenantDynamicDataSourceAutoConfiguration,\ + com.lframework.starter.web.config.SaTokenAutoConfiguration,\ + com.lframework.starter.web.config.MagicCustomAutoConfiguration,\ + com.lframework.starter.web.config.WebSwaggerAutoConfiguration,\ + com.lframework.starter.web.config.WsAutoConfiguration \ No newline at end of file diff --git a/web-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/web-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..d9c8277 --- /dev/null +++ b/web-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,22 @@ +com.lframework.starter.web.config.MybatisAutoConfiguration +com.lframework.starter.web.config.MybatisBeanAutoConfiguration +com.lframework.starter.web.config.TransactionAutoConfiguration +com.lframework.starter.web.config.TenantAutoConfiguration +com.lframework.starter.web.config.CacheAutoConfiguration +com.lframework.starter.web.config.KaptchaAutoConfiguration +com.lframework.starter.web.config.LettuceAutoConfiguration +com.lframework.starter.web.config.MailAutoConfiguration +com.lframework.starter.web.config.PasswordEncoderAutoConfiguration +com.lframework.starter.web.config.RedisAutoConfiguration +com.lframework.starter.web.config.SecurityAutoConfiguration +com.lframework.starter.web.config.SwaggerAutoConfiguration +com.lframework.starter.web.config.UploadAutoConfiguration +com.lframework.starter.web.config.WebAutoConfiguration +com.lframework.starter.web.config.WebBeanAutoConfiguration +com.lframework.starter.web.config.WebMvcAutoConfiguration +com.lframework.starter.web.config.WebCommonAutoConfiguration +com.lframework.starter.web.config.TenantDynamicDataSourceAutoConfiguration +com.lframework.starter.web.config.SaTokenAutoConfiguration +com.lframework.starter.web.config.MagicCustomAutoConfiguration +com.lframework.starter.web.config.WebSwaggerAutoConfiguration +com.lframework.starter.web.config.WsAutoConfiguration diff --git a/web-starter/src/main/resources/mappers/DicCityMapper.xml b/web-starter/src/main/resources/mappers/DicCityMapper.xml new file mode 100644 index 0000000..7499cb3 --- /dev/null +++ b/web-starter/src/main/resources/mappers/DicCityMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + SELECT id, + code, + name, + parent_id, + level + FROM dic_city + + + + + + diff --git a/web-starter/src/main/resources/mappers/GenerateCodeMapper.xml b/web-starter/src/main/resources/mappers/GenerateCodeMapper.xml new file mode 100644 index 0000000..be49558 --- /dev/null +++ b/web-starter/src/main/resources/mappers/GenerateCodeMapper.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/web-starter/src/main/resources/mappers/OpLogsMapper.xml b/web-starter/src/main/resources/mappers/OpLogsMapper.xml new file mode 100644 index 0000000..947b360 --- /dev/null +++ b/web-starter/src/main/resources/mappers/OpLogsMapper.xml @@ -0,0 +1,49 @@ + + + + + + SELECT + * + FROM op_logs + + + DELETE FROM op_logs + WHERE + + + + + + + diff --git a/web-starter/src/main/resources/mappers/QrtzMapper.xml b/web-starter/src/main/resources/mappers/QrtzMapper.xml new file mode 100644 index 0000000..2fe5620 --- /dev/null +++ b/web-starter/src/main/resources/mappers/QrtzMapper.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + SELECT + job.JOB_NAME AS `name`, + job.JOB_GROUP AS `group`, + job.DESCRIPTION AS description, + cron.CRON_EXPRESSION AS cron, + tri.TRIGGER_STATE AS state + FROM qrtz_job_details AS job + LEFT JOIN qrtz_triggers AS tri ON job.JOB_NAME = tri.JOB_NAME AND job.JOB_GROUP = tri.JOB_GROUP + LEFT JOIN qrtz_cron_triggers AS cron ON cron.TRIGGER_NAME = tri.TRIGGER_NAME AND cron.TRIGGER_GROUP= tri.JOB_GROUP + + + + + \ No newline at end of file diff --git a/web-starter/src/main/resources/mappers/RecursionMappingMappre.xml b/web-starter/src/main/resources/mappers/RecursionMappingMappre.xml new file mode 100644 index 0000000..dcb9a11 --- /dev/null +++ b/web-starter/src/main/resources/mappers/RecursionMappingMappre.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/web-starter/src/main/resources/mappers/SysParameterMapper.xml b/web-starter/src/main/resources/mappers/SysParameterMapper.xml new file mode 100644 index 0000000..e15c82d --- /dev/null +++ b/web-starter/src/main/resources/mappers/SysParameterMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.pm_key, + tb.pm_value, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_parameter AS tb + + diff --git a/web-starter/src/main/resources/mappers/TenantMapper.xml b/web-starter/src/main/resources/mappers/TenantMapper.xml new file mode 100644 index 0000000..e67e978 --- /dev/null +++ b/web-starter/src/main/resources/mappers/TenantMapper.xml @@ -0,0 +1,43 @@ + + + + + SELECT + tb.* + FROM tenant AS tb + + + + \ No newline at end of file diff --git a/web-starter/src/main/resources/mappers/UserDetailsMapper.xml b/web-starter/src/main/resources/mappers/UserDetailsMapper.xml new file mode 100644 index 0000000..f6c3c7f --- /dev/null +++ b/web-starter/src/main/resources/mappers/UserDetailsMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml b/web-starter/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml new file mode 100644 index 0000000..e3f3de5 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic_category AS tb + + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysDataDicItemMapper.xml b/web-starter/src/main/resources/mappers/system/SysDataDicItemMapper.xml new file mode 100644 index 0000000..24cb7c0 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysDataDicItemMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.dic_id, + tb.order_no, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic_item AS tb + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysDataDicMapper.xml b/web-starter/src/main/resources/mappers/system/SysDataDicMapper.xml new file mode 100644 index 0000000..359798d --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysDataDicMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.category_id, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic AS tb + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysDeptMapper.xml b/web-starter/src/main/resources/mappers/system/SysDeptMapper.xml new file mode 100644 index 0000000..e762797 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysDeptMapper.xml @@ -0,0 +1,22 @@ + + + + + + SELECT + * + FROM sys_dept + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysGenerateCodeMapper.xml b/web-starter/src/main/resources/mappers/system/SysGenerateCodeMapper.xml new file mode 100644 index 0000000..9493ad0 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysGenerateCodeMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + SELECT + tb.id, + tb.name, + tb.config_str + FROM sys_generate_code AS tb + + diff --git a/web-starter/src/main/resources/mappers/system/SysMailMessageMapper.xml.xml b/web-starter/src/main/resources/mappers/system/SysMailMessageMapper.xml.xml new file mode 100644 index 0000000..51ebf5a --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysMailMessageMapper.xml.xml @@ -0,0 +1,35 @@ + + + + + + SELECT + tb.* + FROM sys_mail_message tb + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysMenuMapper.xml b/web-starter/src/main/resources/mappers/system/SysMenuMapper.xml new file mode 100644 index 0000000..c442979 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysMenuMapper.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + SELECT id, + name, + path, + icon, + hidden, + display, + component_type, + component, + request_param, + parent_id, + title, + no_cache + FROM sys_menu + + + + SELECT + * + FROM sys_menu + + + + + + + + + + INSERT INTO sys_menu_collect (id, user_id, menu_id) VALUES (#{id}, #{userId}, #{menuId}) + + + DELETE FROM sys_menu_collect WHERE user_id = #{userId} AND menu_id = #{menuId} + + + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysNoticeLogMapper.xml b/web-starter/src/main/resources/mappers/system/SysNoticeLogMapper.xml new file mode 100644 index 0000000..eb4e9bb --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysNoticeLogMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + SELECT + tb.id, + tb.notice_id, + tb.user_id, + tb.readed, + tb.read_time + FROM sys_notice_log AS tb + + diff --git a/web-starter/src/main/resources/mappers/system/SysNoticeMapper.xml b/web-starter/src/main/resources/mappers/system/SysNoticeMapper.xml new file mode 100644 index 0000000..6c414ed --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysNoticeMapper.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.title, + tb.content, + tb.available, + tb.published, + tb.publish_time, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.readed_num, + tb.un_read_num + FROM sys_notice AS tb + + + + SELECT + tb.id, + tb.title, + tb.publish_time, + l.readed + FROM sys_notice_log AS l + INNER JOIN sys_notice AS tb ON tb.id = l.notice_id + + + + + UPDATE sys_notice SET readed_num = readed_num + 1, un_read_num = un_read_num - 1 WHERE id = #{id} + + + diff --git a/web-starter/src/main/resources/mappers/system/SysNotifyGroupMapper.xml b/web-starter/src/main/resources/mappers/system/SysNotifyGroupMapper.xml new file mode 100644 index 0000000..9646d1d --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysNotifyGroupMapper.xml @@ -0,0 +1,39 @@ + + + + + SELECT + tb.* + FROM sys_notify_group AS tb + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysNotifyGroupReceiverMapper.xml b/web-starter/src/main/resources/mappers/system/SysNotifyGroupReceiverMapper.xml new file mode 100644 index 0000000..3c19030 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysNotifyGroupReceiverMapper.xml @@ -0,0 +1,17 @@ + + + + + SELECT + tb.* + FROM sys_notify_group_receiver AS tb + + + diff --git a/web-starter/src/main/resources/mappers/system/SysOpenDomainMapper.xml b/web-starter/src/main/resources/mappers/system/SysOpenDomainMapper.xml new file mode 100644 index 0000000..bcaf04f --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysOpenDomainMapper.xml @@ -0,0 +1,43 @@ + + + + + + SELECT + * + FROM sys_open_domain + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysRoleCategoryMapper.xml b/web-starter/src/main/resources/mappers/system/SysRoleCategoryMapper.xml new file mode 100644 index 0000000..c110e0f --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysRoleCategoryMapper.xml @@ -0,0 +1,29 @@ + + + + + + SELECT + * + FROM sys_role_category AS tb + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysRoleMapper.xml b/web-starter/src/main/resources/mappers/system/SysRoleMapper.xml new file mode 100644 index 0000000..20df399 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysRoleMapper.xml @@ -0,0 +1,58 @@ + + + + + + SELECT + * + FROM sys_role + + + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysSiteMessageMapper.xml b/web-starter/src/main/resources/mappers/system/SysSiteMessageMapper.xml new file mode 100644 index 0000000..3b0d046 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysSiteMessageMapper.xml @@ -0,0 +1,56 @@ + + + + + + SELECT + tb.* + FROM sys_site_message tb + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysUserDeptMapper.xml b/web-starter/src/main/resources/mappers/system/SysUserDeptMapper.xml new file mode 100644 index 0000000..5c9e926 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysUserDeptMapper.xml @@ -0,0 +1,32 @@ + + + + + + SELECT + ud.* + FROM sys_user_dept AS ud + INNER JOIN sys_dept AS d ON d.id = ud.dept_id + INNER JOIN sys_user AS u ON u.id = ud.user_id + + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysUserGroupMapper.xml b/web-starter/src/main/resources/mappers/system/SysUserGroupMapper.xml new file mode 100644 index 0000000..a544209 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysUserGroupMapper.xml @@ -0,0 +1,45 @@ + + + + + SELECT + tb.* + FROM sys_user_group AS tb + + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysUserMapper.xml b/web-starter/src/main/resources/mappers/system/SysUserMapper.xml new file mode 100644 index 0000000..4dc727e --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysUserMapper.xml @@ -0,0 +1,95 @@ + + + + + + SELECT + u.* + FROM sys_user AS u + + + + + + + + UPDATE sys_user + SET password = #{password} + WHERE id = #{userId} + + + + UPDATE sys_user + SET email = #{email} + WHERE id = #{userId} + + + + UPDATE sys_user + SET telephone = #{telephone} + WHERE id = #{userId} + + + UPDATE sys_user + SET lock_status = TRUE + WHERE id = #{id} + + + UPDATE sys_user + SET lock_status = FALSE + WHERE id = #{id} + + + + diff --git a/web-starter/src/main/resources/mappers/system/SysUserRoleMapper.xml b/web-starter/src/main/resources/mappers/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..d5a58e2 --- /dev/null +++ b/web-starter/src/main/resources/mappers/system/SysUserRoleMapper.xml @@ -0,0 +1,24 @@ + + + + + SELECT + ur.* + FROM sys_user_role AS ur + INNER JOIN sys_role AS r ON r.id = ur.role_id + INNER JOIN sys_user AS u ON u.id = ur.user_id + + + +