From eb509c907f2a05419e3c8959f3a585212397734b Mon Sep 17 00:00:00 2001 From: lj7788 Date: Mon, 25 Aug 2025 10:54:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A1=86=E6=9E=B6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examapi/.gitignore | 47 + examapi/bin/clean.bat | 12 + examapi/bin/package.bat | 12 + examapi/bin/run.bat | 14 + examapi/pom.xml | 246 +++ examapi/ruoyi-admin/pom.xml | 101 + .../main/java/com/ruoyi/RuoYiApplication.java | 33 + .../com/ruoyi/RuoYiServletInitializer.java | 18 + .../controller/common/CaptchaController.java | 94 + .../controller/common/CommonController.java | 163 ++ .../controller/monitor/CacheController.java | 120 ++ .../controller/monitor/ServerController.java | 27 + .../monitor/SysLogininforController.java | 82 + .../monitor/SysOperlogController.java | 69 + .../monitor/SysUserOnlineController.java | 83 + .../system/SysConfigController.java | 133 ++ .../controller/system/SysDeptController.java | 142 ++ .../system/SysDictDataController.java | 121 ++ .../system/SysDictTypeController.java | 131 ++ .../controller/system/SysIndexController.java | 29 + .../controller/system/SysLoginController.java | 99 + .../controller/system/SysMenuController.java | 142 ++ .../system/SysNoticeController.java | 91 + .../controller/system/SysPostController.java | 129 ++ .../system/SysProfileController.java | 141 ++ .../system/SysRegisterController.java | 38 + .../controller/system/SysRoleController.java | 262 +++ .../controller/system/SysUserController.java | 251 +++ .../web/controller/tool/TestController.java | 183 ++ .../ruoyi/web/core/config/SwaggerConfig.java | 125 ++ .../META-INF/spring-devtools.properties | 1 + .../src/main/resources/application-druid.yml | 63 + .../src/main/resources/application.yml | 158 ++ .../ruoyi-admin/src/main/resources/banner.txt | 24 + .../main/resources/i18n/messages.properties | 38 + .../src/main/resources/logback.xml | 93 + .../main/resources/mybatis/mybatis-config.xml | 20 + examapi/ruoyi-common/pom.xml | 150 ++ .../ruoyi/common/annotation/Anonymous.java | 19 + .../ruoyi/common/annotation/DataScope.java | 33 + .../ruoyi/common/annotation/DataSource.java | 28 + .../com/ruoyi/common/annotation/Excel.java | 188 ++ .../com/ruoyi/common/annotation/Excels.java | 18 + .../java/com/ruoyi/common/annotation/Log.java | 51 + .../ruoyi/common/annotation/RateLimiter.java | 40 + .../ruoyi/common/annotation/RepeatSubmit.java | 31 + .../com/ruoyi/common/config/RuoYiConfig.java | 135 ++ .../ruoyi/common/constant/CacheConstants.java | 44 + .../com/ruoyi/common/constant/Constants.java | 142 ++ .../ruoyi/common/constant/GenConstants.java | 117 ++ .../com/ruoyi/common/constant/HttpStatus.java | 94 + .../common/constant/ScheduleConstants.java | 50 + .../ruoyi/common/constant/UserConstants.java | 78 + .../core/controller/BaseController.java | 202 ++ .../ruoyi/common/core/domain/AjaxResult.java | 216 ++ .../ruoyi/common/core/domain/BaseEntity.java | 118 ++ .../java/com/ruoyi/common/core/domain/R.java | 115 ++ .../ruoyi/common/core/domain/TreeEntity.java | 79 + .../ruoyi/common/core/domain/TreeSelect.java | 77 + .../common/core/domain/entity/SysDept.java | 203 ++ .../core/domain/entity/SysDictData.java | 176 ++ .../core/domain/entity/SysDictType.java | 96 + .../common/core/domain/entity/SysMenu.java | 259 +++ .../common/core/domain/entity/SysRole.java | 241 +++ .../common/core/domain/entity/SysUser.java | 426 ++++ .../common/core/domain/model/LoginBody.java | 69 + .../common/core/domain/model/LoginUser.java | 266 +++ .../core/domain/model/RegisterBody.java | 11 + .../ruoyi/common/core/page/PageDomain.java | 101 + .../ruoyi/common/core/page/TableDataInfo.java | 85 + .../ruoyi/common/core/page/TableSupport.java | 56 + .../ruoyi/common/core/redis/RedisCache.java | 268 +++ .../ruoyi/common/core/text/CharsetKit.java | 86 + .../com/ruoyi/common/core/text/Convert.java | 1000 ++++++++++ .../ruoyi/common/core/text/StrFormatter.java | 92 + .../ruoyi/common/enums/BusinessStatus.java | 20 + .../com/ruoyi/common/enums/BusinessType.java | 59 + .../ruoyi/common/enums/DataSourceType.java | 19 + .../com/ruoyi/common/enums/HttpMethod.java | 36 + .../com/ruoyi/common/enums/LimitType.java | 20 + .../com/ruoyi/common/enums/OperatorType.java | 24 + .../com/ruoyi/common/enums/UserStatus.java | 30 + .../common/exception/CustomException.java | 43 + .../common/exception/DemoModeException.java | 15 + .../common/exception/GlobalException.java | 58 + .../common/exception/ServiceException.java | 74 + .../ruoyi/common/exception/UtilException.java | 26 + .../common/exception/base/BaseException.java | 97 + .../common/exception/file/FileException.java | 19 + .../FileNameLengthLimitExceededException.java | 16 + .../file/FileSizeLimitExceededException.java | 16 + .../exception/file/FileUploadException.java | 61 + .../file/InvalidExtensionException.java | 80 + .../common/exception/job/TaskException.java | 34 + .../exception/user/BlackListException.java | 16 + .../exception/user/CaptchaException.java | 16 + .../user/CaptchaExpireException.java | 16 + .../common/exception/user/UserException.java | 18 + .../user/UserNotExistsException.java | 16 + .../user/UserPasswordNotMatchException.java | 16 + ...UserPasswordRetryLimitExceedException.java | 16 + .../filter/PropertyPreExcludeFilter.java | 24 + .../ruoyi/common/filter/RepeatableFilter.java | 52 + .../filter/RepeatedlyRequestWrapper.java | 76 + .../com/ruoyi/common/filter/XssFilter.java | 75 + .../filter/XssHttpServletRequestWrapper.java | 111 ++ .../java/com/ruoyi/common/utils/Arith.java | 114 ++ .../com/ruoyi/common/utils/DateUtils.java | 191 ++ .../com/ruoyi/common/utils/DictUtils.java | 186 ++ .../com/ruoyi/common/utils/ExceptionUtil.java | 39 + .../java/com/ruoyi/common/utils/LogUtils.java | 18 + .../com/ruoyi/common/utils/MessageUtils.java | 26 + .../com/ruoyi/common/utils/PageUtils.java | 35 + .../com/ruoyi/common/utils/SecurityUtils.java | 120 ++ .../com/ruoyi/common/utils/ServletUtils.java | 218 ++ .../com/ruoyi/common/utils/StringUtils.java | 614 ++++++ .../java/com/ruoyi/common/utils/Threads.java | 99 + .../ruoyi/common/utils/bean/BeanUtils.java | 110 ++ .../common/utils/bean/BeanValidators.java | 24 + .../common/utils/file/FileTypeUtils.java | 76 + .../common/utils/file/FileUploadUtils.java | 232 +++ .../ruoyi/common/utils/file/FileUtils.java | 291 +++ .../ruoyi/common/utils/file/ImageUtils.java | 98 + .../common/utils/file/MimeTypeUtils.java | 59 + .../ruoyi/common/utils/html/EscapeUtil.java | 167 ++ .../ruoyi/common/utils/html/HTMLFilter.java | 570 ++++++ .../ruoyi/common/utils/http/HttpHelper.java | 55 + .../ruoyi/common/utils/http/HttpUtils.java | 274 +++ .../ruoyi/common/utils/ip/AddressUtils.java | 56 + .../com/ruoyi/common/utils/ip/IpUtils.java | 382 ++++ .../common/utils/poi/ExcelHandlerAdapter.java | 19 + .../com/ruoyi/common/utils/poi/ExcelUtil.java | 1746 +++++++++++++++++ .../common/utils/reflect/ReflectUtils.java | 435 ++++ .../com/ruoyi/common/utils/sign/Base64.java | 291 +++ .../com/ruoyi/common/utils/sign/Md5Utils.java | 67 + .../common/utils/spring/SpringUtils.java | 158 ++ .../com/ruoyi/common/utils/sql/SqlUtil.java | 61 + .../com/ruoyi/common/utils/uuid/IdUtils.java | 49 + .../java/com/ruoyi/common/utils/uuid/Seq.java | 86 + .../com/ruoyi/common/utils/uuid/UUID.java | 484 +++++ .../main/java/com/ruoyi/common/xss/Xss.java | 27 + .../com/ruoyi/common/xss/XssValidator.java | 34 + examapi/ruoyi-framework/pom.xml | 70 + .../framework/aspectj/DataScopeAspect.java | 174 ++ .../framework/aspectj/DataSourceAspect.java | 72 + .../ruoyi/framework/aspectj/LogAspect.java | 249 +++ .../framework/aspectj/RateLimiterAspect.java | 89 + .../framework/config/ApplicationConfig.java | 30 + .../ruoyi/framework/config/CaptchaConfig.java | 83 + .../ruoyi/framework/config/DruidConfig.java | 126 ++ .../config/FastJson2JsonRedisSerializer.java | 48 + .../ruoyi/framework/config/FilterConfig.java | 58 + .../framework/config/KaptchaTextCreator.java | 68 + .../ruoyi/framework/config/MyBatisConfig.java | 132 ++ .../ruoyi/framework/config/RedisConfig.java | 69 + .../framework/config/ResourcesConfig.java | 73 + .../framework/config/SecurityConfig.java | 148 ++ .../ruoyi/framework/config/ServerConfig.java | 32 + .../framework/config/ThreadPoolConfig.java | 63 + .../config/properties/DruidProperties.java | 89 + .../properties/PermitAllUrlProperties.java | 73 + .../datasource/DynamicDataSource.java | 26 + .../DynamicDataSourceContextHolder.java | 45 + .../interceptor/RepeatSubmitInterceptor.java | 55 + .../impl/SameUrlDataInterceptor.java | 110 ++ .../ruoyi/framework/manager/AsyncManager.java | 55 + .../framework/manager/ShutdownManager.java | 39 + .../manager/factory/AsyncFactory.java | 102 + .../context/AuthenticationContextHolder.java | 28 + .../context/PermissionContextHolder.java | 27 + .../filter/JwtAuthenticationTokenFilter.java | 44 + .../handle/AuthenticationEntryPointImpl.java | 34 + .../handle/LogoutSuccessHandlerImpl.java | 52 + .../ruoyi/framework/web/domain/Server.java | 240 +++ .../framework/web/domain/server/Cpu.java | 101 + .../framework/web/domain/server/Jvm.java | 130 ++ .../framework/web/domain/server/Mem.java | 61 + .../framework/web/domain/server/Sys.java | 84 + .../framework/web/domain/server/SysFile.java | 114 ++ .../web/exception/GlobalExceptionHandler.java | 114 ++ .../web/service/PermissionService.java | 168 ++ .../web/service/SysLoginService.java | 181 ++ .../web/service/SysPasswordService.java | 94 + .../web/service/SysPermissionService.java | 83 + .../web/service/SysRegisterService.java | 115 ++ .../framework/web/service/TokenService.java | 226 +++ .../web/service/UserDetailsServiceImpl.java | 65 + examapi/ruoyi-generator/pom.xml | 40 + .../com/ruoyi/generator/config/GenConfig.java | 73 + .../generator/controller/GenController.java | 214 ++ .../com/ruoyi/generator/domain/GenTable.java | 372 ++++ .../generator/domain/GenTableColumn.java | 373 ++++ .../mapper/GenTableColumnMapper.java | 60 + .../generator/mapper/GenTableMapper.java | 83 + .../service/GenTableColumnServiceImpl.java | 68 + .../service/GenTableServiceImpl.java | 521 +++++ .../service/IGenTableColumnService.java | 44 + .../generator/service/IGenTableService.java | 121 ++ .../com/ruoyi/generator/util/GenUtils.java | 257 +++ .../generator/util/VelocityInitializer.java | 34 + .../ruoyi/generator/util/VelocityUtils.java | 402 ++++ .../src/main/resources/generator.yml | 10 + .../mapper/generator/GenTableColumnMapper.xml | 127 ++ .../mapper/generator/GenTableMapper.xml | 202 ++ .../main/resources/vm/java/controller.java.vm | 115 ++ .../src/main/resources/vm/java/domain.java.vm | 105 + .../src/main/resources/vm/java/mapper.java.vm | 91 + .../main/resources/vm/java/service.java.vm | 61 + .../resources/vm/java/serviceImpl.java.vm | 169 ++ .../main/resources/vm/java/sub-domain.java.vm | 76 + .../src/main/resources/vm/js/api.js.vm | 44 + .../src/main/resources/vm/sql/sql.vm | 22 + .../main/resources/vm/vue/index-tree.vue.vm | 505 +++++ .../src/main/resources/vm/vue/index.vue.vm | 602 ++++++ .../resources/vm/vue/v3/index-tree.vue.vm | 474 +++++ .../src/main/resources/vm/vue/v3/index.vue.vm | 590 ++++++ .../src/main/resources/vm/vue/v3/readme.txt | 1 + .../src/main/resources/vm/xml/mapper.xml.vm | 135 ++ examapi/ruoyi-quartz/pom.xml | 40 + .../ruoyi/quartz/config/ScheduleConfig.java | 57 + .../quartz/controller/SysJobController.java | 185 ++ .../controller/SysJobLogController.java | 92 + .../java/com/ruoyi/quartz/domain/SysJob.java | 171 ++ .../com/ruoyi/quartz/domain/SysJobLog.java | 155 ++ .../ruoyi/quartz/mapper/SysJobLogMapper.java | 64 + .../com/ruoyi/quartz/mapper/SysJobMapper.java | 67 + .../quartz/service/ISysJobLogService.java | 56 + .../ruoyi/quartz/service/ISysJobService.java | 102 + .../service/impl/SysJobLogServiceImpl.java | 87 + .../service/impl/SysJobServiceImpl.java | 261 +++ .../java/com/ruoyi/quartz/task/RyTask.java | 28 + .../ruoyi/quartz/util/AbstractQuartzJob.java | 107 + .../java/com/ruoyi/quartz/util/CronUtils.java | 63 + .../com/ruoyi/quartz/util/JobInvokeUtil.java | 182 ++ .../QuartzDisallowConcurrentExecution.java | 21 + .../ruoyi/quartz/util/QuartzJobExecution.java | 19 + .../com/ruoyi/quartz/util/ScheduleUtils.java | 141 ++ .../mapper/quartz/SysJobLogMapper.xml | 93 + .../resources/mapper/quartz/SysJobMapper.xml | 111 ++ examapi/ruoyi-system/pom.xml | 28 + .../com/ruoyi/system/domain/SysCache.java | 81 + .../com/ruoyi/system/domain/SysConfig.java | 111 ++ .../ruoyi/system/domain/SysLogininfor.java | 144 ++ .../com/ruoyi/system/domain/SysNotice.java | 102 + .../com/ruoyi/system/domain/SysOperLog.java | 269 +++ .../java/com/ruoyi/system/domain/SysPost.java | 124 ++ .../com/ruoyi/system/domain/SysRoleDept.java | 46 + .../com/ruoyi/system/domain/SysRoleMenu.java | 46 + .../ruoyi/system/domain/SysUserOnline.java | 113 ++ .../com/ruoyi/system/domain/SysUserPost.java | 46 + .../com/ruoyi/system/domain/SysUserRole.java | 46 + .../com/ruoyi/system/domain/vo/MetaVo.java | 106 + .../com/ruoyi/system/domain/vo/RouterVo.java | 148 ++ .../ruoyi/system/mapper/SysConfigMapper.java | 76 + .../ruoyi/system/mapper/SysDeptMapper.java | 118 ++ .../system/mapper/SysDictDataMapper.java | 95 + .../system/mapper/SysDictTypeMapper.java | 83 + .../system/mapper/SysLogininforMapper.java | 42 + .../ruoyi/system/mapper/SysMenuMapper.java | 125 ++ .../ruoyi/system/mapper/SysNoticeMapper.java | 60 + .../ruoyi/system/mapper/SysOperLogMapper.java | 48 + .../ruoyi/system/mapper/SysPostMapper.java | 99 + .../system/mapper/SysRoleDeptMapper.java | 44 + .../ruoyi/system/mapper/SysRoleMapper.java | 107 + .../system/mapper/SysRoleMenuMapper.java | 44 + .../ruoyi/system/mapper/SysUserMapper.java | 127 ++ .../system/mapper/SysUserPostMapper.java | 44 + .../system/mapper/SysUserRoleMapper.java | 62 + .../system/service/ISysConfigService.java | 89 + .../ruoyi/system/service/ISysDeptService.java | 124 ++ .../system/service/ISysDictDataService.java | 60 + .../system/service/ISysDictTypeService.java | 98 + .../system/service/ISysLogininforService.java | 40 + .../ruoyi/system/service/ISysMenuService.java | 144 ++ .../system/service/ISysNoticeService.java | 60 + .../system/service/ISysOperLogService.java | 48 + .../ruoyi/system/service/ISysPostService.java | 99 + .../ruoyi/system/service/ISysRoleService.java | 173 ++ .../system/service/ISysUserOnlineService.java | 48 + .../ruoyi/system/service/ISysUserService.java | 206 ++ .../service/impl/SysConfigServiceImpl.java | 232 +++ .../service/impl/SysDeptServiceImpl.java | 338 ++++ .../service/impl/SysDictDataServiceImpl.java | 111 ++ .../service/impl/SysDictTypeServiceImpl.java | 223 +++ .../impl/SysLogininforServiceImpl.java | 65 + .../service/impl/SysMenuServiceImpl.java | 531 +++++ .../service/impl/SysNoticeServiceImpl.java | 92 + .../service/impl/SysOperLogServiceImpl.java | 76 + .../service/impl/SysPostServiceImpl.java | 178 ++ .../service/impl/SysRoleServiceImpl.java | 424 ++++ .../impl/SysUserOnlineServiceImpl.java | 96 + .../service/impl/SysUserServiceImpl.java | 558 ++++++ .../mapper/system/SysConfigMapper.xml | 117 ++ .../resources/mapper/system/SysDeptMapper.xml | 159 ++ .../mapper/system/SysDictDataMapper.xml | 124 ++ .../mapper/system/SysDictTypeMapper.xml | 99 + .../mapper/system/SysLogininforMapper.xml | 57 + .../resources/mapper/system/SysMenuMapper.xml | 202 ++ .../mapper/system/SysNoticeMapper.xml | 89 + .../mapper/system/SysOperLogMapper.xml | 84 + .../resources/mapper/system/SysPostMapper.xml | 115 ++ .../mapper/system/SysRoleDeptMapper.xml | 34 + .../resources/mapper/system/SysRoleMapper.xml | 152 ++ .../mapper/system/SysRoleMenuMapper.xml | 34 + .../resources/mapper/system/SysUserMapper.xml | 255 +++ .../mapper/system/SysUserPostMapper.xml | 34 + .../mapper/system/SysUserRoleMapper.xml | 44 + examapi/ry.bat | 67 + examapi/ry.sh | 86 + examapi/yanzhu-exam/pom.xml | 198 ++ .../com/yanzhu/exam/cms/utils/DigitUtils.java | 31 + .../com/yanzhu/exam/cms/utils/FileUpload.java | 63 + .../yanzhu/exam/cms/utils/RandomUtils.java | 35 + .../controller/ExamTaskDataController.java | 50 + .../controller/ExamTaskGroupController.java | 106 + .../controller/ExamTaskManagerController.java | 174 ++ .../controller/ExamTaskPersonController.java | 111 ++ .../controller/ExamTaskPictureController.java | 103 + .../ExamTaskQuestionsController.java | 100 + .../yanzhu/exam/exam/domain/ExamTaskData.java | 13 + .../exam/exam/domain/ExamTaskGroup.java | 66 + .../exam/exam/domain/ExamTaskManager.java | 270 +++ .../exam/exam/domain/ExamTaskPerson.java | 111 ++ .../exam/exam/domain/ExamTaskPicture.java | 145 ++ .../exam/exam/domain/ExamTaskQuestions.java | 66 + .../exam/exam/mapper/ExamTaskGroupMapper.java | 61 + .../exam/mapper/ExamTaskManagerMapper.java | 69 + .../exam/mapper/ExamTaskPersonMapper.java | 93 + .../exam/mapper/ExamTaskPictureMapper.java | 61 + .../exam/mapper/ExamTaskQuestionsMapper.java | 61 + .../exam/service/IExamTaskDataService.java | 7 + .../exam/service/IExamTaskGroupService.java | 70 + .../exam/service/IExamTaskManagerService.java | 69 + .../exam/service/IExamTaskPersonService.java | 97 + .../exam/service/IExamTaskPictureService.java | 61 + .../service/IExamTaskQuestionsService.java | 63 + .../service/impl/ExamTaskDataServiceImpl.java | 95 + .../impl/ExamTaskGroupServiceImpl.java | 127 ++ .../impl/ExamTaskManagerServiceImpl.java | 187 ++ .../impl/ExamTaskPersonServiceImpl.java | 125 ++ .../impl/ExamTaskPictureServiceImpl.java | 95 + .../impl/ExamTaskQuestionsServiceImpl.java | 113 ++ .../exam/fms/common/NotSameFileExpection.java | 7 + .../fms/controller/FmsFilesController.java | 195 ++ .../fms/controller/FmsPhotoController.java | 181 ++ .../com/yanzhu/exam/fms/domain/FmsFiles.java | 93 + .../com/yanzhu/exam/fms/domain/FmsPhoto.java | 166 ++ .../exam/fms/domain/MultipartFileParam.java | 61 + .../yanzhu/exam/fms/domain/dto/StdOut.java | 66 + .../exam/fms/mapper/FmsFilesMapper.java | 61 + .../exam/fms/mapper/FmsPhotoMapper.java | 61 + .../yanzhu/exam/fms/service/ChunkService.java | 16 + .../exam/fms/service/IFmsFilesService.java | 61 + .../exam/fms/service/IFmsPhotoService.java | 61 + .../fms/service/impl/ChunkServiceImpl.java | 104 + .../fms/service/impl/FmsFilesServiceImpl.java | 93 + .../fms/service/impl/FmsPhotoServiceImpl.java | 93 + .../com/yanzhu/exam/fms/utils/FileUpload.java | 66 + .../yanzhu/exam/fms/utils/RandomUtils.java | 35 + .../ExamFinishAnswerController.java | 113 ++ .../ExamQuestionsContentDataController.java | 55 + .../ExamQuestionsListDataController.java | 29 + .../controller/ExamTaskAnswerController.java | 103 + .../controller/ExamTitleController.java | 39 + .../controller/ExamUserScoreController.java | 112 ++ .../onlineexam/domain/ExamFinishAnswer.java | 119 ++ .../onlineexam/domain/ExamTaskAnswer.java | 147 ++ .../exam/onlineexam/domain/ExamUserScore.java | 166 ++ .../domain/dto/ExamQuestionsContentData.java | 17 + .../domain/dto/ExamQuestionsData.java | 24 + .../domain/dto/ExamQuestionsListData.java | 16 + .../onlineexam/domain/dto/ExamTitleData.java | 74 + .../mapper/ExamFinishAnswerMapper.java | 77 + .../ExamQuestionsContentDataMapper.java | 10 + .../mapper/ExamQuestionsListDataMapper.java | 9 + .../mapper/ExamTaskAnswerMapper.java | 68 + .../mapper/ExamTitleDataMapper.java | 7 + .../mapper/ExamUserScoreMapper.java | 78 + .../service/IExamFinishAnswerService.java | 77 + .../IExamQuestionsContentDataService.java | 10 + .../IExamQuestionsListDataService.java | 10 + .../service/IExamTaskAnswerService.java | 69 + .../service/IExamTitleDataService.java | 7 + .../service/IExamUserScoreService.java | 78 + .../impl/ExamFinishAnswerServiceImpl.java | 132 ++ .../ExamQuestionsContentDataServiceImpl.java | 24 + .../ExamQuestionsListDataServiceImpl.java | 23 + .../impl/ExamTaskAnswerServiceImpl.java | 105 + .../impl/ExamTitleDataServiceImpl.java | 21 + .../impl/ExamUserScoreServiceImpl.java | 107 + .../controller/ExamBankPictureController.java | 103 + .../ExamQuestionsAnswerController.java | 109 + .../ExamQuestionsBankController.java | 212 ++ .../ExamQuestionsContentController.java | 102 + .../controller/ExamQuestionsController.java | 267 +++ .../ExamQuestionsListController.java | 63 + .../ExamQuestionsPropertyController.java | 113 ++ .../controller/ExamTypeController.java | 120 ++ .../questions/domain/ExamBankPicture.java | 134 ++ .../exam/questions/domain/ExamQuestions.java | 346 ++++ .../questions/domain/ExamQuestionsAnswer.java | 94 + .../questions/domain/ExamQuestionsBank.java | 262 +++ .../domain/ExamQuestionsContent.java | 59 + .../questions/domain/ExamQuestionsList.java | 222 +++ .../domain/ExamQuestionsProperty.java | 241 +++ .../exam/questions/domain/ExamType.java | 126 ++ .../exam/questions/domain/TypeTreeSelect.java | 72 + .../mapper/ExamBankPictureMapper.java | 61 + .../mapper/ExamQuestionsAnswerMapper.java | 69 + .../mapper/ExamQuestionsBankMapper.java | 77 + .../mapper/ExamQuestionsContentMapper.java | 61 + .../mapper/ExamQuestionsListMapper.java | 25 + .../questions/mapper/ExamQuestionsMapper.java | 69 + .../mapper/ExamQuestionsPropertyMapper.java | 61 + .../exam/questions/mapper/ExamTypeMapper.java | 61 + .../service/IExamBankPictureService.java | 61 + .../service/IExamQuestionsAnswerService.java | 69 + .../service/IExamQuestionsBankService.java | 82 + .../service/IExamQuestionsContentService.java | 61 + .../service/IExamQuestionsListService.java | 26 + .../IExamQuestionsPropertyService.java | 61 + .../service/IExamQuestionsService.java | 79 + .../questions/service/IExamTypeService.java | 79 + .../impl/ExamBankPictureServiceImpl.java | 95 + .../impl/ExamQuestionsAnswerServiceImpl.java | 99 + .../impl/ExamQuestionsBankServiceImpl.java | 180 ++ .../impl/ExamQuestionsContentServiceImpl.java | 93 + .../impl/ExamQuestionsListServiceImpl.java | 49 + .../ExamQuestionsPropertyServiceImpl.java | 95 + .../impl/ExamQuestionsServiceImpl.java | 208 ++ .../service/impl/ExamTypeServiceImpl.java | 183 ++ .../system/controller/SysGroupController.java | 122 ++ .../controller/SysGroupPersonController.java | 93 + .../controller/SysUserChoiceController.java | 118 ++ .../controller/SysUserDataController.java | 41 + .../controller/TempUserChoiceController.java | 100 + .../yanzhu/exam/system/domain/SysGroup.java | 106 + .../exam/system/domain/SysGroupPerson.java | 71 + .../exam/system/domain/SysUserChoice.java | 66 + .../exam/system/domain/TempUserChoice.java | 66 + .../exam/system/domain/dto/SysUserCopy.java | 11 + .../exam/system/domain/dto/SysUserData.java | 23 + .../exam/system/mapper/SysGroupMapper.java | 69 + .../system/mapper/SysGroupPersonMapper.java | 61 + .../system/mapper/SysUserChoiceMapper.java | 75 + .../exam/system/mapper/SysUserDataMapper.java | 12 + .../system/mapper/TempUserChoiceMapper.java | 61 + .../service/ISysGroupPersonService.java | 61 + .../exam/system/service/ISysGroupService.java | 69 + .../system/service/ISysUserChoiceService.java | 75 + .../system/service/ISysUserDataService.java | 13 + .../service/ITempUserChoiceService.java | 56 + .../impl/SysGroupPersonServiceImpl.java | 100 + .../service/impl/SysGroupServiceImpl.java | 101 + .../impl/SysUserChoiceServiceImpl.java | 113 ++ .../service/impl/SysUserDataServiceImpl.java | 29 + .../impl/TempUserChoiceServiceImpl.java | 90 + .../com/yanzhu/exam/ueditor/ActionEnter.java | 127 ++ .../yanzhu/exam/ueditor/ConfigManager.java | 233 +++ .../java/com/yanzhu/exam/ueditor/Encoder.java | 24 + .../com/yanzhu/exam/ueditor/PathFormat.java | 157 ++ .../exam/ueditor/common/UEditorFile.java | 32 + .../exam/ueditor/common/UEditorUpload.java | 137 ++ .../ueditor/controller/UEditorController.java | 92 + .../yanzhu/exam/ueditor/define/ActionMap.java | 42 + .../exam/ueditor/define/ActionState.java | 5 + .../yanzhu/exam/ueditor/define/AppInfo.java | 77 + .../yanzhu/exam/ueditor/define/BaseState.java | 92 + .../yanzhu/exam/ueditor/define/FileType.java | 31 + .../yanzhu/exam/ueditor/define/MIMEType.java | 20 + .../exam/ueditor/define/MultiState.java | 112 ++ .../com/yanzhu/exam/ueditor/define/State.java | 18 + .../exam/ueditor/hunter/FileManager.java | 112 ++ .../exam/ueditor/hunter/ImageHunter.java | 144 ++ .../exam/ueditor/upload/Base64Uploader.java | 52 + .../exam/ueditor/upload/BinaryUploader.java | 98 + .../exam/ueditor/upload/StorageManager.java | 158 ++ .../yanzhu/exam/ueditor/upload/Uploader.java | 29 + .../mapper/exam/ExamTaskGroupMapper.xml | 60 + .../mapper/exam/ExamTaskManagerMapper.xml | 161 ++ .../mapper/exam/ExamTaskPersonMapper.xml | 109 + .../mapper/exam/ExamTaskPictureMapper.xml | 84 + .../mapper/exam/ExamTaskQuestionsMapper.xml | 61 + .../resources/mapper/fms/FmsFilesMapper.xml | 88 + .../resources/mapper/fms/FmsPhotoMapper.xml | 85 + .../onlineexam/ExamFinishAnswerMapper.xml | 93 + .../ExamQuestionsContentDataMapper.xml | 27 + .../ExamQuestionsListDataMapper.xml | 44 + .../onlineexam/ExamTaskAnswerMapper.xml | 88 + .../mapper/onlineexam/ExamTitleDataMapper.xml | 136 ++ .../mapper/onlineexam/ExamUserScoreMapper.xml | 114 ++ .../questions/ExamBankPictureMapper.xml | 84 + .../questions/ExamQuestionsAnswerMapper.xml | 79 + .../questions/ExamQuestionsBankMapper.xml | 143 ++ .../questions/ExamQuestionsContentMapper.xml | 57 + .../questions/ExamQuestionsListMapper.xml | 50 + .../mapper/questions/ExamQuestionsMapper.xml | 110 ++ .../questions/ExamQuestionsPropertyMapper.xml | 105 + .../mapper/questions/ExamTypeMapper.xml | 80 + .../mapper/system/SysGroupMapper.xml | 93 + .../mapper/system/SysGroupPersonMapper.xml | 59 + .../mapper/system/SysUserChoiceMapper.xml | 113 ++ .../mapper/system/SysUserDataMapper.xml | 54 + .../mapper/system/TempUserChoiceMapper.xml | 66 + 504 files changed, 55314 insertions(+) create mode 100644 examapi/.gitignore create mode 100644 examapi/bin/clean.bat create mode 100644 examapi/bin/package.bat create mode 100644 examapi/bin/run.bat create mode 100644 examapi/pom.xml create mode 100644 examapi/ruoyi-admin/pom.xml create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java create mode 100644 examapi/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java create mode 100644 examapi/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties create mode 100644 examapi/ruoyi-admin/src/main/resources/application-druid.yml create mode 100644 examapi/ruoyi-admin/src/main/resources/application.yml create mode 100644 examapi/ruoyi-admin/src/main/resources/banner.txt create mode 100644 examapi/ruoyi-admin/src/main/resources/i18n/messages.properties create mode 100644 examapi/ruoyi-admin/src/main/resources/logback.xml create mode 100644 examapi/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml create mode 100644 examapi/ruoyi-common/pom.xml create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java create mode 100644 examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java create mode 100644 examapi/ruoyi-framework/pom.xml create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java create mode 100644 examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java create mode 100644 examapi/ruoyi-generator/pom.xml create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java create mode 100644 examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java create mode 100644 examapi/ruoyi-generator/src/main/resources/generator.yml create mode 100644 examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml create mode 100644 examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/controller.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/domain.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/service.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/js/api.js.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/sql/sql.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt create mode 100644 examapi/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm create mode 100644 examapi/ruoyi-quartz/pom.xml create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java create mode 100644 examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java create mode 100644 examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml create mode 100644 examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml create mode 100644 examapi/ruoyi-system/pom.xml create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml create mode 100644 examapi/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml create mode 100644 examapi/ry.bat create mode 100755 examapi/ry.sh create mode 100644 examapi/yanzhu-exam/pom.xml create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/DigitUtils.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/FileUpload.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/RandomUtils.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskDataController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskGroupController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskManagerController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPersonController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPictureController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskQuestionsController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskGroup.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskManager.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPerson.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPicture.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskQuestions.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskGroupMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskManagerMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPersonMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPictureMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskQuestionsMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskDataService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskGroupService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskManagerService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPersonService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPictureService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskQuestionsService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskDataServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskGroupServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskManagerServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPersonServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPictureServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskQuestionsServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/common/NotSameFileExpection.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsFilesController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsPhotoController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsFiles.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsPhoto.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/MultipartFileParam.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/dto/StdOut.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsFilesMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsPhotoMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/ChunkService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsFilesService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsPhotoService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/ChunkServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsFilesServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsPhotoServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/FileUpload.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/RandomUtils.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamFinishAnswerController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsContentDataController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsListDataController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTaskAnswerController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTitleController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamUserScoreController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamFinishAnswer.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamTaskAnswer.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamUserScore.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsContentData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsListData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamTitleData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamFinishAnswerMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsContentDataMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsListDataMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTaskAnswerMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTitleDataMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamUserScoreMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamFinishAnswerService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsContentDataService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsListDataService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTaskAnswerService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTitleDataService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamUserScoreService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamFinishAnswerServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsContentDataServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsListDataServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTaskAnswerServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTitleDataServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamUserScoreServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamBankPictureController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsAnswerController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsBankController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsContentController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsListController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsPropertyController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamTypeController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamBankPicture.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestions.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsAnswer.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsBank.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsContent.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsList.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsProperty.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamType.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/TypeTreeSelect.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamBankPictureMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsAnswerMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsBankMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsContentMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsListMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsPropertyMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamTypeMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamBankPictureService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsAnswerService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsBankService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsContentService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsListService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsPropertyService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamTypeService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamBankPictureServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsAnswerServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsBankServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsContentServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsListServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsPropertyServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamTypeServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupPersonController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserChoiceController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserDataController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/TempUserChoiceController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroup.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroupPerson.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysUserChoice.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/TempUserChoice.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserCopy.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserData.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupPersonMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserChoiceMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserDataMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/TempUserChoiceMapper.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupPersonService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserChoiceService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserDataService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ITempUserChoiceService.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupPersonServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserChoiceServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserDataServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/TempUserChoiceServiceImpl.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ActionEnter.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ConfigManager.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/Encoder.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/PathFormat.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorFile.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorUpload.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/controller/UEditorController.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionMap.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionState.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/AppInfo.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/BaseState.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/FileType.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MIMEType.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MultiState.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/State.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/FileManager.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/ImageHunter.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Base64Uploader.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/BinaryUploader.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/StorageManager.java create mode 100644 examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Uploader.java create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskGroupMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskManagerMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPersonMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPictureMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskQuestionsMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsFilesMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsPhotoMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamFinishAnswerMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsContentDataMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsListDataMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTaskAnswerMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTitleDataMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamUserScoreMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamBankPictureMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsAnswerMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsBankMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsContentMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsListMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsPropertyMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamTypeMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupPersonMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserChoiceMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserDataMapper.xml create mode 100644 examapi/yanzhu-exam/src/main/resources/mapper/system/TempUserChoiceMapper.xml diff --git a/examapi/.gitignore b/examapi/.gitignore new file mode 100644 index 0000000..0c0da3e --- /dev/null +++ b/examapi/.gitignore @@ -0,0 +1,47 @@ +###################################################################### +# Build Tools + +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +target/ +!.mvn/wrapper/maven-wrapper.jar + +###################################################################### +# IDE + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### JRebel ### +rebel.xml + +### NetBeans ### +nbproject/private/ +build/* +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +###################################################################### +# Others +*.log +*.xml.versionsBackup +*.swp + +!*/build/*.java +!*/build/*.html +!*/build/*.xml diff --git a/examapi/bin/clean.bat b/examapi/bin/clean.bat new file mode 100644 index 0000000..af841d8 --- /dev/null +++ b/examapi/bin/clean.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [ÐÅÏ¢] ÇåÀí¹¤³ÌtargetÉú³É·¾¶¡£ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean + +pause \ No newline at end of file diff --git a/examapi/bin/package.bat b/examapi/bin/package.bat new file mode 100644 index 0000000..af8af8e --- /dev/null +++ b/examapi/bin/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [ÐÅÏ¢] ´ò°üWeb¹¤³Ì£¬Éú³Éwar/jar°üÎļþ¡£ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean package -Dmaven.test.skip=true + +pause \ No newline at end of file diff --git a/examapi/bin/run.bat b/examapi/bin/run.bat new file mode 100644 index 0000000..99c4992 --- /dev/null +++ b/examapi/bin/run.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [ÐÅÏ¢] ʹÓÃJarÃüÁîÔËÐÐWeb¹¤³Ì¡£ +echo. + +cd %~dp0 +cd ../ruoyi-admin/target + +set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -jar %JAVA_OPTS% ruoyi-admin.jar + +cd bin +pause \ No newline at end of file diff --git a/examapi/pom.xml b/examapi/pom.xml new file mode 100644 index 0000000..96bad78 --- /dev/null +++ b/examapi/pom.xml @@ -0,0 +1,246 @@ + + + 4.0.0 + + com.ruoyi + ruoyi + 3.8.6 + + ruoyi + http://www.ruoyi.vip + è‹¥ä¾ç®¡ç†ç³»ç»Ÿ + + + 3.8.6 + UTF-8 + UTF-8 + 1.8 + 3.1.1 + 1.2.16 + 1.21 + 3.0.0 + 2.3.3 + 1.4.6 + 2.0.34 + 6.4.3 + 2.11.0 + 3.2.2 + 4.1.2 + 2.3 + 0.9.1 + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.5.15 + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + eu.bitwalker + UserAgentUtils + ${bitwalker.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + + io.springfox + springfox-boot-starter + ${swagger.version} + + + io.swagger + swagger-models + + + + + + + commons-io + commons-io + ${commons.io.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + + + commons-collections + commons-collections + ${commons.collections.version} + + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson.version} + + + + + org.springframework.boot + spring-boot-starter-validation + 2.5.15 + + + + + com.mysql + mysql-connector-j + 8.0.33 + + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + + pro.fessional + kaptcha + ${kaptcha.version} + + + + + com.ruoyi + ruoyi-quartz + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-generator + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-framework + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-system + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + com.ruoyi + yanzhu-exam + ${ruoyi.version} + + + + + + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-quartz + ruoyi-generator + ruoyi-common + yanzhu-exam + + pom + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public + + true + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public + + true + + + false + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-admin/pom.xml b/examapi/ruoyi-admin/pom.xml new file mode 100644 index 0000000..2a73f38 --- /dev/null +++ b/examapi/ruoyi-admin/pom.xml @@ -0,0 +1,101 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + jar + examapi + + + webæœåŠ¡å…¥å£ + + + + + + + org.springframework.boot + spring-boot-devtools + true + + + + + io.springfox + springfox-boot-starter + + + + + io.swagger + swagger-models + 1.6.2 + + + + + com.mysql + mysql-connector-j + + + + + com.ruoyi + ruoyi-framework + + + + + com.ruoyi + ruoyi-quartz + + + + + com.ruoyi + ruoyi-generator + + + + + com.ruoyi + yanzhu-exam + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 + + false + ${project.artifactId} + + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java new file mode 100644 index 0000000..143f842 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -0,0 +1,33 @@ +package com.ruoyi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +/** + * å¯åŠ¨ç¨‹åº + * + * @author ruoyi + */ +@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +@ComponentScan(basePackages = {"com.ruoyi", "com.yanzhu.exam"}) +public class RuoYiApplication +{ + public static void main(String[] args) + { + // System.setProperty("spring.devtools.restart.enabled", "false"); + SpringApplication.run(RuoYiApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ è‹¥ä¾å¯åЍæˆåŠŸ ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java new file mode 100644 index 0000000..9d82a23 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java @@ -0,0 +1,18 @@ +package com.ruoyi; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * web容器中进行部署 + * + * @author ruoyi + */ +public class RuoYiServletInitializer extends SpringBootServletInitializer +{ + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) + { + return application.sources(RuoYiApplication.class); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java new file mode 100644 index 0000000..e1a397e --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -0,0 +1,94 @@ +package com.ruoyi.web.controller.common; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.FastByteArrayOutputStream; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import com.google.code.kaptcha.Producer; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.sign.Base64; +import com.ruoyi.common.utils.uuid.IdUtils; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 验è¯ç æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +public class CaptchaController +{ + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysConfigService configService; + /** + * 生æˆéªŒè¯ç  + */ + @GetMapping("/captchaImage") + public AjaxResult getCode(HttpServletResponse response) throws IOException + { + AjaxResult ajax = AjaxResult.success(); + boolean captchaEnabled = configService.selectCaptchaEnabled(); + ajax.put("captchaEnabled", captchaEnabled); + if (!captchaEnabled) + { + return ajax; + } + + // ä¿å­˜éªŒè¯ç ä¿¡æ¯ + String uuid = IdUtils.simpleUUID(); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + // 生æˆéªŒè¯ç  + String captchaType = RuoYiConfig.getCaptchaType(); + if ("math".equals(captchaType)) + { + String capText = captchaProducerMath.createText(); + capStr = capText.substring(0, capText.lastIndexOf("@")); + code = capText.substring(capText.lastIndexOf("@") + 1); + image = captchaProducerMath.createImage(capStr); + } + else if ("char".equals(captchaType)) + { + capStr = code = captchaProducer.createText(); + image = captchaProducer.createImage(capStr); + } + + redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + // è½¬æ¢æµä¿¡æ¯å†™å‡º + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try + { + ImageIO.write(image, "jpg", os); + } + catch (IOException e) + { + return AjaxResult.error(e.getMessage()); + } + + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + return ajax; + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java new file mode 100644 index 0000000..d51d61d --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -0,0 +1,163 @@ +package com.ruoyi.web.controller.common; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.framework.config.ServerConfig; + +/** + * é€šç”¨è¯·æ±‚å¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/common") +public class CommonController +{ + private static final Logger log = LoggerFactory.getLogger(CommonController.class); + + @Autowired + private ServerConfig serverConfig; + + private static final String FILE_DELIMETER = ","; + + /** + * 通用下载请求 + * + * @param fileName 文件åç§° + * @param delete 是å¦åˆ é™¤ + */ + @GetMapping("/download") + public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) + { + try + { + if (!FileUtils.checkAllowDownload(fileName)) + { + throw new Exception(StringUtils.format("文件åç§°({})éžæ³•,ä¸å…许下载。 ", fileName)); + } + String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); + String filePath = RuoYiConfig.getDownloadPath() + fileName; + + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, realFileName); + FileUtils.writeBytes(filePath, response.getOutputStream()); + if (delete) + { + FileUtils.deleteFile(filePath); + } + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } + + /** + * 通用上传请求(å•个) + */ + @PostMapping("/upload") + public AjaxResult uploadFile(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + // 上传并返回新文件åç§° + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + AjaxResult ajax = AjaxResult.success(); + ajax.put("url", url); + ajax.put("fileName", fileName); + ajax.put("newFileName", FileUtils.getName(fileName)); + ajax.put("originalFilename", file.getOriginalFilename()); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 通用上传请求(多个) + */ + @PostMapping("/uploads") + public AjaxResult uploadFiles(List files) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + List urls = new ArrayList(); + List fileNames = new ArrayList(); + List newFileNames = new ArrayList(); + List originalFilenames = new ArrayList(); + for (MultipartFile file : files) + { + // 上传并返回新文件åç§° + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + urls.add(url); + fileNames.add(fileName); + newFileNames.add(FileUtils.getName(fileName)); + originalFilenames.add(file.getOriginalFilename()); + } + AjaxResult ajax = AjaxResult.success(); + ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER)); + ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER)); + ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER)); + ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER)); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 本地资æºé€šç”¨ä¸‹è½½ + */ + @GetMapping("/download/resource") + public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + try + { + if (!FileUtils.checkAllowDownload(resource)) + { + throw new Exception(StringUtils.format("èµ„æºæ–‡ä»¶({})éžæ³•,ä¸å…许下载。 ", resource)); + } + // 本地资æºè·¯å¾„ + String localPath = RuoYiConfig.getProfile(); + // æ•°æ®åº“资æºåœ°å€ + String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); + // 下载åç§° + String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, downloadName); + FileUtils.writeBytes(downloadPath, response.getOutputStream()); + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java new file mode 100644 index 0000000..41029fd --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java @@ -0,0 +1,120 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysCache; + +/** + * 缓存监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/cache") +public class CacheController +{ + @Autowired + private RedisTemplate redisTemplate; + + private final static List caches = new ArrayList(); + { + caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信æ¯")); + caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "é…置信æ¯")); + caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "æ•°æ®å­—å…¸")); + caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验è¯ç ")); + caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "é˜²é‡æäº¤")); + caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "陿µå¤„ç†")); + caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密ç é”™è¯¯æ¬¡æ•°")); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping() + public AjaxResult getInfo() throws Exception + { + Properties info = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info()); + Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info("commandstats")); + Object dbSize = redisTemplate.execute((RedisCallback) connection -> connection.dbSize()); + + Map result = new HashMap<>(3); + result.put("info", info); + result.put("dbSize", dbSize); + + List> pieList = new ArrayList<>(); + commandStats.stringPropertyNames().forEach(key -> { + Map data = new HashMap<>(2); + String property = commandStats.getProperty(key); + data.put("name", StringUtils.removeStart(key, "cmdstat_")); + data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); + pieList.add(data); + }); + result.put("commandStats", pieList); + return AjaxResult.success(result); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getNames") + public AjaxResult cache() + { + return AjaxResult.success(caches); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getKeys/{cacheName}") + public AjaxResult getCacheKeys(@PathVariable String cacheName) + { + Set cacheKeys = redisTemplate.keys(cacheName + "*"); + return AjaxResult.success(cacheKeys); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getValue/{cacheName}/{cacheKey}") + public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) + { + String cacheValue = redisTemplate.opsForValue().get(cacheKey); + SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue); + return AjaxResult.success(sysCache); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheName/{cacheName}") + public AjaxResult clearCacheName(@PathVariable String cacheName) + { + Collection cacheKeys = redisTemplate.keys(cacheName + "*"); + redisTemplate.delete(cacheKeys); + return AjaxResult.success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheKey/{cacheKey}") + public AjaxResult clearCacheKey(@PathVariable String cacheKey) + { + redisTemplate.delete(cacheKey); + return AjaxResult.success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheAll") + public AjaxResult clearCacheAll() + { + Collection cacheKeys = redisTemplate.keys("*"); + redisTemplate.delete(cacheKeys); + return AjaxResult.success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java new file mode 100644 index 0000000..082027b --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java @@ -0,0 +1,27 @@ +package com.ruoyi.web.controller.monitor; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.framework.web.domain.Server; + +/** + * æœåŠ¡å™¨ç›‘æŽ§ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/server") +public class ServerController +{ + @PreAuthorize("@ss.hasPermi('monitor:server:list')") + @GetMapping() + public AjaxResult getInfo() throws Exception + { + Server server = new Server(); + server.copyTo(); + return AjaxResult.success(server); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java new file mode 100644 index 0000000..f9f262e --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java @@ -0,0 +1,82 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.SysPasswordService; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.service.ISysLogininforService; + +/** + * 系统访问记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/logininfor") +public class SysLogininforController extends BaseController +{ + @Autowired + private ISysLogininforService logininforService; + + @Autowired + private SysPasswordService passwordService; + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") + @GetMapping("/list") + public TableDataInfo list(SysLogininfor logininfor) + { + startPage(); + List list = logininforService.selectLogininforList(logininfor); + return getDataTable(list); + } + + @Log(title = "登录日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysLogininfor logininfor) + { + List list = logininforService.selectLogininforList(logininfor); + ExcelUtil util = new ExcelUtil(SysLogininfor.class); + util.exportExcel(response, list, "登录日志"); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{infoIds}") + public AjaxResult remove(@PathVariable Long[] infoIds) + { + return toAjax(logininforService.deleteLogininforByIds(infoIds)); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + logininforService.cleanLogininfor(); + return success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')") + @Log(title = "账户解é”", businessType = BusinessType.OTHER) + @GetMapping("/unlock/{userName}") + public AjaxResult unlock(@PathVariable("userName") String userName) + { + passwordService.clearLoginRecordCache(userName); + return success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java new file mode 100644 index 0000000..5378424 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -0,0 +1,69 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysOperLogService; + +/** + * æ“作日志记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/operlog") +public class SysOperlogController extends BaseController +{ + @Autowired + private ISysOperLogService operLogService; + + @PreAuthorize("@ss.hasPermi('monitor:operlog:list')") + @GetMapping("/list") + public TableDataInfo list(SysOperLog operLog) + { + startPage(); + List list = operLogService.selectOperLogList(operLog); + return getDataTable(list); + } + + @Log(title = "æ“作日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:operlog:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysOperLog operLog) + { + List list = operLogService.selectOperLogList(operLog); + ExcelUtil util = new ExcelUtil(SysOperLog.class); + util.exportExcel(response, list, "æ“作日志"); + } + + @Log(title = "æ“作日志", businessType = BusinessType.DELETE) + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/{operIds}") + public AjaxResult remove(@PathVariable Long[] operIds) + { + return toAjax(operLogService.deleteOperLogByIds(operIds)); + } + + @Log(title = "æ“作日志", businessType = BusinessType.CLEAN) + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/clean") + public AjaxResult clean() + { + operLogService.cleanOperLog(); + return success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java new file mode 100644 index 0000000..7c343e2 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -0,0 +1,83 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; + +/** + * 在线用户监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/online") +public class SysUserOnlineController extends BaseController +{ + @Autowired + private ISysUserOnlineService userOnlineService; + + @Autowired + private RedisCache redisCache; + + @PreAuthorize("@ss.hasPermi('monitor:online:list')") + @GetMapping("/list") + public TableDataInfo list(String ipaddr, String userName) + { + Collection keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList(); + for (String key : keys) + { + LoginUser user = redisCache.getCacheObject(key); + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + else if (StringUtils.isNotEmpty(ipaddr)) + { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) + { + userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); + } + else + { + userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); + } + } + Collections.reverse(userOnlineList); + userOnlineList.removeAll(Collections.singleton(null)); + return getDataTable(userOnlineList); + } + + /** + * 强退用户 + */ + @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") + @Log(title = "在线用户", businessType = BusinessType.FORCE) + @DeleteMapping("/{tokenId}") + public AjaxResult forceLogout(@PathVariable String tokenId) + { + redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + return success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java new file mode 100644 index 0000000..95bcaec --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -0,0 +1,133 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 傿•°é…ç½® ä¿¡æ¯æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/config") +public class SysConfigController extends BaseController +{ + @Autowired + private ISysConfigService configService; + + /** + * 获å–傿•°é…置列表 + */ + @PreAuthorize("@ss.hasPermi('system:config:list')") + @GetMapping("/list") + public TableDataInfo list(SysConfig config) + { + startPage(); + List list = configService.selectConfigList(config); + return getDataTable(list); + } + + @Log(title = "傿•°ç®¡ç†", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:config:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysConfig config) + { + List list = configService.selectConfigList(config); + ExcelUtil util = new ExcelUtil(SysConfig.class); + util.exportExcel(response, list, "傿•°æ•°æ®"); + } + + /** + * æ ¹æ®å‚æ•°ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:config:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long configId) + { + return success(configService.selectConfigById(configId)); + } + + /** + * æ ¹æ®å‚æ•°é”®åæŸ¥è¯¢å‚数值 + */ + @GetMapping(value = "/configKey/{configKey}") + public AjaxResult getConfigKey(@PathVariable String configKey) + { + return success(configService.selectConfigByKey(configKey)); + } + + /** + * æ–°å¢žå‚æ•°é…ç½® + */ + @PreAuthorize("@ss.hasPermi('system:config:add')") + @Log(title = "傿•°ç®¡ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysConfig config) + { + if (!configService.checkConfigKeyUnique(config)) + { + return error("æ–°å¢žå‚æ•°'" + config.getConfigName() + "'å¤±è´¥ï¼Œå‚æ•°é”®å已存在"); + } + config.setCreateBy(getUsername()); + return toAjax(configService.insertConfig(config)); + } + + /** + * ä¿®æ”¹å‚æ•°é…ç½® + */ + @PreAuthorize("@ss.hasPermi('system:config:edit')") + @Log(title = "傿•°ç®¡ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysConfig config) + { + if (!configService.checkConfigKeyUnique(config)) + { + return error("ä¿®æ”¹å‚æ•°'" + config.getConfigName() + "'å¤±è´¥ï¼Œå‚æ•°é”®å已存在"); + } + config.setUpdateBy(getUsername()); + return toAjax(configService.updateConfig(config)); + } + + /** + * åˆ é™¤å‚æ•°é…ç½® + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "傿•°ç®¡ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{configIds}") + public AjaxResult remove(@PathVariable Long[] configIds) + { + configService.deleteConfigByIds(configIds); + return success(); + } + + /** + * åˆ·æ–°å‚æ•°ç¼“å­˜ + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "傿•°ç®¡ç†", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + configService.resetConfigCache(); + return success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java new file mode 100644 index 0000000..d2d750b --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -0,0 +1,142 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysDeptService; + +/** + * éƒ¨é—¨ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends BaseController +{ + @Autowired + private ISysDeptService deptService; + + /** + * 获å–部门列表 + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list") + public AjaxResult list(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return success(depts); + } + + /** + * 查询部门列表(排除节点) + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list/exclude/{deptId}") + public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) + { + List depts = deptService.selectDeptList(new SysDept()); + depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); + return success(depts); + } + + /** + * æ ¹æ®éƒ¨é—¨ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:dept:query')") + @GetMapping(value = "/{deptId}") + public AjaxResult getInfo(@PathVariable Long deptId) + { + deptService.checkDeptDataScope(deptId); + return success(deptService.selectDeptById(deptId)); + } + + /** + * 新增部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:add')") + @Log(title = "部门管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDept dept) + { + if (!deptService.checkDeptNameUnique(dept)) + { + return error("新增部门'" + dept.getDeptName() + "'失败,部门å称已存在"); + } + dept.setCreateBy(getUsername()); + return toAjax(deptService.insertDept(dept)); + } + + /** + * 修改部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:edit')") + @Log(title = "部门管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDept dept) + { + Long deptId = dept.getDeptId(); + deptService.checkDeptDataScope(deptId); + if (!deptService.checkDeptNameUnique(dept)) + { + return error("修改部门'" + dept.getDeptName() + "'失败,部门å称已存在"); + } + else if (dept.getParentId().equals(deptId)) + { + return error("修改部门'" + dept.getDeptName() + "'失败,上级部门ä¸èƒ½æ˜¯è‡ªå·±"); + } + else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) + { + return error("è¯¥éƒ¨é—¨åŒ…å«æœªåœç”¨çš„å­éƒ¨é—¨ï¼"); + } + dept.setUpdateBy(getUsername()); + return toAjax(deptService.updateDept(dept)); + } + + /** + * 获å–部门下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return AjaxResult.success(deptService.buildDeptTreeSelect(depts)); + } + + /** + * 删除部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:remove')") + @Log(title = "部门管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{deptId}") + public AjaxResult remove(@PathVariable Long deptId) + { + if (deptService.hasChildByDeptId(deptId)) + { + return warn("存在下级部门,ä¸å…许删除"); + } + if (deptService.checkDeptExistUser(deptId)) + { + return warn("部门存在用户,ä¸å…许删除"); + } + deptService.checkDeptDataScope(deptId); + return toAjax(deptService.deleteDeptById(deptId)); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java new file mode 100644 index 0000000..1914b99 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java @@ -0,0 +1,121 @@ +package com.ruoyi.web.controller.system; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDictDataService; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * æ•°æ®å­—å…¸ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dict/data") +public class SysDictDataController extends BaseController +{ + @Autowired + private ISysDictDataService dictDataService; + + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictData dictData) + { + startPage(); + List list = dictDataService.selectDictDataList(dictData); + return getDataTable(list); + } + + @Log(title = "字典数æ®", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictData dictData) + { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil util = new ExcelUtil(SysDictData.class); + util.exportExcel(response, list, "字典数æ®"); + } + + /** + * 查询字典数æ®è¯¦ç»† + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictCode}") + public AjaxResult getInfo(@PathVariable Long dictCode) + { + return success(dictDataService.selectDictDataById(dictCode)); + } + + /** + * æ ¹æ®å­—典类型查询字典数æ®ä¿¡æ¯ + */ + @GetMapping(value = "/type/{dictType}") + public AjaxResult dictType(@PathVariable String dictType) + { + List data = dictTypeService.selectDictDataByType(dictType); + if (StringUtils.isNull(data)) + { + data = new ArrayList(); + } + return success(data); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典数æ®", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictData dict) + { + dict.setCreateBy(getUsername()); + return toAjax(dictDataService.insertDictData(dict)); + } + + /** + * 修改ä¿å­˜å­—典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典数æ®", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictData dict) + { + dict.setUpdateBy(getUsername()); + return toAjax(dictDataService.updateDictData(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictCodes}") + public AjaxResult remove(@PathVariable Long[] dictCodes) + { + dictDataService.deleteDictDataByIds(dictCodes); + return success(); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java new file mode 100644 index 0000000..9808842 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java @@ -0,0 +1,131 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * æ•°æ®å­—å…¸ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dict/type") +public class SysDictTypeController extends BaseController +{ + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictType dictType) + { + startPage(); + List list = dictTypeService.selectDictTypeList(dictType); + return getDataTable(list); + } + + @Log(title = "字典类型", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictType dictType) + { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil util = new ExcelUtil(SysDictType.class); + util.exportExcel(response, list, "字典类型"); + } + + /** + * 查询字典类型详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictId}") + public AjaxResult getInfo(@PathVariable Long dictId) + { + return success(dictTypeService.selectDictTypeById(dictId)); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictType dict) + { + if (!dictTypeService.checkDictTypeUnique(dict)) + { + return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setCreateBy(getUsername()); + return toAjax(dictTypeService.insertDictType(dict)); + } + + /** + * 修改字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典类型", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictType dict) + { + if (!dictTypeService.checkDictTypeUnique(dict)) + { + return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setUpdateBy(getUsername()); + return toAjax(dictTypeService.updateDictType(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public AjaxResult remove(@PathVariable Long[] dictIds) + { + dictTypeService.deleteDictTypeByIds(dictIds); + return success(); + } + + /** + * 刷新字典缓存 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + dictTypeService.resetDictCache(); + return success(); + } + + /** + * 获å–字典选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List dictTypes = dictTypeService.selectDictTypeAll(); + return success(dictTypes); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java new file mode 100644 index 0000000..009219e --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java @@ -0,0 +1,29 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.StringUtils; + +/** + * 首页 + * + * @author ruoyi + */ +@RestController +public class SysIndexController +{ + /** 系统基础é…ç½® */ + @Autowired + private RuoYiConfig ruoyiConfig; + + /** + * 访问首页,æç¤ºè¯­ + */ + @RequestMapping("/") + public String index() + { + return StringUtils.format("欢迎使用{}åŽå°ç®¡ç†æ¡†æž¶ï¼Œå½“å‰ç‰ˆæœ¬ï¼šv{},请通过å‰ç«¯åœ°å€è®¿é—®ã€‚", ruoyiConfig.getName(), ruoyiConfig.getVersion()); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java new file mode 100644 index 0000000..f1c5268 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -0,0 +1,99 @@ +package com.ruoyi.web.controller.system; + +import java.io.UnsupportedEncodingException; +import java.util.Base64; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.web.service.SysLoginService; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.system.service.ISysMenuService; + +/** + * ç™»å½•éªŒè¯ + * + * @author ruoyi + */ +@RestController +public class SysLoginController +{ + @Autowired + private SysLoginService loginService; + + @Autowired + private ISysMenuService menuService; + + @Autowired + private SysPermissionService permissionService; + + /** + * 登录方法 + * + * @param loginBody ç™»å½•ä¿¡æ¯ + * @return 结果 + */ + @PostMapping("/login") + public AjaxResult login(@RequestBody LoginBody loginBody) + { + // System.out.println("loginBody:" + loginBody.toString()); + String username = null; + String password = null; + try { + username = new String(Base64.getDecoder().decode(loginBody.getUsername()), "UTF-8"); + password = new String(Base64.getDecoder().decode(loginBody.getPassword()), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + return AjaxResult.error("解密字符串出错:" + e.getMessage()); + } + + AjaxResult ajax = AjaxResult.success(); + // 生æˆä»¤ç‰Œ + String token = loginService.login(username, password, loginBody.getCode(), + loginBody.getUuid()); + ajax.put(Constants.TOKEN, token); + return ajax; + } + + /** + * 获å–ç”¨æˆ·ä¿¡æ¯ + * + * @return ç”¨æˆ·ä¿¡æ¯ + */ + @GetMapping("getInfo") + public AjaxResult getInfo() + { + SysUser user = SecurityUtils.getLoginUser().getUser(); + // è§’è‰²é›†åˆ + Set roles = permissionService.getRolePermission(user); + // æƒé™é›†åˆ + Set permissions = permissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + return ajax; + } + + /** + * 获å–è·¯ç”±ä¿¡æ¯ + * + * @return è·¯ç”±ä¿¡æ¯ + */ + @GetMapping("getRouters") + public AjaxResult getRouters() + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuTreeByUserId(userId); + return AjaxResult.success(menuService.buildMenus(menus)); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java new file mode 100644 index 0000000..eaaebd3 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java @@ -0,0 +1,142 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysMenuService; + +/** + * èœå•ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends BaseController +{ + @Autowired + private ISysMenuService menuService; + + /** + * 获å–èœå•列表 + */ + @PreAuthorize("@ss.hasPermi('system:menu:list')") + @GetMapping("/list") + public AjaxResult list(SysMenu menu) + { + List menus = menuService.selectMenuList(menu, getUserId()); + return success(menus); + } + + /** + * æ ¹æ®èœå•ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:menu:query')") + @GetMapping(value = "/{menuId}") + public AjaxResult getInfo(@PathVariable Long menuId) + { + return success(menuService.selectMenuById(menuId)); + } + + /** + * 获å–èœå•下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysMenu menu) + { + List menus = menuService.selectMenuList(menu, getUserId()); + return success(menuService.buildMenuTreeSelect(menus)); + } + + /** + * 加载对应角色èœå•列表树 + */ + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) + { + List menus = menuService.selectMenuList(getUserId()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); + ajax.put("menus", menuService.buildMenuTreeSelect(menus)); + return ajax; + } + + /** + * 新增èœå• + */ + @PreAuthorize("@ss.hasPermi('system:menu:add')") + @Log(title = "èœå•管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysMenu menu) + { + if (!menuService.checkMenuNameUnique(menu)) + { + return error("新增èœå•'" + menu.getMenuName() + "'失败,èœå•å称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("新增èœå•'" + menu.getMenuName() + "'失败,地å€å¿…须以http(s)://开头"); + } + menu.setCreateBy(getUsername()); + return toAjax(menuService.insertMenu(menu)); + } + + /** + * 修改èœå• + */ + @PreAuthorize("@ss.hasPermi('system:menu:edit')") + @Log(title = "èœå•管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysMenu menu) + { + if (!menuService.checkMenuNameUnique(menu)) + { + return error("修改èœå•'" + menu.getMenuName() + "'失败,èœå•å称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("修改èœå•'" + menu.getMenuName() + "'失败,地å€å¿…须以http(s)://开头"); + } + else if (menu.getMenuId().equals(menu.getParentId())) + { + return error("修改èœå•'" + menu.getMenuName() + "'失败,上级èœå•ä¸èƒ½é€‰æ‹©è‡ªå·±"); + } + menu.setUpdateBy(getUsername()); + return toAjax(menuService.updateMenu(menu)); + } + + /** + * 删除èœå• + */ + @PreAuthorize("@ss.hasPermi('system:menu:remove')") + @Log(title = "èœå•管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{menuId}") + public AjaxResult remove(@PathVariable("menuId") Long menuId) + { + if (menuService.hasChildByMenuId(menuId)) + { + return warn("存在å­èœå•,ä¸å…许删除"); + } + if (menuService.checkMenuExistRole(menuId)) + { + return warn("èœå•已分é…,ä¸å…许删除"); + } + return toAjax(menuService.deleteMenuById(menuId)); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java new file mode 100644 index 0000000..36c62b9 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java @@ -0,0 +1,91 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.service.ISysNoticeService; + +/** + * 公告 ä¿¡æ¯æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends BaseController +{ + @Autowired + private ISysNoticeService noticeService; + + /** + * 获å–通知公告列表 + */ + @PreAuthorize("@ss.hasPermi('system:notice:list')") + @GetMapping("/list") + public TableDataInfo list(SysNotice notice) + { + startPage(); + List list = noticeService.selectNoticeList(notice); + return getDataTable(list); + } + + /** + * æ ¹æ®é€šçŸ¥å…¬å‘Šç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:notice:query')") + @GetMapping(value = "/{noticeId}") + public AjaxResult getInfo(@PathVariable Long noticeId) + { + return success(noticeService.selectNoticeById(noticeId)); + } + + /** + * 新增通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:add')") + @Log(title = "通知公告", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysNotice notice) + { + notice.setCreateBy(getUsername()); + return toAjax(noticeService.insertNotice(notice)); + } + + /** + * 修改通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:edit')") + @Log(title = "通知公告", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysNotice notice) + { + notice.setUpdateBy(getUsername()); + return toAjax(noticeService.updateNotice(notice)); + } + + /** + * 删除通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:remove')") + @Log(title = "通知公告", businessType = BusinessType.DELETE) + @DeleteMapping("/{noticeIds}") + public AjaxResult remove(@PathVariable Long[] noticeIds) + { + return toAjax(noticeService.deleteNoticeByIds(noticeIds)); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java new file mode 100644 index 0000000..a5b96c8 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java @@ -0,0 +1,129 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.service.ISysPostService; + +/** + * å²—ä½ä¿¡æ¯æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/post") +public class SysPostController extends BaseController +{ + @Autowired + private ISysPostService postService; + + /** + * 获å–å²—ä½åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('system:post:list')") + @GetMapping("/list") + public TableDataInfo list(SysPost post) + { + startPage(); + List list = postService.selectPostList(post); + return getDataTable(list); + } + + @Log(title = "å²—ä½ç®¡ç†", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:post:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysPost post) + { + List list = postService.selectPostList(post); + ExcelUtil util = new ExcelUtil(SysPost.class); + util.exportExcel(response, list, "岗使•°æ®"); + } + + /** + * æ ¹æ®å²—ä½ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:post:query')") + @GetMapping(value = "/{postId}") + public AjaxResult getInfo(@PathVariable Long postId) + { + return success(postService.selectPostById(postId)); + } + + /** + * æ–°å¢žå²—ä½ + */ + @PreAuthorize("@ss.hasPermi('system:post:add')") + @Log(title = "å²—ä½ç®¡ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysPost post) + { + if (!postService.checkPostNameUnique(post)) + { + return error("新增岗ä½'" + post.getPostName() + "'失败,岗ä½å称已存在"); + } + else if (!postService.checkPostCodeUnique(post)) + { + return error("新增岗ä½'" + post.getPostName() + "'失败,岗ä½ç¼–ç å·²å­˜åœ¨"); + } + post.setCreateBy(getUsername()); + return toAjax(postService.insertPost(post)); + } + + /** + * ä¿®æ”¹å²—ä½ + */ + @PreAuthorize("@ss.hasPermi('system:post:edit')") + @Log(title = "å²—ä½ç®¡ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysPost post) + { + if (!postService.checkPostNameUnique(post)) + { + return error("修改岗ä½'" + post.getPostName() + "'失败,岗ä½å称已存在"); + } + else if (!postService.checkPostCodeUnique(post)) + { + return error("修改岗ä½'" + post.getPostName() + "'失败,岗ä½ç¼–ç å·²å­˜åœ¨"); + } + post.setUpdateBy(getUsername()); + return toAjax(postService.updatePost(post)); + } + + /** + * åˆ é™¤å²—ä½ + */ + @PreAuthorize("@ss.hasPermi('system:post:remove')") + @Log(title = "å²—ä½ç®¡ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{postIds}") + public AjaxResult remove(@PathVariable Long[] postIds) + { + return toAjax(postService.deletePostByIds(postIds)); + } + + /** + * 获å–å²—ä½é€‰æ‹©æ¡†åˆ—表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List posts = postService.selectPostAll(); + return success(posts); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java new file mode 100644 index 0000000..0ffb7e8 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.MimeTypeUtils; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysUserService; + +/** + * ä¸ªäººä¿¡æ¯ ä¸šåŠ¡å¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/user/profile") +public class SysProfileController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private TokenService tokenService; + + /** + * ä¸ªäººä¿¡æ¯ + */ + @GetMapping + public AjaxResult profile() + { + LoginUser loginUser = getLoginUser(); + SysUser user = loginUser.getUser(); + AjaxResult ajax = AjaxResult.success(user); + ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername())); + ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); + return ajax; + } + + /** + * 修改用户 + */ + @Log(title = "个人信æ¯", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult updateProfile(@RequestBody SysUser user) + { + LoginUser loginUser = getLoginUser(); + SysUser sysUser = loginUser.getUser(); + user.setUserName(sysUser.getUserName()); + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,手机å·ç å·²å­˜åœ¨"); + } + if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账å·å·²å­˜åœ¨"); + } + user.setUserId(sysUser.getUserId()); + user.setPassword(null); + user.setAvatar(null); + user.setDeptId(null); + if (userService.updateUserProfile(user) > 0) + { + // æ›´æ–°ç¼“å­˜ç”¨æˆ·ä¿¡æ¯ + sysUser.setNickName(user.getNickName()); + sysUser.setPhonenumber(user.getPhonenumber()); + sysUser.setEmail(user.getEmail()); + sysUser.setSex(user.getSex()); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改个人信æ¯å¼‚常,请è”系管ç†å‘˜"); + } + + /** + * é‡ç½®å¯†ç  + */ + @Log(title = "个人信æ¯", businessType = BusinessType.UPDATE) + @PutMapping("/updatePwd") + public AjaxResult updatePwd(String oldPassword, String newPassword) + { + LoginUser loginUser = getLoginUser(); + String userName = loginUser.getUsername(); + String password = loginUser.getPassword(); + if (!SecurityUtils.matchesPassword(oldPassword, password)) + { + return error("修改密ç å¤±è´¥ï¼Œæ—§å¯†ç é”™è¯¯"); + } + if (SecurityUtils.matchesPassword(newPassword, password)) + { + return error("新密ç ä¸èƒ½ä¸Žæ—§å¯†ç ç›¸åŒ"); + } + if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) + { + // æ›´æ–°ç¼“å­˜ç”¨æˆ·å¯†ç  + loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改密ç å¼‚常,请è”系管ç†å‘˜"); + } + + /** + * 头åƒä¸Šä¼  + */ + @Log(title = "用户头åƒ", businessType = BusinessType.UPDATE) + @PostMapping("/avatar") + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception + { + if (!file.isEmpty()) + { + LoginUser loginUser = getLoginUser(); + String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION); + if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("imgUrl", avatar); + // æ›´æ–°ç¼“å­˜ç”¨æˆ·å¤´åƒ + loginUser.getUser().setAvatar(avatar); + tokenService.setLoginUser(loginUser); + return ajax; + } + } + return error("上传图片异常,请è”系管ç†å‘˜"); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java new file mode 100644 index 0000000..f1552e0 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java @@ -0,0 +1,38 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.RegisterBody; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.SysRegisterService; +import com.ruoyi.system.service.ISysConfigService; + +/** + * æ³¨å†ŒéªŒè¯ + * + * @author ruoyi + */ +@RestController +public class SysRegisterController extends BaseController +{ + @Autowired + private SysRegisterService registerService; + + @Autowired + private ISysConfigService configService; + + @PostMapping("/register") + public AjaxResult register(@RequestBody RegisterBody user) + { + if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) + { + return error("当å‰ç³»ç»Ÿæ²¡æœ‰å¼€å¯æ³¨å†ŒåŠŸèƒ½ï¼"); + } + String msg = registerService.register(user); + return StringUtils.isEmpty(msg) ? success() : error(msg); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java new file mode 100644 index 0000000..ebe7460 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -0,0 +1,262 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.service.ISysDeptService; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; + +/** + * è§’è‰²ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends BaseController +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private TokenService tokenService; + + @Autowired + private SysPermissionService permissionService; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysDeptService deptService; + + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/list") + public TableDataInfo list(SysRole role) + { + startPage(); + List list = roleService.selectRoleList(role); + return getDataTable(list); + } + + @Log(title = "角色管ç†", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:role:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysRole role) + { + List list = roleService.selectRoleList(role); + ExcelUtil util = new ExcelUtil(SysRole.class); + util.exportExcel(response, list, "角色数æ®"); + } + + /** + * æ ¹æ®è§’色编å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/{roleId}") + public AjaxResult getInfo(@PathVariable Long roleId) + { + roleService.checkRoleDataScope(roleId); + return success(roleService.selectRoleById(roleId)); + } + + /** + * 新增角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:add')") + @Log(title = "角色管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysRole role) + { + if (!roleService.checkRoleNameUnique(role)) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色å称已存在"); + } + else if (!roleService.checkRoleKeyUnique(role)) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色æƒé™å·²å­˜åœ¨"); + } + role.setCreateBy(getUsername()); + return toAjax(roleService.insertRole(role)); + + } + + /** + * 修改ä¿å­˜è§’色 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + if (!roleService.checkRoleNameUnique(role)) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色å称已存在"); + } + else if (!roleService.checkRoleKeyUnique(role)) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色æƒé™å·²å­˜åœ¨"); + } + role.setUpdateBy(getUsername()); + + if (roleService.updateRole(role) > 0) + { + // 更新缓存用户æƒé™ + LoginUser loginUser = getLoginUser(); + if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) + { + loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); + loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName())); + tokenService.setLoginUser(loginUser); + } + return success(); + } + return error("修改角色'" + role.getRoleName() + "'失败,请è”系管ç†å‘˜"); + } + + /** + * 修改ä¿å­˜æ•°æ®æƒé™ + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.UPDATE) + @PutMapping("/dataScope") + public AjaxResult dataScope(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + return toAjax(roleService.authDataScope(role)); + } + + /** + * 状æ€ä¿®æ”¹ + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + role.setUpdateBy(getUsername()); + return toAjax(roleService.updateRoleStatus(role)); + } + + /** + * 删除角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:remove')") + @Log(title = "角色管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{roleIds}") + public AjaxResult remove(@PathVariable Long[] roleIds) + { + return toAjax(roleService.deleteRoleByIds(roleIds)); + } + + /** + * 获å–角色选择框列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + return success(roleService.selectRoleAll()); + } + + /** + * 查询已分é…用户角色列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/authUser/allocatedList") + public TableDataInfo allocatedList(SysUser user) + { + startPage(); + List list = userService.selectAllocatedList(user); + return getDataTable(list); + } + + /** + * 查询未分é…用户角色列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/authUser/unallocatedList") + public TableDataInfo unallocatedList(SysUser user) + { + startPage(); + List list = userService.selectUnallocatedList(user); + return getDataTable(list); + } + + /** + * å–æ¶ˆæŽˆæƒç”¨æˆ· + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancel") + public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) + { + return toAjax(roleService.deleteAuthUser(userRole)); + } + + /** + * 批é‡å–消授æƒç”¨æˆ· + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancelAll") + public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) + { + return toAjax(roleService.deleteAuthUsers(roleId, userIds)); + } + + /** + * 批é‡é€‰æ‹©ç”¨æˆ·æŽˆæƒ + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管ç†", businessType = BusinessType.GRANT) + @PutMapping("/authUser/selectAll") + public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) + { + roleService.checkRoleDataScope(roleId); + return toAjax(roleService.insertAuthUsers(roleId, userIds)); + } + + /** + * 获å–对应角色部门树列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/deptTree/{roleId}") + public AjaxResult deptTree(@PathVariable("roleId") Long roleId) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); + return ajax; + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java new file mode 100644 index 0000000..dc29d49 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -0,0 +1,251 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDeptService; +import com.ruoyi.system.service.ISysPostService; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; + +/** + * ç”¨æˆ·ä¿¡æ¯ + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/user") +public class SysUserController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysDeptService deptService; + + @Autowired + private ISysPostService postService; + + /** + * 获å–用户列表 + */ + @PreAuthorize("@ss.hasPermi('system:user:list')") + @GetMapping("/list") + public TableDataInfo list(SysUser user) + { + startPage(); + List list = userService.selectUserList(user); + return getDataTable(list); + } + + @Log(title = "用户管ç†", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:user:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysUser user) + { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + util.exportExcel(response, list, "用户数æ®"); + } + + @Log(title = "用户管ç†", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('system:user:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception + { + ExcelUtil util = new ExcelUtil(SysUser.class); + List userList = util.importExcel(file.getInputStream()); + String operName = getUsername(); + String message = userService.importUser(userList, updateSupport, operName); + return success(message); + } + + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) + { + ExcelUtil util = new ExcelUtil(SysUser.class); + util.importTemplateExcel(response, "用户数æ®"); + } + + /** + * æ ¹æ®ç”¨æˆ·ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping(value = { "/", "/{userId}" }) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) + { + userService.checkUserDataScope(userId); + AjaxResult ajax = AjaxResult.success(); + List roles = roleService.selectRoleAll(); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("posts", postService.selectPostAll()); + if (StringUtils.isNotNull(userId)) + { + SysUser sysUser = userService.selectUserById(userId); + ajax.put(AjaxResult.DATA_TAG, sysUser); + ajax.put("postIds", postService.selectPostListByUserId(userId)); + ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); + } + return ajax; + } + + /** + * 新增用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:add')") + @Log(title = "用户管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysUser user) + { + if (!userService.checkUserNameUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,登录账å·å·²å­˜åœ¨"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,手机å·ç å·²å­˜åœ¨"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,邮箱账å·å·²å­˜åœ¨"); + } + user.setCreateBy(getUsername()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + return toAjax(userService.insertUser(user)); + } + + /** + * 修改用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + if (!userService.checkUserNameUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,登录账å·å·²å­˜åœ¨"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,手机å·ç å·²å­˜åœ¨"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账å·å·²å­˜åœ¨"); + } + user.setUpdateBy(getUsername()); + return toAjax(userService.updateUser(user)); + } + + /** + * 删除用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:remove')") + @Log(title = "用户管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + if (ArrayUtils.contains(userIds, getUserId())) + { + return error("当å‰ç”¨æˆ·ä¸èƒ½åˆ é™¤"); + } + return toAjax(userService.deleteUserByIds(userIds)); + } + + /** + * é‡ç½®å¯†ç  + */ + @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") + @Log(title = "用户管ç†", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public AjaxResult resetPwd(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(getUsername()); + return toAjax(userService.resetPwd(user)); + } + + /** + * 状æ€ä¿®æ”¹ + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管ç†", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setUpdateBy(getUsername()); + return toAjax(userService.updateUserStatus(user)); + } + + /** + * æ ¹æ®ç”¨æˆ·ç¼–å·èŽ·å–æŽˆæƒè§’色 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping("/authRole/{userId}") + public AjaxResult authRole(@PathVariable("userId") Long userId) + { + AjaxResult ajax = AjaxResult.success(); + SysUser user = userService.selectUserById(userId); + List roles = roleService.selectRolesByUserId(userId); + ajax.put("user", user); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + return ajax; + } + + /** + * 用户授æƒè§’色 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管ç†", businessType = BusinessType.GRANT) + @PutMapping("/authRole") + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) + { + userService.checkUserDataScope(userId); + userService.insertUserAuth(userId, roleIds); + return success(); + } + + /** + * 获å–部门树列表 + */ + @PreAuthorize("@ss.hasPermi('system:user:list')") + @GetMapping("/deptTree") + public AjaxResult deptTree(SysDept dept) + { + return success(deptService.selectDeptTreeList(dept)); + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java new file mode 100644 index 0000000..c55f974 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java @@ -0,0 +1,183 @@ +package com.ruoyi.web.controller.tool; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; + +/** + * swagger 用户测试方法 + * + * @author ruoyi + */ +@Api("用户信æ¯ç®¡ç†") +@RestController +@RequestMapping("/test/user") +public class TestController extends BaseController +{ + private final static Map users = new LinkedHashMap(); + { + users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); + users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); + } + + @ApiOperation("获å–用户列表") + @GetMapping("/list") + public R> userList() + { + List userList = new ArrayList(users.values()); + return R.ok(userList); + } + + @ApiOperation("获å–用户详细") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) + @GetMapping("/{userId}") + public R getUser(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + return R.ok(users.get(userId)); + } + else + { + return R.fail("用户ä¸å­˜åœ¨"); + } + } + + @ApiOperation("新增用户") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class), + @ApiImplicitParam(name = "username", value = "用户åç§°", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "password", value = "用户密ç ", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class) + }) + @PostMapping("/save") + public R save(UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return R.fail("用户IDä¸èƒ½ä¸ºç©º"); + } + users.put(user.getUserId(), user); + return R.ok(); + } + + @ApiOperation("更新用户") + @PutMapping("/update") + public R update(@RequestBody UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return R.fail("用户IDä¸èƒ½ä¸ºç©º"); + } + if (users.isEmpty() || !users.containsKey(user.getUserId())) + { + return R.fail("用户ä¸å­˜åœ¨"); + } + users.remove(user.getUserId()); + users.put(user.getUserId(), user); + return R.ok(); + } + + @ApiOperation("删除用户信æ¯") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) + @DeleteMapping("/{userId}") + public R delete(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + users.remove(userId); + return R.ok(); + } + else + { + return R.fail("用户ä¸å­˜åœ¨"); + } + } +} + +@ApiModel(value = "UserEntity", description = "用户实体") +class UserEntity +{ + @ApiModelProperty("用户ID") + private Integer userId; + + @ApiModelProperty("用户åç§°") + private String username; + + @ApiModelProperty("用户密ç ") + private String password; + + @ApiModelProperty("用户手机") + private String mobile; + + public UserEntity() + { + + } + + public UserEntity(Integer userId, String username, String password, String mobile) + { + this.userId = userId; + this.username = username; + this.password = password; + this.mobile = mobile; + } + + public Integer getUserId() + { + return userId; + } + + public void setUserId(Integer userId) + { + this.userId = userId; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getMobile() + { + return mobile; + } + + public void setMobile(String mobile) + { + this.mobile = mobile; + } +} diff --git a/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java new file mode 100644 index 0000000..0b94245 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java @@ -0,0 +1,125 @@ +package com.ruoyi.web.core.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.ruoyi.common.config.RuoYiConfig; +import io.swagger.annotations.ApiOperation; +import io.swagger.models.auth.In; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.Contact; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.service.SecurityScheme; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +/** + * Swagger2的接å£é…ç½® + * + * @author ruoyi + */ +@Configuration +public class SwaggerConfig +{ + /** 系统基础é…ç½® */ + @Autowired + private RuoYiConfig ruoyiConfig; + + /** 是å¦å¼€å¯swagger */ + @Value("${swagger.enabled}") + private boolean enabled; + + /** 设置请求的统一å‰ç¼€ */ + @Value("${swagger.pathMapping}") + private String pathMapping; + + /** + * 创建API + */ + @Bean + public Docket createRestApi() + { + return new Docket(DocumentationType.OAS_30) + // 是å¦å¯ç”¨Swagger + .enable(enabled) + // 用æ¥åˆ›å»ºè¯¥API的基本信æ¯ï¼Œå±•示在文档的页é¢ä¸­ï¼ˆè‡ªå®šä¹‰å±•示的信æ¯ï¼‰ + .apiInfo(apiInfo()) + // è®¾ç½®å“ªäº›æŽ¥å£æš´éœ²ç»™Swagger展示 + .select() + // æ‰«ææ‰€æœ‰æœ‰æ³¨è§£çš„apiï¼Œç”¨è¿™ç§æ–¹å¼æ›´çµæ´» + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + // æ‰«ææŒ‡å®šåŒ…中的swagger注解 + // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) + // æ‰«ææ‰€æœ‰ .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + /* 设置安全模å¼ï¼Œswaggerå¯ä»¥è®¾ç½®è®¿é—®token */ + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()) + .pathMapping(pathMapping); + } + + /** + * 安全模å¼ï¼Œè¿™é‡ŒæŒ‡å®štoken通过Authorization头请求头传递 + */ + private List securitySchemes() + { + List apiKeyList = new ArrayList(); + apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue())); + return apiKeyList; + } + + /** + * 安全上下文 + */ + private List securityContexts() + { + List securityContexts = new ArrayList<>(); + securityContexts.add( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .operationSelector(o -> o.requestMappingPattern().matches("/.*")) + .build()); + return securityContexts; + } + + /** + * 默认的安全上引用 + */ + private List defaultAuth() + { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + List securityReferences = new ArrayList<>(); + securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); + return securityReferences; + } + + /** + * 添加摘è¦ä¿¡æ¯ + */ + private ApiInfo apiInfo() + { + // 用ApiInfoBuilder进行定制 + return new ApiInfoBuilder() + // 设置标题 + .title("标题:若ä¾ç®¡ç†ç³»ç»Ÿ_æŽ¥å£æ–‡æ¡£") + // æè¿° + .description("æè¿°ï¼šç”¨äºŽç®¡ç†é›†å›¢æ——下公å¸çš„人员信æ¯,具体包括XXX,XXX模å—...") + // ä½œè€…ä¿¡æ¯ + .contact(new Contact(ruoyiConfig.getName(), null, null)) + // 版本 + .version("版本å·:" + ruoyiConfig.getVersion()) + .build(); + } +} diff --git a/examapi/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties b/examapi/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000..2b23f85 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties @@ -0,0 +1 @@ +restart.include.json=/com.alibaba.fastjson.*.jar \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/resources/application-druid.yml b/examapi/ruoyi-admin/src/main/resources/application-druid.yml new file mode 100644 index 0000000..455e9fa --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/application-druid.yml @@ -0,0 +1,63 @@ +# æ•°æ®æºé…ç½® +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # ä¸»åº“æ•°æ®æº + master: + #url: jdbc:mysql://62.234.3.186:3306/yanzhu_exam?useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8 + url: jdbc:mysql://127.0.0.1:3306/yanzhu_exam?useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8 + username: root + #password: Sxyanzhu@cf123 + password: haha123321 + # ä»Žåº“æ•°æ®æº + slave: + # ä»Žæ•°æ®æºå¼€å…³/默认关闭 + enabled: false + url: + username: + password: + # åˆå§‹è¿žæŽ¥æ•° + initialSize: 5 + # 最å°è¿žæŽ¥æ± æ•°é‡ + minIdle: 10 + # æœ€å¤§è¿žæŽ¥æ± æ•°é‡ + maxActive: 20 + # é…置获å–连接等待超时的时间 + maxWait: 60000 + # é…置连接超时时间 + connectTimeout: 30000 + # é…置网络超时时间 + socketTimeout: 60000 + # é…置间隔多久æ‰è¿›è¡Œä¸€æ¬¡æ£€æµ‹ï¼Œæ£€æµ‹éœ€è¦å…³é—­çš„空闲连接,å•使˜¯æ¯«ç§’ + timeBetweenEvictionRunsMillis: 60000 + # é…置一个连接在池中最å°ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•使˜¯æ¯«ç§’ + minEvictableIdleTimeMillis: 300000 + # é…置一个连接在池中最大生存的时间,å•使˜¯æ¯«ç§’ + maxEvictableIdleTimeMillis: 900000 + # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白åå•,ä¸å¡«åˆ™å…许所有访问 + allow: + url-pattern: /druid/* + # 控制å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç  + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # æ…¢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/resources/application.yml b/examapi/ruoyi-admin/src/main/resources/application.yml new file mode 100644 index 0000000..3253ade --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/application.yml @@ -0,0 +1,158 @@ +# 项目相关é…ç½® +ruoyi: + # åç§° + name: Yanzhu + # 版本 + version: 3.8.6 + # 版æƒå¹´ä»½ + copyrightYear: 2023 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windowsé…ç½®D:/ruoyi/uploadPath,Linuxé…ç½® /home/ruoyi/uploadPath) + profile: /Users/mac/data/uploadPath/exam + # 获å–ip地å€å¼€å…³ + addressEnabled: false + # 验è¯ç ç±»åž‹ math 数字计算 char å­—ç¬¦éªŒè¯ + captchaType: math + +# å¼€å‘环境é…ç½® +server: + # æœåŠ¡å™¨çš„HTTP端å£ï¼Œé»˜è®¤ä¸º8080 + port: 8040 + servlet: + # 应用的访问路径 + context-path: /examapi + tomcat: + # tomcatçš„URIç¼–ç  + uri-encoding: UTF-8 + # 连接数满åŽçš„æŽ’队数,默认为100 + accept-count: 1000 + threads: + # tomcat最大线程数,默认为200 + max: 800 + # Tomcatå¯åЍåˆå§‹åŒ–的线程数,默认值10 + min-spare: 100 + +# 日志é…ç½® +logging: + level: + com.ruoyi: debug + org.springframework: warn + +# 用户é…ç½® +user: + password: + # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•° + maxRetryCount: 5 + # 密ç é”定时间(默认10分钟) + lockTime: 10 + +# Springé…ç½® +spring: + # 资æºä¿¡æ¯ + messages: + # å›½é™…åŒ–èµ„æºæ–‡ä»¶è·¯å¾„ + basename: i18n/messages + profiles: + active: druid + # 文件上传 + servlet: + multipart: + # å•ä¸ªæ–‡ä»¶å¤§å° + max-file-size: 10MB + # è®¾ç½®æ€»ä¸Šä¼ çš„æ–‡ä»¶å¤§å° + max-request-size: 20MB + # æœåŠ¡æ¨¡å— + devtools: + restart: + # 热部署开关 + enabled: true + # redis é…ç½® + redis: + # åœ°å€ + host: localhost + # 端å£ï¼Œé»˜è®¤ä¸º6379 + port: 6379 + # æ•°æ®åº“索引 + database: 0 + # å¯†ç  + password: 123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最å°ç©ºé—²è¿žæŽ¥ + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数æ®åº“连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有é™åˆ¶ï¼‰ + max-wait: -1ms + +# tokené…ç½® +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 30 + +# MyBatisé…ç½® +mybatis: + # æœç´¢æŒ‡å®šåŒ…别å + typeAliasesPackage: com.ruoyi.**.domain,com.yanzhu.exam.**.domain + # é…ç½®mapper的扫æï¼Œæ‰¾åˆ°æ‰€æœ‰çš„mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的é…置文件 + configLocation: classpath:mybatis/mybatis-config.xml + +# PageHelper分页æ’ä»¶ +pagehelper: + helperDialect: mysql + supportMethodsArguments: true + params: count=countSql + +# Swaggeré…ç½® +swagger: + # 是å¦å¼€å¯swagger + enabled: true + # 请求å‰ç¼€ + pathMapping: /news-api + +# 防止XSS攻击 +xss: + # 过滤开关 + enabled: true + # 排除链接(多个用逗å·åˆ†éš”) + excludes: /system/notice + # 匹é…链接 + urlPatterns: /system/*,/monitor/*,/tool/* + +http: + maxTotal: 300 + defaultMaxPerRoute: 100 + connectTimeout: 30000 + connectionRequestTimeout: 30000 + socketTimeout: 30000 + staleConnectionCheckEnabled: true +# 内容管ç†ç›¸å…³ +cms: + swipper: + photo-path: /photo/swipper + # 内容管ç†ç›¸å…³ + news: + photo-path: /photo/news + exam: + photo-path: /photo/exam + # 文件管ç†ç›¸å…³ + fms: + photo-path: /photo/fms + # 文件管ç†ç›¸å…³ + files: + photo-path: /photo/files + # æµç¨‹é™„件相关 + workflow: + file-path: /photo/ueditor + diff --git a/examapi/ruoyi-admin/src/main/resources/banner.txt b/examapi/ruoyi-admin/src/main/resources/banner.txt new file mode 100644 index 0000000..9466259 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/banner.txt @@ -0,0 +1,24 @@ +Application Version: ${ruoyi.version} +Spring Boot Version: ${spring-boot.version} +//////////////////////////////////////////////////////////////////// +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖ä¿ä½‘ æ°¸ä¸å®•机 永无BUG // +//////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/resources/i18n/messages.properties b/examapi/ruoyi-admin/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..c3956b2 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -0,0 +1,38 @@ +#é”™è¯¯æ¶ˆæ¯ +not.null=* 必须填写 +user.jcaptcha.error=验è¯ç é”™è¯¯ +user.jcaptcha.expire=验è¯ç å·²å¤±æ•ˆ +user.not.exists=用户ä¸å­˜åœ¨/密ç é”™è¯¯ +user.password.not.match=用户ä¸å­˜åœ¨/密ç é”™è¯¯ +user.password.retry.limit.count=密ç è¾“入错误{0}次 +user.password.retry.limit.exceed=密ç è¾“入错误{0}æ¬¡ï¼Œå¸æˆ·é”定{1}分钟 +user.password.delete=对ä¸èµ·ï¼Œæ‚¨çš„è´¦å·å·²è¢«åˆ é™¤ +user.blocked=用户已å°ç¦ï¼Œè¯·è”系管ç†å‘˜ +role.blocked=角色已å°ç¦ï¼Œè¯·è”系管ç†å‘˜ +login.blocked=å¾ˆé—æ†¾ï¼Œè®¿é—®IP已被列入系统黑åå• +user.logout.success=退出æˆåŠŸ + +length.not.valid=长度必须在{min}到{max}个字符之间 + +user.username.not.valid=* 2到20个汉字ã€å­—æ¯ã€æ•°å­—或下划线组æˆï¼Œä¸”å¿…é¡»ä»¥éžæ•°å­—开头 +user.password.not.valid=* 5-50个字符 + +user.email.not.valid=邮箱格å¼é”™è¯¯ +user.mobile.phone.number.not.valid=æ‰‹æœºå·æ ¼å¼é”™è¯¯ +user.login.success=登录æˆåŠŸ +user.register.success=注册æˆåŠŸ +user.notfound=è¯·é‡æ–°ç™»å½• +user.forcelogout=管ç†å‘˜å¼ºåˆ¶é€€å‡ºï¼Œè¯·é‡æ–°ç™»å½• +user.unknown.error=æœªçŸ¥é”™è¯¯ï¼Œè¯·é‡æ–°ç™»å½• + +##æ–‡ä»¶ä¸Šä¼ æ¶ˆæ¯ +upload.exceed.maxSize=上传的文件大å°è¶…出é™åˆ¶çš„æ–‡ä»¶å¤§å°ï¼
å…è®¸çš„æ–‡ä»¶æœ€å¤§å¤§å°æ˜¯ï¼š{0}MBï¼ +upload.filename.exceed.length=ä¸Šä¼ çš„æ–‡ä»¶åæœ€é•¿{0}个字符 + +##æƒé™ +no.permission=您没有数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] +no.create.permission=您没有创建数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] +no.update.permission=您没有修改数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] +no.delete.permission=您没有删除数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] +no.export.permission=您没有导出数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] +no.view.permission=您没有查看数æ®çš„æƒé™ï¼Œè¯·è”系管ç†å‘˜æ·»åŠ æƒé™ [{0}] diff --git a/examapi/ruoyi-admin/src/main/resources/logback.xml b/examapi/ruoyi-admin/src/main/resources/logback.xml new file mode 100644 index 0000000..54a1f2e --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/logback.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/sys-info.log + + + + ${log.path}/sys-info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/sys-error.log + + + + ${log.path}/sys-error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + ${log.path}/sys-user.log + + + ${log.path}/sys-user.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/examapi/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..4b8c496 --- /dev/null +++ b/examapi/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/examapi/ruoyi-common/pom.xml b/examapi/ruoyi-common/pom.xml new file mode 100644 index 0000000..9062b4e --- /dev/null +++ b/examapi/ruoyi-common/pom.xml @@ -0,0 +1,150 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-common + + + common通用工具 + + + + + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.apache.commons + commons-lang3 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + 3.5.2 + + + + + com.alibaba.fastjson2 + fastjson2 + + + + + commons-io + commons-io + + + + + org.apache.poi + poi-ooxml + + + + + org.yaml + snakeyaml + + + + + io.jsonwebtoken + jjwt + + + + + javax.xml.bind + jaxb-api + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + + eu.bitwalker + UserAgentUtils + + + + + javax.servlet + javax.servlet-api + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + -Xlint:deprecation + -Xlint:unchecked + + + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java new file mode 100644 index 0000000..8b6966e --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 匿å访问ä¸é‰´æƒæ³¨è§£ + * + * @author ruoyi + */ +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Anonymous +{ +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java new file mode 100644 index 0000000..cebe592 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * æ•°æ®æƒé™è¿‡æ»¤æ³¨è§£ + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope +{ + /** + * 部门表的别å + */ + public String deptAlias() default ""; + + /** + * 用户表的别å + */ + public String userAlias() default ""; + + /** + * æƒé™å­—符(用于多个角色匹é…符åˆè¦æ±‚çš„æƒé™ï¼‰é»˜è®¤æ ¹æ®æƒé™æ³¨è§£@ss获å–,多个æƒé™ç”¨é€—å·åˆ†éš”å¼€æ¥ + */ + public String permission() default ""; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java new file mode 100644 index 0000000..6b41ee7 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java @@ -0,0 +1,28 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.enums.DataSourceType; + +/** + * è‡ªå®šä¹‰å¤šæ•°æ®æºåˆ‡æ¢æ³¨è§£ + * + * 优先级:先方法,åŽç±»ï¼Œå¦‚æžœæ–¹æ³•è¦†ç›–äº†ç±»ä¸Šçš„æ•°æ®æºç±»åž‹ï¼Œä»¥æ–¹æ³•的为准,å¦åˆ™ä»¥ç±»ä¸Šçš„为准 + * + * @author ruoyi + */ +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface DataSource +{ + /** + * åˆ‡æ¢æ•°æ®æºåç§° + */ + public DataSourceType value() default DataSourceType.MASTER; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java new file mode 100644 index 0000000..ed7d445 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -0,0 +1,188 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.math.BigDecimal; +import java.math.RoundingMode; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import com.ruoyi.common.utils.poi.ExcelHandlerAdapter; + +/** + * 自定义导出Excelæ•°æ®æ³¨è§£ + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Excel +{ + /** + * 导出时在excelä¸­æŽ’åº + */ + public int sort() default Integer.MAX_VALUE; + + /** + * 导出到Excel中的åå­—. + */ + public String name() default ""; + + /** + * 日期格å¼, 如: yyyy-MM-dd + */ + public String dateFormat() default ""; + + /** + * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) + */ + public String dictType() default ""; + + /** + * 读å–å†…å®¹è½¬è¡¨è¾¾å¼ (如: 0=ç”·,1=女,2=未知) + */ + public String readConverterExp() default ""; + + /** + * 分隔符,读å–字符串组内容 + */ + public String separator() default ","; + + /** + * BigDecimal 精度 默认:-1(默认ä¸å¼€å¯BigDecimalæ ¼å¼åŒ–) + */ + public int scale() default -1; + + /** + * BigDecimal èˆå…¥è§„则 默认:RoundingMode.HALF_EVEN + */ + public RoundingMode roundingMode() default RoundingMode.HALF_EVEN; + + /** + * 导出时在excel中æ¯ä¸ªåˆ—的高度 + */ + public double height() default 14; + + /** + * 导出时在excel中æ¯ä¸ªåˆ—的宽度 + */ + public double width() default 16; + + /** + * 文字åŽç¼€,如% 90 å˜æˆ90% + */ + public String suffix() default ""; + + /** + * 当值为空时,字段的默认值 + */ + public String defaultValue() default ""; + + /** + * æç¤ºä¿¡æ¯ + */ + public String prompt() default ""; + + /** + * 设置åªèƒ½é€‰æ‹©ä¸èƒ½è¾“入的列内容. + */ + public String[] combo() default {}; + + /** + * 是å¦éœ€è¦çºµå‘åˆå¹¶å•元格,应对需求:嫿œ‰list集åˆå•元格) + */ + public boolean needMerge() default false; + + /** + * 是å¦å¯¼å‡ºæ•°æ®,应对需求:有时我们需è¦å¯¼å‡ºä¸€ä»½æ¨¡æ¿,这是标题需è¦ä½†å†…容需è¦ç”¨æˆ·æ‰‹å·¥å¡«å†™. + */ + public boolean isExport() default true; + + /** + * å¦ä¸€ä¸ªç±»ä¸­çš„属性åç§°,支æŒå¤šçº§èŽ·å–,以尿•°ç‚¹éš”å¼€ + */ + public String targetAttr() default ""; + + /** + * 是å¦è‡ªåŠ¨ç»Ÿè®¡æ•°æ®,在最åŽè¿½åŠ ä¸€è¡Œç»Ÿè®¡æ•°æ®æ€»å’Œ + */ + public boolean isStatistics() default false; + + /** + * 导出类型(0æ•°å­— 1字符串 2图片) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出列头背景颜色 + */ + public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT; + + /** + * 导出列头字体颜色 + */ + public IndexedColors headerColor() default IndexedColors.WHITE; + + /** + * 导出å•元格背景颜色 + */ + public IndexedColors backgroundColor() default IndexedColors.WHITE; + + /** + * 导出å•元格字体颜色 + */ + public IndexedColors color() default IndexedColors.BLACK; + + /** + * å¯¼å‡ºå­—æ®µå¯¹é½æ–¹å¼ + */ + public HorizontalAlignment align() default HorizontalAlignment.CENTER; + + /** + * 自定义数æ®å¤„ç†å™¨ + */ + public Class handler() default ExcelHandlerAdapter.class; + + /** + * 自定义数æ®å¤„ç†å™¨å‚æ•° + */ + public String[] args() default {}; + + /** + * 字段类型(0:导出导入;1:仅导出;2:仅导入) + */ + Type type() default Type.ALL; + + public enum Type + { + ALL(0), EXPORT(1), IMPORT(2); + private final int value; + + Type(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + public enum ColumnType + { + NUMERIC(0), STRING(1), IMAGE(2); + private final int value; + + ColumnType(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java new file mode 100644 index 0000000..5850723 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excel注解集 + * + * @author ruoyi + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Excels +{ + public Excel[] value(); +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java new file mode 100644 index 0000000..5ae846a --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java @@ -0,0 +1,51 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.enums.OperatorType; + +/** + * 自定义æ“作日志记录注解 + * + * @author ruoyi + * + */ +@Target({ ElementType.PARAMETER, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log +{ + /** + * æ¨¡å— + */ + public String title() default ""; + + /** + * 功能 + */ + public BusinessType businessType() default BusinessType.OTHER; + + /** + * æ“作人类别 + */ + public OperatorType operatorType() default OperatorType.MANAGE; + + /** + * 是å¦ä¿å­˜è¯·æ±‚çš„å‚æ•° + */ + public boolean isSaveRequestData() default true; + + /** + * 是å¦ä¿å­˜å“åº”çš„å‚æ•° + */ + public boolean isSaveResponseData() default true; + + /** + * æŽ’é™¤æŒ‡å®šçš„è¯·æ±‚å‚æ•° + */ + public String[] excludeParamNames() default {}; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java new file mode 100644 index 0000000..050ac2d --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java @@ -0,0 +1,40 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.enums.LimitType; + +/** + * 陿µæ³¨è§£ + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RateLimiter +{ + /** + * 陿µkey + */ + public String key() default CacheConstants.RATE_LIMIT_KEY; + + /** + * 陿µæ—¶é—´,å•ä½ç§’ + */ + public int time() default 60; + + /** + * 陿µæ¬¡æ•° + */ + public int count() default 100; + + /** + * 陿µç±»åž‹ + */ + public LimitType limitType() default LimitType.DEFAULT; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java new file mode 100644 index 0000000..1e27743 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java @@ -0,0 +1,31 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义注解防止表å•é‡å¤æäº¤ + * + * @author ruoyi + * + */ +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RepeatSubmit +{ + /** + * 间隔时间(ms),å°äºŽæ­¤æ—¶é—´è§†ä¸ºé‡å¤æäº¤ + */ + public int interval() default 5000; + + /** + * æç¤ºæ¶ˆæ¯ + */ + public String message() default "ä¸å…许é‡å¤æäº¤ï¼Œè¯·ç¨å€™å†è¯•"; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java new file mode 100644 index 0000000..84c0029 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -0,0 +1,135 @@ +package com.ruoyi.common.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 读å–项目相关é…ç½® + * + * @author ruoyi + */ +@Component +@ConfigurationProperties(prefix = "ruoyi") +public class RuoYiConfig +{ + /** 项目åç§° */ + private String name; + + /** 版本 */ + private String version; + + /** 版æƒå¹´ä»½ */ + private String copyrightYear; + + /** 实例演示开关 */ + private boolean demoEnabled; + + /** 上传路径 */ + private static String profile; + + /** 获å–地å€å¼€å…³ */ + private static boolean addressEnabled; + + /** 验è¯ç ç±»åž‹ */ + private static String captchaType; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getCopyrightYear() + { + return copyrightYear; + } + + public void setCopyrightYear(String copyrightYear) + { + this.copyrightYear = copyrightYear; + } + + public boolean isDemoEnabled() + { + return demoEnabled; + } + + public void setDemoEnabled(boolean demoEnabled) + { + this.demoEnabled = demoEnabled; + } + + public static String getProfile() + { + return profile; + } + + public void setProfile(String profile) + { + RuoYiConfig.profile = profile; + } + + public static boolean isAddressEnabled() + { + return addressEnabled; + } + + public void setAddressEnabled(boolean addressEnabled) + { + RuoYiConfig.addressEnabled = addressEnabled; + } + + public static String getCaptchaType() { + return captchaType; + } + + public void setCaptchaType(String captchaType) { + RuoYiConfig.captchaType = captchaType; + } + + /** + * 获å–导入上传路径 + */ + public static String getImportPath() + { + return getProfile() + "/import"; + } + + /** + * 获å–头åƒä¸Šä¼ è·¯å¾„ + */ + public static String getAvatarPath() + { + return getProfile() + "/avatar"; + } + + /** + * 获å–下载路径 + */ + public static String getDownloadPath() + { + return getProfile() + "/download/"; + } + + /** + * 获å–上传路径 + */ + public static String getUploadPath() + { + return getProfile() + "/upload"; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java new file mode 100644 index 0000000..c89692c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -0,0 +1,44 @@ +package com.ruoyi.common.constant; + +/** + * 缓存的key å¸¸é‡ + * + * @author ruoyi + */ +public class CacheConstants +{ + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 验è¯ç  redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 傿•°ç®¡ç† cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * å­—å…¸ç®¡ç† cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * é˜²é‡æäº¤ redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 陿µ redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 登录账户密ç é”™è¯¯æ¬¡æ•° redis key + */ + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java new file mode 100644 index 0000000..f4ba293 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -0,0 +1,142 @@ +package com.ruoyi.common.constant; + +import io.jsonwebtoken.Claims; + +/** + * 通用常é‡ä¿¡æ¯ + * + * @author ruoyi + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * www主域 + */ + public static final String WWW = "www."; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用æˆåŠŸæ ‡è¯† + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录æˆåŠŸ + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验è¯ç æœ‰æ•ˆæœŸï¼ˆåˆ†é’Ÿï¼‰ + */ + public static final Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + public static final String TOKEN = "token"; + + /** + * 令牌å‰ç¼€ + */ + public static final String TOKEN_PREFIX = "Bearer "; + + /** + * 令牌å‰ç¼€ + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + + /** + * 用户ID + */ + public static final String JWT_USERID = "userid"; + + /** + * 用户åç§° + */ + public static final String JWT_USERNAME = Claims.SUBJECT; + + /** + * ç”¨æˆ·å¤´åƒ + */ + public static final String JWT_AVATAR = "avatar"; + + /** + * 创建时间 + */ + public static final String JWT_CREATED = "created"; + + /** + * 用户æƒé™ + */ + public static final String JWT_AUTHORITIES = "authorities"; + + /** + * èµ„æºæ˜ å°„路径 å‰ç¼€ + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi:"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap:"; + + /** + * LDAPS 远程方法调用 + */ + public static final String LOOKUP_LDAPS = "ldaps:"; + + /** + * 定时任务白åå•é…置(仅å…许访问的包å,如其他需è¦å¯ä»¥è‡ªè¡Œæ·»åŠ ï¼‰ + */ + public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; + + /** + * 定时任务è¿è§„的字符 + */ + public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", + "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" }; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java new file mode 100644 index 0000000..e7382b3 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java @@ -0,0 +1,117 @@ +package com.ruoyi.common.constant; + +/** + * 代ç ç”Ÿæˆé€šç”¨å¸¸é‡ + * + * @author ruoyi + */ +public class GenConstants +{ + /** å•表(增删改查) */ + public static final String TPL_CRUD = "crud"; + + /** 树表(增删改查) */ + public static final String TPL_TREE = "tree"; + + /** 主å­è¡¨ï¼ˆå¢žåˆ æ”¹æŸ¥ï¼‰ */ + public static final String TPL_SUB = "sub"; + + /** æ ‘ç¼–ç å­—段 */ + public static final String TREE_CODE = "treeCode"; + + /** 树父编ç å­—段 */ + public static final String TREE_PARENT_CODE = "treeParentCode"; + + /** æ ‘å称字段 */ + public static final String TREE_NAME = "treeName"; + + /** 上级èœå•ID字段 */ + public static final String PARENT_MENU_ID = "parentMenuId"; + + /** 上级èœå•å称字段 */ + public static final String PARENT_MENU_NAME = "parentMenuName"; + + /** æ•°æ®åº“字符串类型 */ + public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; + + /** æ•°æ®åº“文本类型 */ + public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; + + /** æ•°æ®åº“时间类型 */ + public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; + + /** æ•°æ®åº“数字类型 */ + public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", + "bit", "bigint", "float", "double", "decimal" }; + + /** 页é¢ä¸éœ€è¦ç¼–辑字段 */ + public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; + + /** 页é¢ä¸éœ€è¦æ˜¾ç¤ºçš„列表字段 */ + public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time" }; + + /** 页é¢ä¸éœ€è¦æŸ¥è¯¢å­—段 */ + public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time", "remark" }; + + /** Entity基类字段 */ + public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; + + /** Tree基类字段 */ + public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; + + /** 文本框 */ + public static final String HTML_INPUT = "input"; + + /** 文本域 */ + public static final String HTML_TEXTAREA = "textarea"; + + /** 下拉框 */ + public static final String HTML_SELECT = "select"; + + /** å•选框 */ + public static final String HTML_RADIO = "radio"; + + /** å¤é€‰æ¡† */ + public static final String HTML_CHECKBOX = "checkbox"; + + /** 日期控件 */ + public static final String HTML_DATETIME = "datetime"; + + /** 图片上传控件 */ + public static final String HTML_IMAGE_UPLOAD = "imageUpload"; + + /** 文件上传控件 */ + public static final String HTML_FILE_UPLOAD = "fileUpload"; + + /** 富文本控件 */ + public static final String HTML_EDITOR = "editor"; + + /** 字符串类型 */ + public static final String TYPE_STRING = "String"; + + /** æ•´åž‹ */ + public static final String TYPE_INTEGER = "Integer"; + + /** é•¿æ•´åž‹ */ + public static final String TYPE_LONG = "Long"; + + /** 浮点型 */ + public static final String TYPE_DOUBLE = "Double"; + + /** 高精度计算类型 */ + public static final String TYPE_BIGDECIMAL = "BigDecimal"; + + /** 时间类型 */ + public static final String TYPE_DATE = "Date"; + + /** 模糊查询 */ + public static final String QUERY_LIKE = "LIKE"; + + /** 相等查询 */ + public static final String QUERY_EQ = "EQ"; + + /** éœ€è¦ */ + public static final String REQUIRE = "1"; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java new file mode 100644 index 0000000..db839c5 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java @@ -0,0 +1,94 @@ +package com.ruoyi.common.constant; + +/** + * 返回状æ€ç  + * + * @author ruoyi + */ +public class HttpStatus +{ + /** + * æ“作æˆåŠŸ + */ + public static final int SUCCESS = 200; + + /** + * 对象创建æˆåŠŸ + */ + public static final int CREATED = 201; + + /** + * 请求已ç»è¢«æŽ¥å— + */ + public static final int ACCEPTED = 202; + + /** + * æ“ä½œå·²ç»æ‰§è¡ŒæˆåŠŸï¼Œä½†æ˜¯æ²¡æœ‰è¿”å›žæ•°æ® + */ + public static final int NO_CONTENT = 204; + + /** + * 资æºå·²è¢«ç§»é™¤ + */ + public static final int MOVED_PERM = 301; + + /** + * é‡å®šå‘ + */ + public static final int SEE_OTHER = 303; + + /** + * èµ„æºæ²¡æœ‰è¢«ä¿®æ”¹ + */ + public static final int NOT_MODIFIED = 304; + + /** + * 傿•°åˆ—表错误(缺少,格å¼ä¸åŒ¹é…) + */ + public static final int BAD_REQUEST = 400; + + /** + * æœªæŽˆæƒ + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问å—é™ï¼ŒæŽˆæƒè¿‡æœŸ + */ + public static final int FORBIDDEN = 403; + + /** + * 资æºï¼ŒæœåŠ¡æœªæ‰¾åˆ° + */ + public static final int NOT_FOUND = 404; + + /** + * ä¸å…许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资æºå†²çªï¼Œæˆ–者资æºè¢«é” + */ + public static final int CONFLICT = 409; + + /** + * 䏿”¯æŒçš„æ•°æ®ï¼Œåª’体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * æŽ¥å£æœªå®žçް + */ + public static final int NOT_IMPLEMENTED = 501; + + /** + * ç³»ç»Ÿè­¦å‘Šæ¶ˆæ¯ + */ + public static final int WARN = 601; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java new file mode 100644 index 0000000..8318b8f --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java @@ -0,0 +1,50 @@ +package com.ruoyi.common.constant; + +/** + * ä»»åŠ¡è°ƒåº¦é€šç”¨å¸¸é‡ + * + * @author ruoyi + */ +public class ScheduleConstants +{ + public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; + + /** 执行目标key */ + public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; + + /** 默认 */ + public static final String MISFIRE_DEFAULT = "0"; + + /** ç«‹å³è§¦å‘执行 */ + public static final String MISFIRE_IGNORE_MISFIRES = "1"; + + /** 触å‘一次执行 */ + public static final String MISFIRE_FIRE_AND_PROCEED = "2"; + + /** ä¸è§¦å‘ç«‹å³æ‰§è¡Œ */ + public static final String MISFIRE_DO_NOTHING = "3"; + + public enum Status + { + /** + * 正常 + */ + NORMAL("0"), + /** + * æš‚åœ + */ + PAUSE("1"); + + private String value; + + private Status(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java new file mode 100644 index 0000000..b09b6f3 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java @@ -0,0 +1,78 @@ +package com.ruoyi.common.constant; + +/** + * 用户常é‡ä¿¡æ¯ + * + * @author ruoyi + */ +public class UserConstants +{ + /** + * å¹³å°å†…系统用户的唯一标志 + */ + public static final String SYS_USER = "SYS_USER"; + + /** æ­£å¸¸çŠ¶æ€ */ + public static final String NORMAL = "0"; + + /** å¼‚å¸¸çŠ¶æ€ */ + public static final String EXCEPTION = "1"; + + /** 用户å°ç¦çŠ¶æ€ */ + public static final String USER_DISABLE = "1"; + + /** 角色å°ç¦çŠ¶æ€ */ + public static final String ROLE_DISABLE = "1"; + + /** éƒ¨é—¨æ­£å¸¸çŠ¶æ€ */ + public static final String DEPT_NORMAL = "0"; + + /** 部门åœç”¨çŠ¶æ€ */ + public static final String DEPT_DISABLE = "1"; + + /** å­—å…¸æ­£å¸¸çŠ¶æ€ */ + public static final String DICT_NORMAL = "0"; + + /** 是å¦ä¸ºç³»ç»Ÿé»˜è®¤ï¼ˆæ˜¯ï¼‰ */ + public static final String YES = "Y"; + + /** 是å¦èœå•外链(是) */ + public static final String YES_FRAME = "0"; + + /** 是å¦èœå•外链(å¦ï¼‰ */ + public static final String NO_FRAME = "1"; + + /** èœå•类型(目录) */ + public static final String TYPE_DIR = "M"; + + /** èœå•类型(èœå•) */ + public static final String TYPE_MENU = "C"; + + /** èœå•类型(按钮) */ + public static final String TYPE_BUTTON = "F"; + + /** Layout组件标识 */ + public final static String LAYOUT = "Layout"; + + /** ParentView组件标识 */ + public final static String PARENT_VIEW = "ParentView"; + + /** InnerLink组件标识 */ + public final static String INNER_LINK = "InnerLink"; + + /** 校验是å¦å”¯ä¸€çš„返回标识 */ + public final static boolean UNIQUE = true; + public final static boolean NOT_UNIQUE = false; + + /** + * 用户å长度é™åˆ¶ + */ + public static final int USERNAME_MIN_LENGTH = 2; + public static final int USERNAME_MAX_LENGTH = 20; + + /** + * 密ç é•¿åº¦é™åˆ¶ + */ + public static final int PASSWORD_MIN_LENGTH = 5; + public static final int PASSWORD_MAX_LENGTH = 20; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java new file mode 100644 index 0000000..c131bc4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java @@ -0,0 +1,202 @@ +package com.ruoyi.common.core.controller; + +import java.beans.PropertyEditorSupport; +import java.util.Date; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.page.TableSupport; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.PageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.sql.SqlUtil; + +/** + * web层通用数æ®å¤„ç† + * + * @author ruoyi + */ +public class BaseController +{ + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * å°†å‰å°ä¼ é€’过æ¥çš„æ—¥æœŸæ ¼å¼çš„字符串,自动转化为Date类型 + */ + @InitBinder + public void initBinder(WebDataBinder binder) + { + // Date ç±»åž‹è½¬æ¢ + binder.registerCustomEditor(Date.class, new PropertyEditorSupport() + { + @Override + public void setAsText(String text) + { + setValue(DateUtils.parseDate(text)); + } + }); + } + + /** + * è®¾ç½®è¯·æ±‚åˆ†é¡µæ•°æ® + */ + protected void startPage() + { + PageUtils.startPage(); + } + + /** + * è®¾ç½®è¯·æ±‚æŽ’åºæ•°æ® + */ + protected void startOrderBy() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) + { + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + PageHelper.orderBy(orderBy); + } + } + + /** + * 清ç†åˆ†é¡µçš„线程å˜é‡ + */ + protected void clearPage() + { + PageUtils.clearPage(); + } + + /** + * å“åº”è¯·æ±‚åˆ†é¡µæ•°æ® + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected TableDataInfo getDataTable(List list) + { + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询æˆåŠŸ"); + rspData.setRows(list); + rspData.setTotal(new PageInfo(list).getTotal()); + return rspData; + } + + /** + * 返回æˆåŠŸ + */ + public AjaxResult success() + { + return AjaxResult.success(); + } + + /** + * è¿”å›žå¤±è´¥æ¶ˆæ¯ + */ + public AjaxResult error() + { + return AjaxResult.error(); + } + + /** + * 返回æˆåŠŸæ¶ˆæ¯ + */ + public AjaxResult success(String message) + { + return AjaxResult.success(message); + } + + /** + * 返回æˆåŠŸæ¶ˆæ¯ + */ + public AjaxResult success(Object data) + { + return AjaxResult.success(data); + } + + /** + * è¿”å›žå¤±è´¥æ¶ˆæ¯ + */ + public AjaxResult error(String message) + { + return AjaxResult.error(message); + } + + /** + * è¿”å›žè­¦å‘Šæ¶ˆæ¯ + */ + public AjaxResult warn(String message) + { + return AjaxResult.warn(message); + } + + /** + * å“应返回结果 + * + * @param rows å½±å“行数 + * @return æ“作结果 + */ + protected AjaxResult toAjax(int rows) + { + return rows > 0 ? AjaxResult.success() : AjaxResult.error(); + } + + /** + * å“应返回结果 + * + * @param result 结果 + * @return æ“作结果 + */ + protected AjaxResult toAjax(boolean result) + { + return result ? success() : error(); + } + + /** + * 页é¢è·³è½¬ + */ + public String redirect(String url) + { + return StringUtils.format("redirect:{}", url); + } + + /** + * 获å–ç”¨æˆ·ç¼“å­˜ä¿¡æ¯ + */ + public LoginUser getLoginUser() + { + return SecurityUtils.getLoginUser(); + } + + /** + * 获å–登录用户id + */ + public Long getUserId() + { + return getLoginUser().getUserId(); + } + + /** + * 获å–登录部门id + */ + public Long getDeptId() + { + return getLoginUser().getDeptId(); + } + + /** + * 获å–登录用户å + */ + public String getUsername() + { + return getLoginUser().getUsername(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java new file mode 100644 index 0000000..42dcbcd --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java @@ -0,0 +1,216 @@ +package com.ruoyi.common.core.domain; + +import java.util.HashMap; +import java.util.Objects; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.utils.StringUtils; + +/** + * æ“ä½œæ¶ˆæ¯æé†’ + * + * @author ruoyi + */ +public class AjaxResult extends HashMap +{ + private static final long serialVersionUID = 1L; + + /** 状æ€ç  */ + public static final String CODE_TAG = "code"; + + /** 返回内容 */ + public static final String MSG_TAG = "msg"; + + /** æ•°æ®å¯¹è±¡ */ + public static final String DATA_TAG = "data"; + + /** + * åˆå§‹åŒ–一个新创建的 AjaxResult 对象,使其表示一个空消æ¯ã€‚ + */ + public AjaxResult() + { + } + + /** + * åˆå§‹åŒ–一个新创建的 AjaxResult 对象 + * + * @param code 状æ€ç  + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * åˆå§‹åŒ–一个新创建的 AjaxResult 对象 + * + * @param code 状æ€ç  + * @param msg 返回内容 + * @param data æ•°æ®å¯¹è±¡ + */ + public AjaxResult(int code, String msg, Object data) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (StringUtils.isNotNull(data)) + { + super.put(DATA_TAG, data); + } + } + + /** + * 返回æˆåŠŸæ¶ˆæ¯ + * + * @return æˆåŠŸæ¶ˆæ¯ + */ + public static AjaxResult success() + { + return AjaxResult.success("æ“作æˆåŠŸ"); + } + + /** + * 返回æˆåŠŸæ•°æ® + * + * @return æˆåŠŸæ¶ˆæ¯ + */ + public static AjaxResult success(Object data) + { + return AjaxResult.success("æ“作æˆåŠŸ", data); + } + + /** + * 返回æˆåŠŸæ¶ˆæ¯ + * + * @param msg 返回内容 + * @return æˆåŠŸæ¶ˆæ¯ + */ + public static AjaxResult success(String msg) + { + return AjaxResult.success(msg, null); + } + + /** + * 返回æˆåŠŸæ¶ˆæ¯ + * + * @param msg 返回内容 + * @param data æ•°æ®å¯¹è±¡ + * @return æˆåŠŸæ¶ˆæ¯ + */ + public static AjaxResult success(String msg, Object data) + { + return new AjaxResult(HttpStatus.SUCCESS, msg, data); + } + + /** + * è¿”å›žè­¦å‘Šæ¶ˆæ¯ + * + * @param msg 返回内容 + * @return è­¦å‘Šæ¶ˆæ¯ + */ + public static AjaxResult warn(String msg) + { + return AjaxResult.warn(msg, null); + } + + /** + * è¿”å›žè­¦å‘Šæ¶ˆæ¯ + * + * @param msg 返回内容 + * @param data æ•°æ®å¯¹è±¡ + * @return è­¦å‘Šæ¶ˆæ¯ + */ + public static AjaxResult warn(String msg, Object data) + { + return new AjaxResult(HttpStatus.WARN, msg, data); + } + + /** + * è¿”å›žé”™è¯¯æ¶ˆæ¯ + * + * @return é”™è¯¯æ¶ˆæ¯ + */ + public static AjaxResult error() + { + return AjaxResult.error("æ“作失败"); + } + + /** + * è¿”å›žé”™è¯¯æ¶ˆæ¯ + * + * @param msg 返回内容 + * @return é”™è¯¯æ¶ˆæ¯ + */ + public static AjaxResult error(String msg) + { + return AjaxResult.error(msg, null); + } + + /** + * è¿”å›žé”™è¯¯æ¶ˆæ¯ + * + * @param msg 返回内容 + * @param data æ•°æ®å¯¹è±¡ + * @return é”™è¯¯æ¶ˆæ¯ + */ + public static AjaxResult error(String msg, Object data) + { + return new AjaxResult(HttpStatus.ERROR, msg, data); + } + + /** + * è¿”å›žé”™è¯¯æ¶ˆæ¯ + * + * @param code 状æ€ç  + * @param msg 返回内容 + * @return é”™è¯¯æ¶ˆæ¯ + */ + public static AjaxResult error(int code, String msg) + { + return new AjaxResult(code, msg, null); + } + + /** + * 是å¦ä¸ºæˆåŠŸæ¶ˆæ¯ + * + * @return 结果 + */ + public boolean isSuccess() + { + return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG)); + } + + /** + * 是å¦ä¸ºè­¦å‘Šæ¶ˆæ¯ + * + * @return 结果 + */ + public boolean isWarn() + { + return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG)); + } + + /** + * 是å¦ä¸ºé”™è¯¯æ¶ˆæ¯ + * + * @return 结果 + */ + public boolean isError() + { + return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG)); + } + + /** + * 方便链å¼è°ƒç”¨ + * + * @param key é”® + * @param value 值 + * @return æ•°æ®å¯¹è±¡ + */ + @Override + public AjaxResult put(String key, Object value) + { + super.put(key, value); + return this; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java new file mode 100644 index 0000000..67269ff --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -0,0 +1,118 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Entity基类 + * + * @author ruoyi + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** æœç´¢å€¼ */ + @JsonIgnore + private String searchValue; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** æ›´æ–°æ—¶é—´ */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** 备注 */ + private String remark; + + /** è¯·æ±‚å‚æ•° */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public String getSearchValue() + { + return searchValue; + } + + public void setSearchValue(String searchValue) + { + this.searchValue = searchValue; + } + + public String getCreateBy() + { + return createBy; + } + + public void setCreateBy(String createBy) + { + this.createBy = createBy; + } + + public Date getCreateTime() + { + return createTime; + } + + public void setCreateTime(Date createTime) + { + this.createTime = createTime; + } + + public String getUpdateBy() + { + return updateBy; + } + + public void setUpdateBy(String updateBy) + { + this.updateBy = updateBy; + } + + public Date getUpdateTime() + { + return updateTime; + } + + public void setUpdateTime(Date updateTime) + { + this.updateTime = updateTime; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java new file mode 100644 index 0000000..ef15802 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java @@ -0,0 +1,115 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import com.ruoyi.common.constant.HttpStatus; + +/** + * å“应信æ¯ä¸»ä½“ + * + * @author ruoyi + */ +public class R implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** æˆåŠŸ */ + public static final int SUCCESS = HttpStatus.SUCCESS; + + /** 失败 */ + public static final int FAIL = HttpStatus.ERROR; + + private int code; + + private String msg; + + private T data; + + public static R ok() + { + return restResult(null, SUCCESS, "æ“作æˆåŠŸ"); + } + + public static R ok(T data) + { + return restResult(data, SUCCESS, "æ“作æˆåŠŸ"); + } + + public static R ok(T data, String msg) + { + return restResult(data, SUCCESS, msg); + } + + public static R fail() + { + return restResult(null, FAIL, "æ“作失败"); + } + + public static R fail(String msg) + { + return restResult(null, FAIL, msg); + } + + public static R fail(T data) + { + return restResult(data, FAIL, "æ“作失败"); + } + + public static R fail(T data, String msg) + { + return restResult(data, FAIL, msg); + } + + public static R fail(int code, String msg) + { + return restResult(null, code, msg); + } + + private static R restResult(T data, int code, String msg) + { + R apiResult = new R<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public T getData() + { + return data; + } + + public void setData(T data) + { + this.data = data; + } + + public static Boolean isError(R ret) + { + return !isSuccess(ret); + } + + public static Boolean isSuccess(R ret) + { + return R.SUCCESS == ret.getCode(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java new file mode 100644 index 0000000..171f04c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java @@ -0,0 +1,79 @@ +package com.ruoyi.common.core.domain; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tree基类 + * + * @author ruoyi + */ +public class TreeEntity extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 父èœå•åç§° */ + private String parentName; + + /** 父èœå•ID */ + private Long parentId; + + /** æ˜¾ç¤ºé¡ºåº */ + private Integer orderNum; + + /** 祖级列表 */ + private String ancestors; + + /** å­éƒ¨é—¨ */ + private List children = new ArrayList<>(); + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java new file mode 100644 index 0000000..4a59e40 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java @@ -0,0 +1,77 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * Treeselect树结构实体类 + * + * @author ruoyi + */ +public class TreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点åç§° */ + private String label; + + /** å­èŠ‚ç‚¹ */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect() + { + + } + + public TreeSelect(SysDept dept) + { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysMenu menu) + { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java new file mode 100644 index 0000000..693461b --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -0,0 +1,203 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 部门表 sys_dept + * + * @author ruoyi + */ +public class SysDept extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 部门ID */ + private Long deptId; + + /** 父部门ID */ + private Long parentId; + + /** 祖级列表 */ + private String ancestors; + + /** 部门åç§° */ + private String deptName; + + /** æ˜¾ç¤ºé¡ºåº */ + private Integer orderNum; + + /** 负责人 */ + private String leader; + + /** è”ç³»ç”µè¯ */ + private String phone; + + /** 邮箱 */ + private String email; + + /** 部门状æ€:0正常,1åœç”¨ */ + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 父部门åç§° */ + private String parentName; + + /** å­éƒ¨é—¨ */ + private List children = new ArrayList(); + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + @NotBlank(message = "部门åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 30, message = "部门å称长度ä¸èƒ½è¶…过30个字符") + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + @NotNull(message = "显示顺åºä¸èƒ½ä¸ºç©º") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getLeader() + { + return leader; + } + + public void setLeader(String leader) + { + this.leader = leader; + } + + @Size(min = 0, max = 11, message = "è”系电è¯é•¿åº¦ä¸èƒ½è¶…过11个字符") + public String getPhone() + { + return phone; + } + + public void setPhone(String phone) + { + this.phone = phone; + } + + @Email(message = "邮箱格å¼ä¸æ­£ç¡®") + @Size(min = 0, max = 50, message = "邮箱长度ä¸èƒ½è¶…过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("deptId", getDeptId()) + .append("parentId", getParentId()) + .append("ancestors", getAncestors()) + .append("deptName", getDeptName()) + .append("orderNum", getOrderNum()) + .append("leader", getLeader()) + .append("phone", getPhone()) + .append("email", getEmail()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java new file mode 100644 index 0000000..e79eaa2 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -0,0 +1,176 @@ +package com.ruoyi.common.core.domain.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 字典数æ®è¡¨ sys_dict_data + * + * @author ruoyi + */ +public class SysDictData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** å­—å…¸ç¼–ç  */ + @Excel(name = "字典编ç ", cellType = ColumnType.NUMERIC) + private Long dictCode; + + /** å­—å…¸æŽ’åº */ + @Excel(name = "字典排åº", cellType = ColumnType.NUMERIC) + private Long dictSort; + + /** 字典标签 */ + @Excel(name = "字典标签") + private String dictLabel; + + /** 字典键值 */ + @Excel(name = "字典键值") + private String dictValue; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** æ ·å¼å±žæ€§ï¼ˆå…¶ä»–æ ·å¼æ‰©å±•) */ + private String cssClass; + + /** è¡¨æ ¼å­—å…¸æ ·å¼ */ + private String listClass; + + /** 是å¦é»˜è®¤ï¼ˆY是 Nå¦ï¼‰ */ + @Excel(name = "是å¦é»˜è®¤", readConverterExp = "Y=是,N=å¦") + private String isDefault; + + /** 状æ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + @Excel(name = "状æ€", readConverterExp = "0=正常,1=åœç”¨") + private String status; + + public Long getDictCode() + { + return dictCode; + } + + public void setDictCode(Long dictCode) + { + this.dictCode = dictCode; + } + + public Long getDictSort() + { + return dictSort; + } + + public void setDictSort(Long dictSort) + { + this.dictSort = dictSort; + } + + @NotBlank(message = "字典标签ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "字典标签长度ä¸èƒ½è¶…过100个字符") + public String getDictLabel() + { + return dictLabel; + } + + public void setDictLabel(String dictLabel) + { + this.dictLabel = dictLabel; + } + + @NotBlank(message = "字典键值ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "字典键值长度ä¸èƒ½è¶…过100个字符") + public String getDictValue() + { + return dictValue; + } + + public void setDictValue(String dictValue) + { + this.dictValue = dictValue; + } + + @NotBlank(message = "字典类型ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "字典类型长度ä¸èƒ½è¶…过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + @Size(min = 0, max = 100, message = "æ ·å¼å±žæ€§é•¿åº¦ä¸èƒ½è¶…过100个字符") + public String getCssClass() + { + return cssClass; + } + + public void setCssClass(String cssClass) + { + this.cssClass = cssClass; + } + + public String getListClass() + { + return listClass; + } + + public void setListClass(String listClass) + { + this.listClass = listClass; + } + + public boolean getDefault() + { + return UserConstants.YES.equals(this.isDefault); + } + + public String getIsDefault() + { + return isDefault; + } + + public void setIsDefault(String isDefault) + { + this.isDefault = isDefault; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictCode", getDictCode()) + .append("dictSort", getDictSort()) + .append("dictLabel", getDictLabel()) + .append("dictValue", getDictValue()) + .append("dictType", getDictType()) + .append("cssClass", getCssClass()) + .append("listClass", getListClass()) + .append("isDefault", getIsDefault()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java new file mode 100644 index 0000000..0befbf4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -0,0 +1,96 @@ +package com.ruoyi.common.core.domain.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 字典类型表 sys_dict_type + * + * @author ruoyi + */ +public class SysDictType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典主键 */ + @Excel(name = "字典主键", cellType = ColumnType.NUMERIC) + private Long dictId; + + /** å­—å…¸åç§° */ + @Excel(name = "å­—å…¸åç§°") + private String dictName; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 状æ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + @Excel(name = "状æ€", readConverterExp = "0=正常,1=åœç”¨") + private String status; + + public Long getDictId() + { + return dictId; + } + + public void setDictId(Long dictId) + { + this.dictId = dictId; + } + + @NotBlank(message = "å­—å…¸åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "字典类型å称长度ä¸èƒ½è¶…过100个字符") + public String getDictName() + { + return dictName; + } + + public void setDictName(String dictName) + { + this.dictName = dictName; + } + + @NotBlank(message = "字典类型ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "字典类型类型长度ä¸èƒ½è¶…过100个字符") + @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字æ¯å¼€å¤´ï¼Œä¸”åªèƒ½ä¸ºï¼ˆå°å†™å­—æ¯ï¼Œæ•°å­—,下滑线)") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictId", getDictId()) + .append("dictName", getDictName()) + .append("dictType", getDictType()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java new file mode 100644 index 0000000..9f3a6f6 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -0,0 +1,259 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * èœå•æƒé™è¡¨ sys_menu + * + * @author ruoyi + */ +public class SysMenu extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** èœå•ID */ + private Long menuId; + + /** èœå•åç§° */ + private String menuName; + + /** 父èœå•åç§° */ + private String parentName; + + /** 父èœå•ID */ + private Long parentId; + + /** æ˜¾ç¤ºé¡ºåº */ + private Integer orderNum; + + /** è·¯ç”±åœ°å€ */ + private String path; + + /** 组件路径 */ + private String component; + + /** è·¯ç”±å‚æ•° */ + private String query; + + /** 是å¦ä¸ºå¤–链(0是 1å¦ï¼‰ */ + private String isFrame; + + /** 是å¦ç¼“存(0缓存 1ä¸ç¼“存) */ + private String isCache; + + /** 类型(M目录 Cèœå• F按钮) */ + private String menuType; + + /** 显示状æ€ï¼ˆ0显示 1éšè—) */ + private String visible; + + /** èœå•状æ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + private String status; + + /** æƒé™å­—符串 */ + private String perms; + + /** èœå•图标 */ + private String icon; + + /** å­èœå• */ + private List children = new ArrayList(); + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @NotBlank(message = "èœå•åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 50, message = "èœå•å称长度ä¸èƒ½è¶…过50个字符") + public String getMenuName() + { + return menuName; + } + + public void setMenuName(String menuName) + { + this.menuName = menuName; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + @NotNull(message = "显示顺åºä¸èƒ½ä¸ºç©º") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + @Size(min = 0, max = 200, message = "路由地å€ä¸èƒ½è¶…过200个字符") + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + @Size(min = 0, max = 200, message = "组件路径ä¸èƒ½è¶…过255个字符") + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public String getIsFrame() + { + return isFrame; + } + + public void setIsFrame(String isFrame) + { + this.isFrame = isFrame; + } + + public String getIsCache() + { + return isCache; + } + + public void setIsCache(String isCache) + { + this.isCache = isCache; + } + + @NotBlank(message = "èœå•类型ä¸èƒ½ä¸ºç©º") + public String getMenuType() + { + return menuType; + } + + public void setMenuType(String menuType) + { + this.menuType = menuType; + } + + public String getVisible() + { + return visible; + } + + public void setVisible(String visible) + { + this.visible = visible; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Size(min = 0, max = 100, message = "æƒé™æ ‡è¯†é•¿åº¦ä¸èƒ½è¶…过100个字符") + public String getPerms() + { + return perms; + } + + public void setPerms(String perms) + { + this.perms = perms; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("menuId", getMenuId()) + .append("menuName", getMenuName()) + .append("parentId", getParentId()) + .append("orderNum", getOrderNum()) + .append("path", getPath()) + .append("component", getComponent()) + .append("isFrame", getIsFrame()) + .append("IsCache", getIsCache()) + .append("menuType", getMenuType()) + .append("visible", getVisible()) + .append("status ", getStatus()) + .append("perms", getPerms()) + .append("icon", getIcon()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java new file mode 100644 index 0000000..2396f80 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -0,0 +1,241 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Set; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 角色表 sys_role + * + * @author ruoyi + */ +public class SysRole extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 角色ID */ + @Excel(name = "角色åºå·", cellType = ColumnType.NUMERIC) + private Long roleId; + + /** 角色åç§° */ + @Excel(name = "角色åç§°") + private String roleName; + + /** 角色æƒé™ */ + @Excel(name = "角色æƒé™") + private String roleKey; + + /** è§’è‰²æŽ’åº */ + @Excel(name = "角色排åº") + private Integer roleSort; + + /** æ•°æ®èŒƒå›´ï¼ˆ1ï¼šæ‰€æœ‰æ•°æ®æƒé™ï¼›2ï¼šè‡ªå®šä¹‰æ•°æ®æƒé™ï¼›3ï¼šæœ¬éƒ¨é—¨æ•°æ®æƒé™ï¼›4:本部门åŠä»¥ä¸‹æ•°æ®æƒé™ï¼›5ï¼šä»…æœ¬äººæ•°æ®æƒé™ï¼‰ */ + @Excel(name = "æ•°æ®èŒƒå›´", readConverterExp = "1=æ‰€æœ‰æ•°æ®æƒé™,2=è‡ªå®šä¹‰æ•°æ®æƒé™,3=æœ¬éƒ¨é—¨æ•°æ®æƒé™,4=本部门åŠä»¥ä¸‹æ•°æ®æƒé™,5=ä»…æœ¬äººæ•°æ®æƒé™") + private String dataScope; + + /** èœå•树选择项是å¦å…³è”显示( 0:父å­ä¸äº’ç›¸å…³è”æ˜¾ç¤º 1:父å­äº’ç›¸å…³è”æ˜¾ç¤ºï¼‰ */ + private boolean menuCheckStrictly; + + /** 部门树选择项是å¦å…³è”显示(0:父å­ä¸äº’ç›¸å…³è”æ˜¾ç¤º 1:父å­äº’ç›¸å…³è”æ˜¾ç¤º ) */ + private boolean deptCheckStrictly; + + /** 角色状æ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + @Excel(name = "角色状æ€", readConverterExp = "0=正常,1=åœç”¨") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 用户是å¦å­˜åœ¨æ­¤è§’色标识 默认ä¸å­˜åœ¨ */ + private boolean flag = false; + + /** èœå•组 */ + private Long[] menuIds; + + /** éƒ¨é—¨ç»„ï¼ˆæ•°æ®æƒé™ï¼‰ */ + private Long[] deptIds; + + /** 角色èœå•æƒé™ */ + private Set permissions; + + public SysRole() + { + + } + + public SysRole(Long roleId) + { + this.roleId = roleId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public boolean isAdmin() + { + return isAdmin(this.roleId); + } + + public static boolean isAdmin(Long roleId) + { + return roleId != null && 1L == roleId; + } + + @NotBlank(message = "角色åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 30, message = "角色å称长度ä¸èƒ½è¶…过30个字符") + public String getRoleName() + { + return roleName; + } + + public void setRoleName(String roleName) + { + this.roleName = roleName; + } + + @NotBlank(message = "æƒé™å­—符ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "æƒé™å­—符长度ä¸èƒ½è¶…过100个字符") + public String getRoleKey() + { + return roleKey; + } + + public void setRoleKey(String roleKey) + { + this.roleKey = roleKey; + } + + @NotNull(message = "显示顺åºä¸èƒ½ä¸ºç©º") + public Integer getRoleSort() + { + return roleSort; + } + + public void setRoleSort(Integer roleSort) + { + this.roleSort = roleSort; + } + + public String getDataScope() + { + return dataScope; + } + + public void setDataScope(String dataScope) + { + this.dataScope = dataScope; + } + + public boolean isMenuCheckStrictly() + { + return menuCheckStrictly; + } + + public void setMenuCheckStrictly(boolean menuCheckStrictly) + { + this.menuCheckStrictly = menuCheckStrictly; + } + + public boolean isDeptCheckStrictly() + { + return deptCheckStrictly; + } + + public void setDeptCheckStrictly(boolean deptCheckStrictly) + { + this.deptCheckStrictly = deptCheckStrictly; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + public Long[] getMenuIds() + { + return menuIds; + } + + public void setMenuIds(Long[] menuIds) + { + this.menuIds = menuIds; + } + + public Long[] getDeptIds() + { + return deptIds; + } + + public void setDeptIds(Long[] deptIds) + { + this.deptIds = deptIds; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("roleName", getRoleName()) + .append("roleKey", getRoleKey()) + .append("roleSort", getRoleSort()) + .append("dataScope", getDataScope()) + .append("menuCheckStrictly", isMenuCheckStrictly()) + .append("deptCheckStrictly", isDeptCheckStrictly()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java new file mode 100644 index 0000000..1d61e32 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -0,0 +1,426 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.*; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.xss.Xss; + +/** + * 用户对象 sys_user + * + * @author ruoyi + */ +public class SysUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户ID */ + @Excel(name = "用户åºå·", cellType = ColumnType.NUMERIC, prompt = "用户编å·") + private Long userId; + + /** 部门ID */ + @Excel(name = "部门编å·", type = Type.IMPORT) + private Long deptId; + + /** 分公å¸ID */ + private Long countyCode; + + + /** ç”¨æˆ·è´¦å· */ + @Excel(name = "登录åç§°") + private String userName; + + /** 用户昵称 */ + @Excel(name = "用户åç§°") + private String nickName; + + /** 用户邮箱 */ + @Excel(name = "用户邮箱") + private String email; + + /** 手机å·ç  */ + @Excel(name = "手机å·ç ") + private String phonenumber; + + /** 用户性别 */ + @Excel(name = "用户性别", readConverterExp = "0=ç”·,1=女,2=未知") + private String sex; + + /** ç”¨æˆ·å¤´åƒ */ + private String avatar; + + /** 微信openid */ + private String wechatOpenid; + + /** 微信unionid */ + private String wechatUnionid; + + /** 微信昵称 */ + private String wechatNickname; + + /** å¾®ä¿¡å¤´åƒ */ + private String wechatAvatar; + + /** 是å¦ç»‘定微信 */ + private String bindWechat; + + /** å¯†ç  */ + private String password; + + /** ç›åР坆 */ + private String salt; + + /** å¸å·çжæ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + @Excel(name = "å¸å·çжæ€", readConverterExp = "0=正常,1=åœç”¨") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 最åŽç™»å½•IP */ + @Excel(name = "最åŽç™»å½•IP", type = Type.EXPORT) + private String loginIp; + + /** 最åŽç™»å½•æ—¶é—´ */ + @Excel(name = "最åŽç™»å½•æ—¶é—´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) + private Date loginDate; + + /** 部门对象 */ + @Excels({ + @Excel(name = "部门åç§°", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + }) + private SysDept dept; + + /** 角色对象 */ + private List roles; + + /** 角色组 */ + private Long[] roleIds; + + /** å²—ä½ç»„ */ + private Long[] postIds; + + /** 角色ID */ + private Long roleId; + + public SysUser() + { + + } + + public SysUser(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public boolean isAdmin() + { + return isAdmin(this.userId); + } + + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getCountyCode() { + return countyCode; + } + + public void setCountyCode(Long countyCode) { + this.countyCode = countyCode; + } + + @Size(min = 0, max = 30, message = "用户昵称长度ä¸èƒ½è¶…过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @NotBlank(message = "用户账å·ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 30, message = "用户账å·é•¿åº¦ä¸èƒ½è¶…过30个字符") + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + @Email(message = "邮箱格å¼ä¸æ­£ç¡®") + @Size(min = 0, max = 50, message = "邮箱长度ä¸èƒ½è¶…过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + @Size(min = 0, max = 11, message = "手机å·ç é•¿åº¦ä¸èƒ½è¶…过11个字符") + public String getPhonenumber() + { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) + { + this.phonenumber = phonenumber; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + public String getWechatOpenid() + { + return wechatOpenid; + } + + public void setWechatOpenid(String wechatOpenid) + { + this.wechatOpenid = wechatOpenid; + } + + public String getWechatUnionid() + { + return wechatUnionid; + } + + public void setWechatUnionid(String wechatUnionid) + { + this.wechatUnionid = wechatUnionid; + } + + public String getWechatNickname() + { + return wechatNickname; + } + + public void setWechatNickname(String wechatNickname) + { + this.wechatNickname = wechatNickname; + } + + public String getWechatAvatar() + { + return wechatAvatar; + } + + public void setWechatAvatar(String wechatAvatar) + { + this.wechatAvatar = wechatAvatar; + } + + public String getBindWechat() + { + return bindWechat; + } + + public void setBindWechat(String bindWechat) + { + this.bindWechat = bindWechat; + } + + @JsonIgnore + @JsonProperty + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getSalt() + { + return salt; + } + + public void setSalt(String salt) + { + this.salt = salt; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getLoginIp() + { + return loginIp; + } + + public void setLoginIp(String loginIp) + { + this.loginIp = loginIp; + } + + public Date getLoginDate() + { + return loginDate; + } + + public void setLoginDate(Date loginDate) + { + this.loginDate = loginDate; + } + + public SysDept getDept() + { + return dept; + } + + public void setDept(SysDept dept) + { + this.dept = dept; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + public Long[] getRoleIds() + { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) + { + this.roleIds = roleIds; + } + + public Long[] getPostIds() + { + return postIds; + } + + public void setPostIds(Long[] postIds) + { + this.postIds = postIds; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("countyCode",getCountyCode()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("wechatOpenid", getWechatOpenid()) + .append("wechatUnionid", getWechatUnionid()) + .append("wechatNickname", getWechatNickname()) + .append("wechatAvatar", getWechatAvatar()) + .append("bindWechat", getBindWechat()) + .append("password", getPassword()) + .append("salt", getSalt()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("postIds",getPostIds()) + .append("roleIds",getRoleIds()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java new file mode 100644 index 0000000..583b7a6 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java @@ -0,0 +1,69 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户登录对象 + * + * @author ruoyi + */ +public class LoginBody +{ + /** + * 用户å + */ + private String username; + + /** + * ç”¨æˆ·å¯†ç  + */ + private String password; + + /** + * 验è¯ç  + */ + private String code; + + /** + * 唯一标识 + */ + private String uuid; + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getCode() + { + return code; + } + + public void setCode(String code) + { + this.code = code; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java new file mode 100644 index 0000000..95e169c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -0,0 +1,266 @@ +package com.ruoyi.common.core.domain.model; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import java.util.Collection; +import java.util.Set; + +/** + * 登录用户身份æƒé™ + * + * @author ruoyi + */ +public class LoginUser implements UserDetails +{ + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IPåœ°å€ + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * æµè§ˆå™¨ç±»åž‹ + */ + private String browser; + + /** + * æ“作系统 + */ + private String os; + + /** + * æƒé™åˆ—表 + */ + private Set permissions; + + /** + * ç”¨æˆ·ä¿¡æ¯ + */ + private SysUser user; + + public LoginUser() + { + } + + public LoginUser(SysUser user, Set permissions) + { + this.user = user; + this.permissions = permissions; + } + + public LoginUser(Long userId, Long deptId, SysUser user, Set permissions) + { + this.userId = userId; + this.deptId = deptId; + this.user = user; + this.permissions = permissions; + } + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public String getToken() + { + return token; + } + + public void setToken(String token) + { + this.token = token; + } + + @JSONField(serialize = false) + @Override + public String getPassword() + { + return user.getPassword(); + } + + @Override + public String getUsername() + { + return user.getUserName(); + } + + /** + * è´¦æˆ·æ˜¯å¦æœªè¿‡æœŸ,è¿‡æœŸæ— æ³•éªŒè¯ + */ + @JSONField(serialize = false) + @Override + public boolean isAccountNonExpired() + { + return true; + } + + /** + * 指定用户是å¦è§£é”,é”å®šçš„ç”¨æˆ·æ— æ³•è¿›è¡Œèº«ä»½éªŒè¯ + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isAccountNonLocked() + { + return true; + } + + /** + * 指示是å¦å·²è¿‡æœŸçš„用户的凭æ®(密ç ),过期的凭æ®é˜²æ­¢è®¤è¯ + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isCredentialsNonExpired() + { + return true; + } + + /** + * 是å¦å¯ç”¨ ,ç¦ç”¨çš„用户ä¸èƒ½èº«ä»½éªŒè¯ + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isEnabled() + { + return true; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getExpireTime() + { + return expireTime; + } + + public void setExpireTime(Long expireTime) + { + this.expireTime = expireTime; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + public SysUser getUser() + { + return user; + } + + public void setUser(SysUser user) + { + this.user = user; + } + + @Override + public Collection getAuthorities() + { + return null; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java new file mode 100644 index 0000000..5baa887 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java @@ -0,0 +1,11 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户注册对象 + * + * @author ruoyi + */ +public class RegisterBody extends LoginBody +{ + +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java new file mode 100644 index 0000000..8966cb4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -0,0 +1,101 @@ +package com.ruoyi.common.core.page; + +import com.ruoyi.common.utils.StringUtils; + +/** + * åˆ†é¡µæ•°æ® + * + * @author ruoyi + */ +public class PageDomain +{ + /** 当å‰è®°å½•起始索引 */ + private Integer pageNum; + + /** æ¯é¡µæ˜¾ç¤ºè®°å½•æ•° */ + private Integer pageSize; + + /** 排åºåˆ— */ + private String orderByColumn; + + /** 排åºçš„æ–¹å‘desc或者asc */ + private String isAsc = "asc"; + + /** åˆ†é¡µå‚æ•°åˆç†åŒ– */ + private Boolean reasonable = true; + + public String getOrderBy() + { + if (StringUtils.isEmpty(orderByColumn)) + { + return ""; + } + return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; + } + + public Integer getPageNum() + { + return pageNum; + } + + public void setPageNum(Integer pageNum) + { + this.pageNum = pageNum; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public String getOrderByColumn() + { + return orderByColumn; + } + + public void setOrderByColumn(String orderByColumn) + { + this.orderByColumn = orderByColumn; + } + + public String getIsAsc() + { + return isAsc; + } + + public void setIsAsc(String isAsc) + { + if (StringUtils.isNotEmpty(isAsc)) + { + // 兼容å‰ç«¯æŽ’åºç±»åž‹ + if ("ascending".equals(isAsc)) + { + isAsc = "asc"; + } + else if ("descending".equals(isAsc)) + { + isAsc = "desc"; + } + this.isAsc = isAsc; + } + } + + public Boolean getReasonable() + { + if (StringUtils.isNull(reasonable)) + { + return Boolean.TRUE; + } + return reasonable; + } + + public void setReasonable(Boolean reasonable) + { + this.reasonable = reasonable; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java new file mode 100644 index 0000000..a3487b8 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java @@ -0,0 +1,85 @@ +package com.ruoyi.common.core.page; + +import java.io.Serializable; +import java.util.List; + +/** + * 表格分页数æ®å¯¹è±¡ + * + * @author ruoyi + */ +public class TableDataInfo implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 总记录数 */ + private long total; + + /** åˆ—è¡¨æ•°æ® */ + private List rows; + + /** 消æ¯çжæ€ç  */ + private int code; + + /** 消æ¯å†…容 */ + private String msg; + + /** + * 表格数æ®å¯¹è±¡ + */ + public TableDataInfo() + { + } + + /** + * 分页 + * + * @param list åˆ—è¡¨æ•°æ® + * @param total 总记录数 + */ + public TableDataInfo(List list, int total) + { + this.rows = list; + this.total = total; + } + + public long getTotal() + { + return total; + } + + public void setTotal(long total) + { + this.total = total; + } + + public List getRows() + { + return rows; + } + + public void setRows(List rows) + { + this.rows = rows; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java new file mode 100644 index 0000000..62ac4f9 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.core.page; + +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 表格数æ®å¤„ç† + * + * @author ruoyi + */ +public class TableSupport +{ + /** + * 当å‰è®°å½•起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * æ¯é¡µæ˜¾ç¤ºè®°å½•æ•° + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排åºåˆ— + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排åºçš„æ–¹å‘ "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * åˆ†é¡µå‚æ•°åˆç†åŒ– + */ + public static final String REASONABLE = "reasonable"; + + /** + * å°è£…分页对象 + */ + public static PageDomain getPageDomain() + { + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1)); + pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10)); + pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); + pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); + pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); + return pageDomain; + } + + public static PageDomain buildPageRequest() + { + return getPageDomain(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java new file mode 100644 index 0000000..d0a6de4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -0,0 +1,268 @@ +package com.ruoyi.common.core.redis; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundSetOperations; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +/** + * spring redis 工具类 + * + * @author ruoyi + **/ +@SuppressWarnings(value = { "unchecked", "rawtypes" }) +@Component +public class RedisCache +{ + @Autowired + public RedisTemplate redisTemplate; + + /** + * 缓存基本的对象,Integerã€Stringã€å®žä½“类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) + { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integerã€Stringã€å®žä½“类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout æ—¶é—´ + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) + { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redisé”® + * @param timeout è¶…æ—¶æ—¶é—´ + * @return true=设置æˆåŠŸï¼›false=设置失败 + */ + public boolean expire(final String key, final long timeout) + { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redisé”® + * @param timeout è¶…æ—¶æ—¶é—´ + * @param unit æ—¶é—´å•ä½ + * @return true=设置æˆåŠŸï¼›false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) + { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * èŽ·å–æœ‰æ•ˆæ—¶é—´ + * + * @param key Redisé”® + * @return 有效时间 + */ + public long getExpire(final String key) + { + return redisTemplate.getExpire(key); + } + + /** + * 判断 key是å¦å­˜åœ¨ + * + * @param key é”® + * @return true 存在 falseä¸å­˜åœ¨ + */ + public Boolean hasKey(String key) + { + return redisTemplate.hasKey(key); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return ç¼“å­˜é”®å€¼å¯¹åº”çš„æ•°æ® + */ + public T getCacheObject(final String key) + { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除å•个对象 + * + * @param key + */ + public boolean deleteObject(final String key) + { + return redisTemplate.delete(key); + } + + /** + * 删除集åˆå¯¹è±¡ + * + * @param collection 多个对象 + * @return + */ + public boolean deleteObject(final Collection collection) + { + return redisTemplate.delete(collection) > 0; + } + + /** + * 缓存Listæ•°æ® + * + * @param key 缓存的键值 + * @param dataList 待缓存的Listæ•°æ® + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) + { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return ç¼“å­˜é”®å€¼å¯¹åº”çš„æ•°æ® + */ + public List getCacheList(final String key) + { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet ç¼“å­˜çš„æ•°æ® + * @return 缓存数æ®çš„对象 + */ + public BoundSetOperations setCacheSet(final String key, final Set dataSet) + { + BoundSetOperations setOperation = redisTemplate.boundSetOps(key); + Iterator it = dataSet.iterator(); + while (it.hasNext()) + { + setOperation.add(it.next()); + } + return setOperation; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) + { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) + { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) + { + return redisTemplate.opsForHash().entries(key); + } + + /** + * å¾€Hashä¸­å­˜å…¥æ•°æ® + * + * @param key Redisé”® + * @param hKey Hashé”® + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) + { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获å–Hashä¸­çš„æ•°æ® + * + * @param key Redisé”® + * @param hKey Hashé”® + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) + { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获å–多个Hashä¸­çš„æ•°æ® + * + * @param key Redisé”® + * @param hKeys Hashé”®é›†åˆ + * @return Hashå¯¹è±¡é›†åˆ + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) + { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 删除Hashä¸­çš„æŸæ¡æ•°æ® + * + * @param key Redisé”® + * @param hKey Hashé”® + * @return æ˜¯å¦æˆåŠŸ + */ + public boolean deleteCacheMapValue(final String key, final String hKey) + { + return redisTemplate.opsForHash().delete(key, hKey) > 0; + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串å‰ç¼€ + * @return 对象列表 + */ + public Collection keys(final String pattern) + { + return redisTemplate.keys(pattern); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java new file mode 100644 index 0000000..4fa575c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java @@ -0,0 +1,86 @@ +package com.ruoyi.common.core.text; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import com.ruoyi.common.utils.StringUtils; + +/** + * 字符集工具类 + * + * @author ruoyi + */ +public class CharsetKit +{ + /** ISO-8859-1 */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** UTF-8 */ + public static final String UTF_8 = "UTF-8"; + /** GBK */ + public static final String GBK = "GBK"; + + /** ISO-8859-1 */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** GBK */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转æ¢ä¸ºCharset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) + { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转æ¢å­—ç¬¦ä¸²çš„å­—ç¬¦é›†ç¼–ç  + * + * @param source 字符串 + * @param srcCharset æºå­—符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转æ¢åŽçš„字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) + { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转æ¢å­—ç¬¦ä¸²çš„å­—ç¬¦é›†ç¼–ç  + * + * @param source 字符串 + * @param srcCharset æºå­—符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转æ¢åŽçš„字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) + { + if (null == srcCharset) + { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) + { + destCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) + { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return ç³»ç»Ÿå­—ç¬¦é›†ç¼–ç  + */ + public static String systemCharset() + { + return Charset.defaultCharset().name(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java new file mode 100644 index 0000000..50d2be0 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java @@ -0,0 +1,1000 @@ +package com.ruoyi.common.core.text; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; +import com.ruoyi.common.utils.StringUtils; +import org.apache.commons.lang3.ArrayUtils; + +/** + * 类型转æ¢å™¨ + * + * @author ruoyi + */ +public class Convert +{ + /** + * 转æ¢ä¸ºå­—符串
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转æ¢ä¸ºå­—符串
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转æ¢ä¸ºå­—符
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转æ¢ä¸ºå­—符
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转æ¢ä¸ºbyte
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºbyte
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转æ¢ä¸ºShort
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºShort
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转æ¢ä¸ºNumber
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºNumber
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转æ¢ä¸ºint
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºint
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转æ¢ä¸ºInteger数组
+ * + * @param str 被转æ¢çš„值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转æ¢ä¸ºLong数组
+ * + * @param str 被转æ¢çš„值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转æ¢ä¸ºInteger数组
+ * + * @param split 分隔符 + * @param split 被转æ¢çš„值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转æ¢ä¸ºLong数组
+ * + * @param split 分隔符 + * @param str 被转æ¢çš„值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转æ¢ä¸ºString数组
+ * + * @param str 被转æ¢çš„值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转æ¢ä¸ºString数组
+ * + * @param split 分隔符 + * @param split 被转æ¢çš„值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转æ¢ä¸ºlong
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支æŒç§‘学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºlong
+ * 如果给定的值为null,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转æ¢ä¸ºdouble
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支æŒç§‘学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºdouble
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转æ¢ä¸ºFloat
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºFloat
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转æ¢ä¸ºboolean
+ * String支æŒçš„值为:trueã€falseã€yesã€okã€no,1,0 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºboolean
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转æ¢ä¸ºEnum对象
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * + * @param clazz Enumçš„Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºEnum对象
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * + * @param clazz Enumçš„Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转æ¢ä¸ºBigInteger
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºBigInteger
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值null
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转æ¢ä¸ºBigDecimal
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @param defaultValue 转æ¢é”™è¯¯æ—¶çš„默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转æ¢ä¸ºBigDecimal
+ * 如果给定的值为空,或者转æ¢å¤±è´¥ï¼Œè¿”回默认值
+ * 转æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™ + * + * @param value 被转æ¢çš„值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1ã€Byte数组和ByteBuffer会被转æ¢ä¸ºå¯¹åº”字符串的数组 2ã€å¯¹è±¡æ•°ç»„会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1ã€Byte数组和ByteBuffer会被转æ¢ä¸ºå¯¹åº”字符串的数组 2ã€å¯¹è±¡æ•°ç»„会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1ã€Byte数组和ByteBuffer会被转æ¢ä¸ºå¯¹åº”字符串的数组 2ã€å¯¹è±¡æ•°ç»„会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[]) + { + return str((byte[]) obj, charset); + } + else if (obj instanceof Byte[]) + { + byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj); + return str(bytes, charset); + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * å°†byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * è§£ç å­—èŠ‚ç  + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解ç çš„结果å–å†³äºŽå¹³å° + * @return è§£ç åŽçš„字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编ç çš„byteBufferæ•°æ®è½¬æ¢ä¸ºå­—符串 + * + * @param data æ•°æ® + * @param charset 字符集,如果为空使用当å‰ç³»ç»Ÿå­—符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编ç çš„byteBufferæ•°æ®è½¬æ¢ä¸ºå­—符串 + * + * @param data æ•°æ® + * @param charset 字符集,如果为空使用当å‰ç³»ç»Ÿå­—符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角åŠè§’è½¬æ¢ + /** + * åŠè§’转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * åŠè§’转全角 + * + * @param input String + * @param notConvertSet 䏿›¿æ¢çš„å­—ç¬¦é›†åˆ + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // è·³è¿‡ä¸æ›¿æ¢çš„字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转åŠè§’ + * + * @param input String. + * @return åŠè§’字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替æ¢å…¨è§’为åŠè§’ + * + * @param text 文本 + * @param notConvertSet 䏿›¿æ¢çš„å­—ç¬¦é›†åˆ + * @return 替æ¢åŽçš„字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // è·³è¿‡ä¸æ›¿æ¢çš„字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金é¢å¤§å†™è½¬æ¢ 先写个完整的然åŽå°†å¦‚é›¶æ‹¾æ›¿æ¢æˆé›¶ + * + * @param n æ•°å­— + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "è§’", "分" }; + String[] digit = { "é›¶", "壹", "è´°", "å", "肆", "ä¼", "陆", "柒", "æŒ", "玖" }; + String[][] unit = { { "å…ƒ", "万", "亿" }, { "", "拾", "ä½°", "仟" } }; + + String head = n < 0 ? "è´Ÿ" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(é›¶.)+", ""); + } + if (s.length() < 1) + { + s = "æ•´"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(é›¶.)*é›¶$", "").replaceAll("^$", "é›¶") + unit[0][i] + s; + } + return head + s.replaceAll("(é›¶.)*é›¶å…ƒ", "å…ƒ").replaceFirst("(é›¶.)+", "").replaceAll("(é›¶.)+", "é›¶").replaceAll("^æ•´$", "零元整"); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java new file mode 100644 index 0000000..dbf3e23 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java @@ -0,0 +1,92 @@ +package com.ruoyi.common.core.text; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 字符串格å¼åŒ– + * + * @author ruoyi + */ +public class StrFormatter +{ + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * æ ¼å¼åŒ–字符串
+ * æ­¤æ–¹æ³•åªæ˜¯ç®€å•å°†å ä½ç¬¦ {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°
+ * 如果想输出 {} 使用 \\转义 { å³å¯ï¼Œå¦‚果想输出 {} 之å‰çš„ \ 使用åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param strPattern å­—ç¬¦ä¸²æ¨¡æ¿ + * @param argArray 傿•°åˆ—表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // åˆå§‹åŒ–定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// å ä½ç¬¦æ‰€åœ¨ä½ç½® + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模æ¿å‰©ä½™éƒ¨åˆ†ä¸å†åŒ…å«å ä½ç¬¦ï¼ŒåŠ å…¥å‰©ä½™éƒ¨åˆ†åŽè¿”回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之å‰è¿˜æœ‰ä¸€ä¸ªè½¬ä¹‰ç¬¦ï¼Œå ä½ç¬¦ä¾æ—§æœ‰æ•ˆ + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // å ä½ç¬¦è¢«è½¬ä¹‰ + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常å ä½ç¬¦ + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // 加入最åŽä¸€ä¸ªå ä½ç¬¦åŽæ‰€æœ‰çš„字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java new file mode 100644 index 0000000..78188fc --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.enums; + +/** + * æ“ä½œçŠ¶æ€ + * + * @author ruoyi + * + */ +public enum BusinessStatus +{ + /** + * æˆåŠŸ + */ + SUCCESS, + + /** + * 失败 + */ + FAIL, +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java new file mode 100644 index 0000000..2bbeaf7 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.enums; + +/** + * 业务æ“作类型 + * + * @author ruoyi + */ +public enum BusinessType +{ + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + + /** + * æŽˆæƒ + */ + GRANT, + + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + + /** + * 强退 + */ + FORCE, + + /** + * 生æˆä»£ç  + */ + GENCODE, + + /** + * æ¸…ç©ºæ•°æ® + */ + CLEAN, +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java new file mode 100644 index 0000000..4b5341d --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.enums; + +/** + * æ•°æ®æº + * + * @author ruoyi + */ +public enum DataSourceType +{ + /** + * 主库 + */ + MASTER, + + /** + * 从库 + */ + SLAVE +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java new file mode 100644 index 0000000..2fa9f86 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java @@ -0,0 +1,36 @@ +package com.ruoyi.common.enums; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.Nullable; + +/** + * è¯·æ±‚æ–¹å¼ + * + * @author ruoyi + */ +public enum HttpMethod +{ + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + + private static final Map mappings = new HashMap<>(16); + + static + { + for (HttpMethod httpMethod : values()) + { + mappings.put(httpMethod.name(), httpMethod); + } + } + + @Nullable + public static HttpMethod resolve(@Nullable String method) + { + return (method != null ? mappings.get(method) : null); + } + + public boolean matches(String method) + { + return (this == resolve(method)); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java new file mode 100644 index 0000000..ad01659 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.enums; + +/** + * 陿µç±»åž‹ + * + * @author ruoyi + */ + +public enum LimitType +{ + /** + * é»˜è®¤ç­–ç•¥å…¨å±€é™æµ + */ + DEFAULT, + + /** + * æ ¹æ®è¯·æ±‚者IPè¿›è¡Œé™æµ + */ + IP +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java new file mode 100644 index 0000000..06532af --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.enums; + +/** + * æ“作人类别 + * + * @author ruoyi + */ +public enum OperatorType +{ + /** + * 其它 + */ + OTHER, + + /** + * åŽå°ç”¨æˆ· + */ + MANAGE, + + /** + * 手机端用户 + */ + MOBILE +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java new file mode 100644 index 0000000..a4613ff --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java @@ -0,0 +1,30 @@ +package com.ruoyi.common.enums; + +/** + * ç”¨æˆ·çŠ¶æ€ + * + * @author ruoyi + */ +public enum UserStatus +{ + OK("0", "正常"), DISABLE("1", "åœç”¨"), DELETED("2", "删除"); + + private final String code; + private final String info; + + UserStatus(String code, String info) + { + this.code = code; + this.info = info; + } + + public String getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java new file mode 100644 index 0000000..d96c7ba --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java @@ -0,0 +1,43 @@ +package com.ruoyi.common.exception; + +/** + * 自定义异常 + * + * @author ruoyi + */ +public class CustomException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + private Integer code; + + private String message; + + public CustomException(String message) + { + this.message = message; + } + + public CustomException(String message, Integer code) + { + this.message = message; + this.code = code; + } + + public CustomException(String message, Throwable e) + { + super(message, e); + this.message = message; + } + + @Override + public String getMessage() + { + return message; + } + + public Integer getCode() + { + return code; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java new file mode 100644 index 0000000..57bffc4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java @@ -0,0 +1,15 @@ +package com.ruoyi.common.exception; + +/** + * 演示模å¼å¼‚常 + * + * @author ruoyi + */ +public class DemoModeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public DemoModeException() + { + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java new file mode 100644 index 0000000..9f0dec4 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java @@ -0,0 +1,58 @@ +package com.ruoyi.common.exception; + +/** + * 全局异常 + * + * @author ruoyi + */ +public class GlobalException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 错误æç¤º + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * å’Œ {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,é¿å…ååºåˆ—化问题 + */ + public GlobalException() + { + } + + public GlobalException(String message) + { + this.message = message; + } + + public String getDetailMessage() + { + return detailMessage; + } + + public GlobalException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() + { + return message; + } + + public GlobalException setMessage(String message) + { + this.message = message; + return this; + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java new file mode 100644 index 0000000..a9247b5 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java @@ -0,0 +1,74 @@ +package com.ruoyi.common.exception; + +/** + * 业务异常 + * + * @author ruoyi + */ +public final class ServiceException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * é”™è¯¯ç  + */ + private Integer code; + + /** + * 错误æç¤º + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * å’Œ {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,é¿å…ååºåˆ—化问题 + */ + public ServiceException() + { + } + + public ServiceException(String message) + { + this.message = message; + } + + public ServiceException(String message, Integer code) + { + this.message = message; + this.code = code; + } + + public String getDetailMessage() + { + return detailMessage; + } + + @Override + public String getMessage() + { + return message; + } + + public Integer getCode() + { + return code; + } + + public ServiceException setMessage(String message) + { + this.message = message; + return this; + } + + public ServiceException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java new file mode 100644 index 0000000..a544fb6 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.exception; + +/** + * 工具类异常 + * + * @author ruoyi + */ +public class UtilException extends RuntimeException +{ + private static final long serialVersionUID = 8247610319171014183L; + + public UtilException(Throwable e) + { + super(e.getMessage(), e); + } + + public UtilException(String message) + { + super(message); + } + + public UtilException(String message, Throwable throwable) + { + super(message, throwable); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java new file mode 100644 index 0000000..3dd2c1e --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java @@ -0,0 +1,97 @@ +package com.ruoyi.common.exception.base; + +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * 基础异常 + * + * @author ruoyi + */ +public class BaseException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * æ‰€å±žæ¨¡å— + */ + private String module; + + /** + * é”™è¯¯ç  + */ + private String code; + + /** + * 错误ç å¯¹åº”çš„å‚æ•° + */ + private Object[] args; + + /** + * é”™è¯¯æ¶ˆæ¯ + */ + private String defaultMessage; + + public BaseException(String module, String code, Object[] args, String defaultMessage) + { + this.module = module; + this.code = code; + this.args = args; + this.defaultMessage = defaultMessage; + } + + public BaseException(String module, String code, Object[] args) + { + this(module, code, args, null); + } + + public BaseException(String module, String defaultMessage) + { + this(module, null, null, defaultMessage); + } + + public BaseException(String code, Object[] args) + { + this(null, code, args, null); + } + + public BaseException(String defaultMessage) + { + this(null, null, null, defaultMessage); + } + + @Override + public String getMessage() + { + String message = null; + if (!StringUtils.isEmpty(code)) + { + message = MessageUtils.message(code, args); + } + if (message == null) + { + message = defaultMessage; + } + return message; + } + + public String getModule() + { + return module; + } + + public String getCode() + { + return code; + } + + public Object[] getArgs() + { + return args; + } + + public String getDefaultMessage() + { + return defaultMessage; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java new file mode 100644 index 0000000..ed14af1 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.exception.file; + +import com.ruoyi.common.exception.base.BaseException; + +/** + * 文件信æ¯å¼‚常类 + * + * @author ruoyi + */ +public class FileException extends BaseException +{ + private static final long serialVersionUID = 1L; + + public FileException(String code, Object[] args) + { + super("file", code, args, null); + } + +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java new file mode 100644 index 0000000..44941b8 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.file; + +/** + * 文件åç§°è¶…é•¿é™åˆ¶å¼‚常类 + * + * @author ruoyi + */ +public class FileNameLengthLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileNameLengthLimitExceededException(int defaultFileNameLength) + { + super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java new file mode 100644 index 0000000..f855e72 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.file; + +/** + * 文件å大å°é™åˆ¶å¼‚常类 + * + * @author ruoyi + */ +public class FileSizeLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileSizeLimitExceededException(long defaultMaxSize) + { + super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java new file mode 100644 index 0000000..f45e7ef --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java @@ -0,0 +1,61 @@ +package com.ruoyi.common.exception.file; + +import java.io.PrintStream; +import java.io.PrintWriter; + +/** + * 文件上传异常类 + * + * @author ruoyi + */ +public class FileUploadException extends Exception +{ + + private static final long serialVersionUID = 1L; + + private final Throwable cause; + + public FileUploadException() + { + this(null, null); + } + + public FileUploadException(final String msg) + { + this(msg, null); + } + + public FileUploadException(String msg, Throwable cause) + { + super(msg); + this.cause = cause; + } + + @Override + public void printStackTrace(PrintStream stream) + { + super.printStackTrace(stream); + if (cause != null) + { + stream.println("Caused by:"); + cause.printStackTrace(stream); + } + } + + @Override + public void printStackTrace(PrintWriter writer) + { + super.printStackTrace(writer); + if (cause != null) + { + writer.println("Caused by:"); + cause.printStackTrace(writer); + } + } + + @Override + public Throwable getCause() + { + return cause; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java new file mode 100644 index 0000000..f3e9c33 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java @@ -0,0 +1,80 @@ +package com.ruoyi.common.exception.file; + +import java.util.Arrays; + +/** + * 文件上传 误异常类 + * + * @author ruoyi + */ +public class InvalidExtensionException extends FileUploadException +{ + private static final long serialVersionUID = 1L; + + private String[] allowedExtension; + private String extension; + private String filename; + + public InvalidExtensionException(String[] allowedExtension, String extension, String filename) + { + super("文件[" + filename + "]åŽç¼€[" + extension + "]䏿­£ç¡®ï¼Œè¯·ä¸Šä¼ " + Arrays.toString(allowedExtension) + "æ ¼å¼"); + this.allowedExtension = allowedExtension; + this.extension = extension; + this.filename = filename; + } + + public String[] getAllowedExtension() + { + return allowedExtension; + } + + public String getExtension() + { + return extension; + } + + public String getFilename() + { + return filename; + } + + public static class InvalidImageExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidFlashExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidMediaExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidVideoExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java new file mode 100644 index 0000000..14b2361 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.exception.job; + +/** + * 计划策略异常 + * + * @author ruoyi + */ +public class TaskException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Code code; + + public TaskException(String msg, Code code) + { + this(msg, code, null); + } + + public TaskException(String msg, Code code, Exception nestedEx) + { + super(msg, nestedEx); + this.code = code; + } + + public Code getCode() + { + return code; + } + + public enum Code + { + TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java new file mode 100644 index 0000000..2bf5038 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 黑åå•IP异常类 + * + * @author ruoyi + */ +public class BlackListException extends UserException +{ + private static final long serialVersionUID = 1L; + + public BlackListException() + { + super("login.blocked", null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java new file mode 100644 index 0000000..e3334ae --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 验è¯ç é”™è¯¯å¼‚常类 + * + * @author ruoyi + */ +public class CaptchaException extends UserException +{ + private static final long serialVersionUID = 1L; + + public CaptchaException() + { + super("user.jcaptcha.error", null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java new file mode 100644 index 0000000..5e6fd0f --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 验è¯ç å¤±æ•ˆå¼‚常类 + * + * @author ruoyi + */ +public class CaptchaExpireException extends UserException +{ + private static final long serialVersionUID = 1L; + + public CaptchaExpireException() + { + super("user.jcaptcha.expire", null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java new file mode 100644 index 0000000..79160d8 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.exception.user; + +import com.ruoyi.common.exception.base.BaseException; + +/** + * 用户信æ¯å¼‚常类 + * + * @author ruoyi + */ +public class UserException extends BaseException +{ + private static final long serialVersionUID = 1L; + + public UserException(String code, Object[] args) + { + super("user", code, args, null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java new file mode 100644 index 0000000..eff8181 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户ä¸å­˜åœ¨å¼‚常类 + * + * @author ruoyi + */ +public class UserNotExistsException extends UserException +{ + private static final long serialVersionUID = 1L; + + public UserNotExistsException() + { + super("user.not.exists", null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java new file mode 100644 index 0000000..71449e2 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户密ç ä¸æ­£ç¡®æˆ–ä¸ç¬¦åˆè§„范异常类 + * + * @author ruoyi + */ +public class UserPasswordNotMatchException extends UserException +{ + private static final long serialVersionUID = 1L; + + public UserPasswordNotMatchException() + { + super("user.password.not.match", null); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java new file mode 100644 index 0000000..0de8d24 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户错误最大次数异常类 + * + * @author ruoyi + */ +public class UserPasswordRetryLimitExceedException extends UserException +{ + private static final long serialVersionUID = 1L; + + public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) + { + super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime }); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java new file mode 100644 index 0000000..4cde4a9 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.filter; + +import com.alibaba.fastjson2.filter.SimplePropertyPreFilter; + +/** + * 排除JSONæ•æ„Ÿå±žæ€§ + * + * @author ruoyi + */ +public class PropertyPreExcludeFilter extends SimplePropertyPreFilter +{ + public PropertyPreExcludeFilter() + { + } + + public PropertyPreExcludeFilter addExcludes(String... filters) + { + for (int i = 0; i < filters.length; i++) + { + this.getExcludes().add(filters[i]); + } + return this; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java new file mode 100644 index 0000000..3946d48 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java @@ -0,0 +1,52 @@ +package com.ruoyi.common.filter; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.MediaType; +import com.ruoyi.common.utils.StringUtils; + +/** + * Repeatable 过滤器 + * + * @author ruoyi + */ +public class RepeatableFilter implements Filter +{ + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest + && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) + { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) + { + chain.doFilter(request, response); + } + else + { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() + { + + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java new file mode 100644 index 0000000..ca822ed --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java @@ -0,0 +1,76 @@ +package com.ruoyi.common.filter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import com.ruoyi.common.utils.http.HttpHelper; +import com.ruoyi.common.constant.Constants; + +/** + * 构建å¯é‡å¤è¯»å–inputStreamçš„request + * + * @author ruoyi + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper +{ + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException + { + super(request); + request.setCharacterEncoding(Constants.UTF8); + response.setCharacterEncoding(Constants.UTF8); + + body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8); + } + + @Override + public BufferedReader getReader() throws IOException + { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + return new ServletInputStream() + { + @Override + public int read() throws IOException + { + return bais.read(); + } + + @Override + public int available() throws IOException + { + return body.length; + } + + @Override + public boolean isFinished() + { + return false; + } + + @Override + public boolean isReady() + { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) + { + + } + }; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java new file mode 100644 index 0000000..23a76fe --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java @@ -0,0 +1,75 @@ +package com.ruoyi.common.filter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.enums.HttpMethod; + +/** + * 防止XSS攻击的过滤器 + * + * @author ruoyi + */ +public class XssFilter implements Filter +{ + /** + * 排除链接 + */ + public List excludes = new ArrayList<>(); + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + String tempExcludes = filterConfig.getInitParameter("excludes"); + if (StringUtils.isNotEmpty(tempExcludes)) + { + String[] url = tempExcludes.split(","); + for (int i = 0; url != null && i < url.length; i++) + { + excludes.add(url[i]); + } + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeURL(req, resp)) + { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) + { + String url = request.getServletPath(); + String method = request.getMethod(); + // GET DELETE ä¸è¿‡æ»¤ + if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) + { + return true; + } + return StringUtils.matches(url, excludes); + } + + @Override + public void destroy() + { + + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..e0cc40a --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,111 @@ +package com.ruoyi.common.filter; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import org.apache.commons.io.IOUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.html.EscapeUtil; + +/** + * XSSè¿‡æ»¤å¤„ç† + * + * @author ruoyi + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper +{ + /** + * @param request + */ + public XssHttpServletRequestWrapper(HttpServletRequest request) + { + super(request); + } + + @Override + public String[] getParameterValues(String name) + { + String[] values = super.getParameterValues(name); + if (values != null) + { + int length = values.length; + String[] escapesValues = new String[length]; + for (int i = 0; i < length; i++) + { + // 防xss攻击和过滤å‰åŽç©ºæ ¼ + escapesValues[i] = EscapeUtil.clean(values[i]).trim(); + } + return escapesValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + // éžjson类型,直接返回 + if (!isJsonRequest()) + { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = IOUtils.toString(super.getInputStream(), "utf-8"); + if (StringUtils.isEmpty(json)) + { + return super.getInputStream(); + } + + // xss过滤 + json = EscapeUtil.clean(json).trim(); + byte[] jsonBytes = json.getBytes("utf-8"); + final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes); + return new ServletInputStream() + { + @Override + public boolean isFinished() + { + return true; + } + + @Override + public boolean isReady() + { + return true; + } + + @Override + public int available() throws IOException + { + return jsonBytes.length; + } + + @Override + public void setReadListener(ReadListener readListener) + { + } + + @Override + public int read() throws IOException + { + return bis.read(); + } + }; + } + + /** + * æ˜¯å¦æ˜¯Json请求 + * + * @param request + */ + public boolean isJsonRequest() + { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java new file mode 100644 index 0000000..b6326c2 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java @@ -0,0 +1,114 @@ +package com.ruoyi.common.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 精确的浮点数è¿ç®— + * + * @author ruoyi + */ +public class Arith +{ + + /** 默认除法è¿ç®—精度 */ + private static final int DEF_DIV_SCALE = 10; + + /** 这个类ä¸èƒ½å®žä¾‹åŒ– */ + private Arith() + { + } + + /** + * æä¾›ç²¾ç¡®çš„加法è¿ç®—。 + * @param v1 被加数 + * @param v2 加数 + * @return ä¸¤ä¸ªå‚æ•°çš„å’Œ + */ + public static double add(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).doubleValue(); + } + + /** + * æä¾›ç²¾ç¡®çš„凿³•è¿ç®—。 + * @param v1 è¢«å‡æ•° + * @param v2 凿•° + * @return ä¸¤ä¸ªå‚æ•°çš„å·® + */ + public static double sub(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * æä¾›ç²¾ç¡®çš„乘法è¿ç®—。 + * @param v1 被乘数 + * @param v2 乘数 + * @return ä¸¤ä¸ªå‚æ•°çš„积 + */ + public static double mul(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法è¿ç®—,当å‘生除ä¸å°½çš„æƒ…况时,精确到 + * å°æ•°ç‚¹ä»¥åŽ10ä½ï¼Œä»¥åŽçš„æ•°å­—å››èˆäº”入。 + * @param v1 被除数 + * @param v2 除数 + * @return ä¸¤ä¸ªå‚æ•°çš„商 + */ + public static double div(double v1, double v2) + { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法è¿ç®—。当å‘生除ä¸å°½çš„æƒ…况时,由scale傿•°æŒ‡ + * 定精度,以åŽçš„æ•°å­—å››èˆäº”入。 + * @param v1 被除数 + * @param v2 除数 + * @param scale 表示表示需è¦ç²¾ç¡®åˆ°å°æ•°ç‚¹ä»¥åŽå‡ ä½ã€‚ + * @return ä¸¤ä¸ªå‚æ•°çš„商 + */ + public static double div(double v1, double v2, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + if (b1.compareTo(BigDecimal.ZERO) == 0) + { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * æä¾›ç²¾ç¡®çš„å°æ•°ä½å››èˆäº”入处ç†ã€‚ + * @param v 需è¦å››èˆäº”入的数字 + * @param scale å°æ•°ç‚¹åŽä¿ç•™å‡ ä½ + * @return å››èˆäº”å…¥åŽçš„结果 + */ + public static double round(double v, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(Double.toString(v)); + BigDecimal one = BigDecimal.ONE; + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java new file mode 100644 index 0000000..04c87d8 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -0,0 +1,191 @@ +package com.ruoyi.common.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间工具类 + * + * @author ruoyi + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils +{ + public static String YYYY = "yyyy"; + + public static String YYYY_MM = "yyyy-MM"; + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获å–当å‰Date型日期 + * + * @return Date() 当剿—¥æœŸ + */ + public static Date getNowDate() + { + return new Date(); + } + + /** + * 获å–当剿—¥æœŸ, 默认格å¼ä¸ºyyyy-MM-dd + * + * @return String + */ + public static String getDate() + { + return dateTimeNow(YYYY_MM_DD); + } + + public static final String getTime() + { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static final String dateTimeNow() + { + return dateTimeNow(YYYYMMDDHHMMSS); + } + + public static final String dateTimeNow(final String format) + { + return parseDateToStr(format, new Date()); + } + + public static final String dateTime(final Date date) + { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static final String parseDateToStr(final String format, final Date date) + { + return new SimpleDateFormat(format).format(date); + } + + public static final Date dateTime(final String format, final String ts) + { + try + { + return new SimpleDateFormat(format).parse(ts); + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 å³å¹´/月/æ—¥ 如2018/08/08 + */ + public static final String datePath() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 å³å¹´/月/æ—¥ 如20180808 + */ + public static final String dateTime() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 æ ¼å¼ + */ + public static Date parseDate(Object str) + { + if (str == null) + { + return null; + } + try + { + return parseDate(str.toString(), parsePatterns); + } + catch (ParseException e) + { + return null; + } + } + + /** + * èŽ·å–æœåС噍å¯åŠ¨æ—¶é—´ + */ + public static Date getServerStartDate() + { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算相差天数 + */ + public static int differentDaysByMillisecond(Date date1, Date date2) + { + return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); + } + + /** + * 计算时间差 + * + * @param endTime æœ€åŽæ—¶é—´ + * @param startTime 开始时间 + * @return 时间差(天/å°æ—¶/分钟) + */ + public static String timeDistance(Date endDate, Date startTime) + { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - startTime.getTime(); + // 计算差多少天 + long day = diff / nd; + // è®¡ç®—å·®å¤šå°‘å°æ—¶ + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "å°æ—¶" + min + "分钟"; + } + + /** + * 增加 LocalDateTime ==> Date + */ + public static Date toDate(LocalDateTime temporalAccessor) + { + ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } + + /** + * 增加 LocalDate ==> Date + */ + public static Date toDate(LocalDate temporalAccessor) + { + LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); + ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java new file mode 100644 index 0000000..39ad84a --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -0,0 +1,186 @@ +package com.ruoyi.common.utils; + +import java.util.Collection; +import java.util.List; +import com.alibaba.fastjson2.JSONArray; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 字典工具类 + * + * @author ruoyi + */ +public class DictUtils +{ + /** + * 分隔符 + */ + public static final String SEPARATOR = ","; + + /** + * 设置字典缓存 + * + * @param key 傿•°é”® + * @param dictDatas 字典数æ®åˆ—表 + */ + public static void setDictCache(String key, List dictDatas) + { + SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); + } + + /** + * 获å–字典缓存 + * + * @param key 傿•°é”® + * @return dictDatas 字典数æ®åˆ—表 + */ + public static List getDictCache(String key) + { + JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + if (StringUtils.isNotNull(arrayCache)) + { + return arrayCache.toList(SysDictData.class); + } + return null; + } + + /** + * æ ¹æ®å­—典类型和字典值获å–字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue) + { + return getDictLabel(dictType, dictValue, SEPARATOR); + } + + /** + * æ ¹æ®å­—典类型和字典标签获å–字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel) + { + return getDictValue(dictType, dictLabel, SEPARATOR); + } + + /** + * æ ¹æ®å­—典类型和字典值获å–字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.isNotNull(datas)) + { + if (StringUtils.containsAny(separator, dictValue)) + { + for (SysDictData dict : datas) + { + for (String value : dictValue.split(separator)) + { + if (value.equals(dict.getDictValue())) + { + propertyString.append(dict.getDictLabel()).append(separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictValue.equals(dict.getDictValue())) + { + return dict.getDictLabel(); + } + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * æ ¹æ®å­—典类型和字典标签获å–字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) + { + for (SysDictData dict : datas) + { + for (String label : dictLabel.split(separator)) + { + if (label.equals(dict.getDictLabel())) + { + propertyString.append(dict.getDictValue()).append(separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictLabel.equals(dict.getDictLabel())) + { + return dict.getDictValue(); + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 删除指定字典缓存 + * + * @param key 字典键 + */ + public static void removeDictCache(String key) + { + SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); + } + + /** + * 清空字典缓存 + */ + public static void clearDictCache() + { + Collection keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*"); + SpringUtils.getBean(RedisCache.class).deleteObject(keys); + } + + /** + * 设置cache key + * + * @param configKey 傿•°é”® + * @return 缓存键key + */ + public static String getCacheKey(String configKey) + { + return CacheConstants.SYS_DICT_KEY + configKey; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java new file mode 100644 index 0000000..50b10fe --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java @@ -0,0 +1,39 @@ +package com.ruoyi.common.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.commons.lang3.exception.ExceptionUtils; + +/** + * 错误信æ¯å¤„ç†ç±»ã€‚ + * + * @author ruoyi + */ +public class ExceptionUtil +{ + /** + * 获å–exception的详细错误信æ¯ã€‚ + */ + public static String getExceptionMessage(Throwable e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + return sw.toString(); + } + + public static String getRootErrorMessage(Exception e) + { + Throwable root = ExceptionUtils.getRootCause(e); + root = (root == null ? e : root); + if (root == null) + { + return ""; + } + String msg = root.getMessage(); + if (msg == null) + { + return "null"; + } + return StringUtils.defaultString(msg); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java new file mode 100644 index 0000000..e415c9c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.utils; + +/** + * 处ç†å¹¶è®°å½•日志文件 + * + * @author ruoyi + */ +public class LogUtils +{ + public static String getBlock(Object msg) + { + if (msg == null) + { + msg = ""; + } + return "[" + msg.toString() + "]"; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java new file mode 100644 index 0000000..5f2d9ea --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.utils; + +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 获å–i18nèµ„æºæ–‡ä»¶ + * + * @author ruoyi + */ +public class MessageUtils +{ + /** + * æ ¹æ®æ¶ˆæ¯é”®å’Œå‚æ•° èŽ·å–æ¶ˆæ¯ 委托给spring messageSource + * + * @param code 消æ¯é”® + * @param args 傿•° + * @return 获å–国际化翻译值 + */ + public static String message(String code, Object... args) + { + MessageSource messageSource = SpringUtils.getBean(MessageSource.class); + return messageSource.getMessage(code, args, LocaleContextHolder.getLocale()); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java new file mode 100644 index 0000000..70e9b08 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.utils; + +import com.github.pagehelper.PageHelper; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableSupport; +import com.ruoyi.common.utils.sql.SqlUtil; + +/** + * 分页工具类 + * + * @author ruoyi + */ +public class PageUtils extends PageHelper +{ + /** + * è®¾ç½®è¯·æ±‚åˆ†é¡µæ•°æ® + */ + public static void startPage() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + Boolean reasonable = pageDomain.getReasonable(); + PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); + } + + /** + * 清ç†åˆ†é¡µçš„线程å˜é‡ + */ + public static void clearPage() + { + PageHelper.clearPage(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java new file mode 100644 index 0000000..96e437b --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java @@ -0,0 +1,120 @@ +package com.ruoyi.common.utils; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.exception.ServiceException; + +/** + * 安全æœåŠ¡å·¥å…·ç±» + * + * @author ruoyi + */ +public class SecurityUtils +{ + /** + * 用户ID + **/ + public static Long getUserId() + { + try + { + return getLoginUser().getUserId(); + } + catch (Exception e) + { + throw new ServiceException("获å–用户ID异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获å–部门ID + **/ + public static Long getDeptId() + { + try + { + return getLoginUser().getDeptId(); + } + catch (Exception e) + { + throw new ServiceException("获å–部门ID异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获å–用户账户 + **/ + public static String getUsername() + { + try + { + return getLoginUser().getUsername(); + } + catch (Exception e) + { + throw new ServiceException("获å–用户账户异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获å–用户 + **/ + public static LoginUser getLoginUser() + { + try + { + return (LoginUser) getAuthentication().getPrincipal(); + } + catch (Exception e) + { + throw new ServiceException("获å–用户信æ¯å¼‚常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获å–Authentication + */ + public static Authentication getAuthentication() + { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 生æˆBCryptPasswordEncoderå¯†ç  + * + * @param password å¯†ç  + * @return 加密字符串 + */ + public static String encryptPassword(String password) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + /** + * åˆ¤æ–­å¯†ç æ˜¯å¦ç›¸åŒ + * + * @param rawPassword çœŸå®žå¯†ç  + * @param encodedPassword 加密åŽå­—符 + * @return 结果 + */ + public static boolean matchesPassword(String rawPassword, String encodedPassword) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 是å¦ä¸ºç®¡ç†å‘˜ + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java new file mode 100644 index 0000000..292b8da --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java @@ -0,0 +1,218 @@ +package com.ruoyi.common.utils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.text.Convert; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +public class ServletUtils +{ + /** + * 获å–String傿•° + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获å–String傿•° + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获å–Integer傿•° + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获å–Integer傿•° + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获å–Boolean傿•° + */ + public static Boolean getParameterToBool(String name) + { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获å–Boolean傿•° + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) + { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * èŽ·å¾—æ‰€æœ‰è¯·æ±‚å‚æ•° + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParams(ServletRequest request) + { + final Map map = request.getParameterMap(); + return Collections.unmodifiableMap(map); + } + + /** + * èŽ·å¾—æ‰€æœ‰è¯·æ±‚å‚æ•° + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParamMap(ServletRequest request) + { + Map params = new HashMap<>(); + for (Map.Entry entry : getParams(request).entrySet()) + { + params.put(entry.getKey(), StringUtils.join(entry.getValue(), ",")); + } + return params; + } + + /** + * 获å–request + */ + public static HttpServletRequest getRequest() + { + return getRequestAttributes().getRequest(); + } + + /** + * 获å–response + */ + public static HttpServletResponse getResponse() + { + return getRequestAttributes().getResponse(); + } + + /** + * 获å–session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) + { + try + { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + /** + * æ˜¯å¦æ˜¯Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + String accept = request.getHeader("accept"); + if (accept != null && accept.contains("application/json")) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + return StringUtils.inStringIgnoreCase(ajax, "json", "xml"); + } + + /** + * å†…å®¹ç¼–ç  + * + * @param str 内容 + * @return ç¼–ç åŽçš„内容 + */ + public static String urlEncode(String str) + { + try + { + return URLEncoder.encode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } + + /** + * å†…å®¹è§£ç  + * + * @param str 内容 + * @return è§£ç åŽçš„内容 + */ + public static String urlDecode(String str) + { + try + { + return URLDecoder.decode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java new file mode 100644 index 0000000..aa34b03 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java @@ -0,0 +1,614 @@ +package com.ruoyi.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.springframework.util.AntPathMatcher; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.text.StrFormatter; + +/** + * 字符串工具类 + * + * @author ruoyi + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** + * 获å–傿•°ä¸ä¸ºç©ºå€¼ + * + * @param value defaultValue è¦åˆ¤æ–­çš„value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是å¦ä¸ºç©ºï¼Œ 包å«List,Set,Queue + * + * @param coll è¦åˆ¤æ–­çš„Collection + * @return true:为空 false:éžç©º + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是å¦éžç©ºï¼ŒåŒ…å«List,Set,Queue + * + * @param coll è¦åˆ¤æ–­çš„Collection + * @return true:éžç©º false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是å¦ä¸ºç©º + * + * @param objects è¦åˆ¤æ–­çš„对象数组 + ** @return true:为空 false:éžç©º + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是å¦éžç©º + * + * @param objects è¦åˆ¤æ–­çš„对象数组 + * @return true:éžç©º false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是å¦ä¸ºç©º + * + * @param map è¦åˆ¤æ–­çš„Map + * @return true:为空 false:éžç©º + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是å¦ä¸ºç©º + * + * @param map è¦åˆ¤æ–­çš„Map + * @return true:éžç©º false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是å¦ä¸ºç©ºä¸² + * + * @param str String + * @return true:为空 false:éžç©º + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是å¦ä¸ºéžç©ºä¸² + * + * @param str String + * @return true:éžç©ºä¸² false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是å¦ä¸ºç©º + * + * @param object Object + * @return true:为空 false:éžç©º + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是å¦éžç©º + * + * @param object Object + * @return true:éžç©º false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦æ˜¯æ•°ç»„类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 falseï¼šä¸æ˜¯æ•°ç»„ + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截å–字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截å–字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end ç»“æŸ + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * æ ¼å¼åŒ–文本, {} 表示å ä½ç¬¦
+ * æ­¤æ–¹æ³•åªæ˜¯ç®€å•å°†å ä½ç¬¦ {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°
+ * 如果想输出 {} 使用 \\转义 { å³å¯ï¼Œå¦‚果想输出 {} 之å‰çš„ \ 使用åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模æ¿ï¼Œè¢«æ›¿æ¢çš„部分用 {} 表示 + * @param params 傿•°å€¼ + * @return æ ¼å¼åŒ–åŽçš„æ–‡æœ¬ + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 是å¦ä¸ºhttp(s)://开头 + * + * @param link 链接 + * @return 结果 + */ + public static boolean ishttp(String link) + { + return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return seté›†åˆ + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return listé›†åˆ + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtils.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtils.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtils.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 判断给定的collection列表中是å¦åŒ…嫿•°ç»„array 判断给定的数组array中是å¦åŒ…å«ç»™å®šçš„元素value + * + * @param collection ç»™å®šçš„é›†åˆ + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 查找指定字符串是å¦åŒ…嫿Œ‡å®šå­—符串列表中的任æ„ä¸€ä¸ªå­—ç¬¦ä¸²åŒæ—¶ä¸²å¿½ç•¥å¤§å°å†™ + * + * @param cs 指定字符串 + * @param searchCharSequences éœ€è¦æ£€æŸ¥çš„字符串数组 + * @return 是å¦åŒ…å«ä»»æ„一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) + { + if (isEmpty(cs) || isEmpty(searchCharSequences)) + { + return false; + } + for (CharSequence testStr : searchCharSequences) + { + if (containsIgnoreCase(cs, testStr)) + { + return true; + } + } + return false; + } + + /** + * 驼峰转下划线命å + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // å‰ç½®å­—符是å¦å¤§å†™ + boolean preCharIsUpperCase = true; + // 当å‰å­—符是å¦å¤§å†™ + boolean curreCharIsUpperCase = true; + // 下一字符是å¦å¤§å†™ + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是å¦åŒ…å«å­—符串 + * + * @param str 验è¯å­—符串 + * @param strs 字符串组 + * @return 包å«è¿”回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方å¼å‘½å的字符串转æ¢ä¸ºé©¼å³°å¼ã€‚如果转æ¢å‰çš„下划线大写方å¼å‘½å的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转æ¢å‰çš„下划线大写方å¼å‘½å的字符串 + * @return 转æ¢åŽçš„驼峰å¼å‘½å的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必è¦è½¬æ¢ + return ""; + } + else if (!name.contains("_")) + { + // ä¸å«ä¸‹åˆ’线,仅将首字æ¯å¤§å†™ + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头ã€ç»“尾的下æ¢çº¿æˆ–åŒé‡ä¸‹åˆ’线 + if (camel.isEmpty()) + { + continue; + } + // 首字æ¯å¤§å†™ + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰å¼å‘½å法 + * 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是å¦åŒ¹é…指定字符串列表中的任æ„一个字符串 + * + * @param str 指定字符串 + * @param strs éœ€è¦æ£€æŸ¥çš„字符串数组 + * @return 是å¦åŒ¹é… + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是å¦ä¸Žè§„则é…ç½®: + * ? 表示å•个字符; + * * 表示一层路径内的任æ„字符串,ä¸å¯è·¨å±‚级; + * ** 表示任æ„层路径; + * + * @param pattern 匹é…规则 + * @param url 需è¦åŒ¹é…çš„url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补é½0,使之达到指定长度。注æ„,如果数字转æ¢ä¸ºå­—符串åŽï¼Œé•¿åº¦å¤§äºŽsize,则åªä¿ç•™ 最åŽsize个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格å¼ï¼Œè¯¥å­—符串为指定长度。 + */ + public static final String padl(final Number num, final int size) + { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补é½ã€‚如果原始字符串s长度大于size,则åªä¿ç•™æœ€åŽsize个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补é½çš„字符 + * @return è¿”å›žæŒ‡å®šé•¿åº¦çš„å­—ç¬¦ä¸²ï¼Œç”±åŽŸå­—ç¬¦ä¸²å·¦è¡¥é½æˆ–截å–得到。 + */ + public static final String padl(final String s, final int size, final char c) + { + final StringBuilder sb = new StringBuilder(size); + if (s != null) + { + final int len = s.length(); + if (s.length() <= size) + { + for (int i = size - len; i > 0; i--) + { + sb.append(c); + } + sb.append(s); + } + else + { + return s.substring(len - size, len); + } + } + else + { + for (int i = size; i > 0; i--) + { + sb.append(c); + } + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java new file mode 100644 index 0000000..f349352 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java @@ -0,0 +1,99 @@ +package com.ruoyi.common.utils; + +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 线程相关工具类. + * + * @author ruoyi + */ +public class Threads +{ + private static final Logger logger = LoggerFactory.getLogger(Threads.class); + + /** + * sleep等待,å•ä½ä¸ºæ¯«ç§’ + */ + public static void sleep(long milliseconds) + { + try + { + Thread.sleep(milliseconds); + } + catch (InterruptedException e) + { + return; + } + } + + /** + * åœæ­¢çº¿ç¨‹æ±  + * 先使用shutdown, åœæ­¢æŽ¥æ”¶æ–°ä»»åС并å°è¯•å®Œæˆæ‰€æœ‰å·²å­˜åœ¨ä»»åŠ¡. + * 如果超时, 则调用shutdownNow, å–æ¶ˆåœ¨workQueue中Pending的任务,并中断所有阻塞函数. + * 如果ä»ç„¶è¶…時,則強制退出. + * å¦å¯¹åœ¨shutdown时线程本身被调用中断åšäº†å¤„ç†. + */ + public static void shutdownAndAwaitTermination(ExecutorService pool) + { + if (pool != null && !pool.isShutdown()) + { + pool.shutdown(); + try + { + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + pool.shutdownNow(); + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + logger.info("Pool did not terminate"); + } + } + } + catch (InterruptedException ie) + { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + /** + * 打å°çº¿ç¨‹å¼‚å¸¸ä¿¡æ¯ + */ + public static void printException(Runnable r, Throwable t) + { + if (t == null && r instanceof Future) + { + try + { + Future future = (Future) r; + if (future.isDone()) + { + future.get(); + } + } + catch (CancellationException ce) + { + t = ce; + } + catch (ExecutionException ee) + { + t = ee.getCause(); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + } + if (t != null) + { + logger.error(t.getMessage(), t); + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java new file mode 100644 index 0000000..51cdc2f --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java @@ -0,0 +1,110 @@ +package com.ruoyi.common.utils.bean; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Bean 工具类 + * + * @author ruoyi + */ +public class BeanUtils extends org.springframework.beans.BeanUtils +{ + /** Bean方法å中属性å开始的下标 */ + private static final int BEAN_METHOD_PROP_INDEX = 3; + + /** * 匹é…getteræ–¹æ³•çš„æ­£åˆ™è¡¨è¾¾å¼ */ + private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); + + /** * 匹é…setteræ–¹æ³•çš„æ­£åˆ™è¡¨è¾¾å¼ */ + private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); + + /** + * Bean属性å¤åˆ¶å·¥å…·æ–¹æ³•。 + * + * @param dest 目标对象 + * @param src æºå¯¹è±¡ + */ + public static void copyBeanProp(Object dest, Object src) + { + try + { + copyProperties(src, dest); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * 获å–对象的setter方法。 + * + * @param obj 对象 + * @return 对象的setter方法列表 + */ + public static List getSetterMethods(Object obj) + { + // setter方法列表 + List setterMethods = new ArrayList(); + + // èŽ·å–æ‰€æœ‰æ–¹æ³• + Method[] methods = obj.getClass().getMethods(); + + // 查找setter方法 + + for (Method method : methods) + { + Matcher m = SET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 1)) + { + setterMethods.add(method); + } + } + // 返回setter方法列表 + return setterMethods; + } + + /** + * 获å–对象的getter方法。 + * + * @param obj 对象 + * @return 对象的getter方法列表 + */ + + public static List getGetterMethods(Object obj) + { + // getter方法列表 + List getterMethods = new ArrayList(); + // èŽ·å–æ‰€æœ‰æ–¹æ³• + Method[] methods = obj.getClass().getMethods(); + // 查找getter方法 + for (Method method : methods) + { + Matcher m = GET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 0)) + { + getterMethods.add(method); + } + } + // 返回getter方法列表 + return getterMethods; + } + + /** + * 检查Bean方法åä¸­çš„å±žæ€§åæ˜¯å¦ç›¸ç­‰ã€‚
+ * 如getName()å’ŒsetName()属性å一样,getName()å’ŒsetAge()属性åä¸ä¸€æ ·ã€‚ + * + * @param m1 方法å1 + * @param m2 方法å2 + * @return 属性å一样返回true,å¦åˆ™è¿”回false + */ + + public static boolean isMethodPropEquals(String m1, String m2) + { + return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java new file mode 100644 index 0000000..d9821e0 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.utils.bean; + +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +/** + * beanå¯¹è±¡å±žæ€§éªŒè¯ + * + * @author ruoyi + */ +public class BeanValidators +{ + public static void validateWithException(Validator validator, Object object, Class... groups) + throws ConstraintViolationException + { + Set> constraintViolations = validator.validate(object, groups); + if (!constraintViolations.isEmpty()) + { + throw new ConstraintViolationException(constraintViolations); + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java new file mode 100644 index 0000000..25f5306 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java @@ -0,0 +1,76 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import org.apache.commons.lang3.StringUtils; + +/** + * 文件类型工具类 + * + * @author ruoyi + */ +public class FileTypeUtils +{ + /** + * èŽ·å–æ–‡ä»¶ç±»åž‹ + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param file 文件å + * @return åŽç¼€ï¼ˆä¸å«".") + */ + public static String getFileType(File file) + { + if (null == file) + { + return StringUtils.EMPTY; + } + return getFileType(file.getName()); + } + + /** + * èŽ·å–æ–‡ä»¶ç±»åž‹ + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param fileName 文件å + * @return åŽç¼€ï¼ˆä¸å«".") + */ + public static String getFileType(String fileName) + { + int separatorIndex = fileName.lastIndexOf("."); + if (separatorIndex < 0) + { + return ""; + } + return fileName.substring(separatorIndex + 1).toLowerCase(); + } + + /** + * èŽ·å–æ–‡ä»¶ç±»åž‹ + * + * @param photoByte æ–‡ä»¶å­—èŠ‚ç  + * @return åŽç¼€ï¼ˆä¸å«".") + */ + public static String getFileExtendName(byte[] photoByte) + { + String strFileExtendName = "JPG"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) + { + strFileExtendName = "GIF"; + } + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) + { + strFileExtendName = "JPG"; + } + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) + { + strFileExtendName = "BMP"; + } + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) + { + strFileExtendName = "PNG"; + } + return strFileExtendName; + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java new file mode 100644 index 0000000..4652a29 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -0,0 +1,232 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Objects; +import org.apache.commons.io.FilenameUtils; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; +import com.ruoyi.common.exception.file.FileSizeLimitExceededException; +import com.ruoyi.common.exception.file.InvalidExtensionException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.Seq; + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileUploadUtils +{ + /** + * é»˜è®¤å¤§å° 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * é»˜è®¤çš„æ–‡ä»¶åæœ€å¤§é•¿åº¦ 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * é»˜è®¤ä¸Šä¼ çš„åœ°å€ + */ + private static String defaultBaseDir = RuoYiConfig.getProfile(); + + public static void setDefaultBaseDir(String defaultBaseDir) + { + FileUploadUtils.defaultBaseDir = defaultBaseDir; + } + + public static String getDefaultBaseDir() + { + return defaultBaseDir; + } + + /** + * 以默认é…置进行文件上传 + * + * @param file 上传的文件 + * @return 文件åç§° + * @throws Exception + */ + public static final String upload(MultipartFile file) throws IOException + { + try + { + return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * æ ¹æ®æ–‡ä»¶è·¯å¾„上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件åç§° + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException + { + try + { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param allowedExtension 上传文件类型 + * @return 返回上传æˆåŠŸçš„æ–‡ä»¶å + * @throws FileSizeLimitExceededException å¦‚æžœè¶…å‡ºæœ€å¤§å¤§å° + * @throws FileNameLengthLimitExceededException 文件å太长 + * @throws IOException 比如读写文件出错时 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, + InvalidExtensionException + { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + assertAllowed(file, allowedExtension); + + String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(baseDir, fileName); + } + + /** + * ç¼–ç æ–‡ä»¶å + */ + public static final String extractFilename(MultipartFile file) + { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file)); + } + + public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException + { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.exists()) + { + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static final String getPathFileName(String uploadDir, String fileName) throws IOException + { + int dirLastIndex = RuoYiConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + } + + /** + * æ–‡ä»¶å¤§å°æ ¡éªŒ + * + * @param file 上传的文件 + * @return + * @throws FileSizeLimitExceededException å¦‚æžœè¶…å‡ºæœ€å¤§å¤§å° + * @throws InvalidExtensionException + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (size > DEFAULT_MAX_SIZE) + { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) + { + if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) + { + throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) + { + throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) + { + throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) + { + throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, + fileName); + } + else + { + throw new InvalidExtensionException(allowedExtension, extension, fileName); + } + } + } + + /** + * 判断MIMEç±»åž‹æ˜¯å¦æ˜¯å…许的MIME类型 + * + * @param extension + * @param allowedExtension + * @return + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) + { + for (String str : allowedExtension) + { + if (str.equalsIgnoreCase(extension)) + { + return true; + } + } + return false; + } + + /** + * èŽ·å–æ–‡ä»¶åçš„åŽç¼€ + * + * @param file è¡¨å•æ–‡ä»¶ + * @return åŽç¼€å + */ + public static final String getExtension(MultipartFile file) + { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) + { + extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); + } + return extension; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java new file mode 100644 index 0000000..5c96f7c --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -0,0 +1,291 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.ArrayUtils; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import org.apache.commons.io.FilenameUtils; + +/** + * 文件处ç†å·¥å…·ç±» + * + * @author ruoyi + */ +public class FileUtils +{ + public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; + + /** + * 输出指定文件的byte数组 + * + * @param filePath 文件路径 + * @param os è¾“å‡ºæµ + * @return + */ + public static void writeBytes(String filePath, OutputStream os) throws IOException + { + FileInputStream fis = null; + try + { + File file = new File(filePath); + if (!file.exists()) + { + throw new FileNotFoundException(filePath); + } + fis = new FileInputStream(file); + byte[] b = new byte[1024]; + int length; + while ((length = fis.read(b)) > 0) + { + os.write(b, 0, length); + } + } + catch (IOException e) + { + throw e; + } + finally + { + IOUtils.close(os); + IOUtils.close(fis); + } + } + + /** + * 写数æ®åˆ°æ–‡ä»¶ä¸­ + * + * @param data æ•°æ® + * @return 目标文件 + * @throws IOException IO异常 + */ + public static String writeImportBytes(byte[] data) throws IOException + { + return writeBytes(data, RuoYiConfig.getImportPath()); + } + + /** + * 写数æ®åˆ°æ–‡ä»¶ä¸­ + * + * @param data æ•°æ® + * @param uploadDir 目标文件 + * @return 目标文件 + * @throws IOException IO异常 + */ + public static String writeBytes(byte[] data, String uploadDir) throws IOException + { + FileOutputStream fos = null; + String pathName = ""; + try + { + String extension = getFileExtendName(data); + pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName); + fos = new FileOutputStream(file); + fos.write(data); + } + finally + { + IOUtils.close(fos); + } + return FileUploadUtils.getPathFileName(uploadDir, pathName); + } + + /** + * 删除文件 + * + * @param filePath 文件 + * @return + */ + public static boolean deleteFile(String filePath) + { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且ä¸ä¸ºç©ºåˆ™è¿›è¡Œåˆ é™¤ + if (file.isFile() && file.exists()) + { + flag = file.delete(); + } + return flag; + } + + /** + * 文件åç§°éªŒè¯ + * + * @param filename 文件åç§° + * @return true 正常 false éžæ³• + */ + public static boolean isValidFilename(String filename) + { + return filename.matches(FILENAME_PATTERN); + } + + /** + * 检查文件是å¦å¯ä¸‹è½½ + * + * @param resource 需è¦ä¸‹è½½çš„æ–‡ä»¶ + * @return true 正常 false éžæ³• + */ + public static boolean checkAllowDownload(String resource) + { + // ç¦æ­¢ç›®å½•上跳级别 + if (StringUtils.contains(resource, "..")) + { + return false; + } + + // 检查å…许下载的文件规则 + if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) + { + return true; + } + + // ä¸åœ¨å…许下载的文件规则 + return false; + } + + /** + * 下载文件å釿–°ç¼–ç  + * + * @param request 请求对象 + * @param fileName 文件å + * @return ç¼–ç åŽçš„æ–‡ä»¶å + */ + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException + { + final String agent = request.getHeader("USER-AGENT"); + String filename = fileName; + if (agent.contains("MSIE")) + { + // IEæµè§ˆå™¨ + filename = URLEncoder.encode(filename, "utf-8"); + filename = filename.replace("+", " "); + } + else if (agent.contains("Firefox")) + { + // ç«ç‹æµè§ˆå™¨ + filename = new String(fileName.getBytes(), "ISO8859-1"); + } + else if (agent.contains("Chrome")) + { + // googleæµè§ˆå™¨ + filename = URLEncoder.encode(filename, "utf-8"); + } + else + { + // 其它æµè§ˆå™¨ + filename = URLEncoder.encode(filename, "utf-8"); + } + return filename; + } + + /** + * 下载文件å釿–°ç¼–ç  + * + * @param response å“应对象 + * @param realFileName 真实文件å + */ + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException + { + String percentEncodedFileName = percentEncode(realFileName); + + StringBuilder contentDispositionValue = new StringBuilder(); + contentDispositionValue.append("attachment; filename=") + .append(percentEncodedFileName) + .append(";") + .append("filename*=") + .append("utf-8''") + .append(percentEncodedFileName); + + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); + response.setHeader("Content-disposition", contentDispositionValue.toString()); + response.setHeader("download-filename", percentEncodedFileName); + } + + /** + * 百分å·ç¼–ç å·¥å…·æ–¹æ³• + * + * @param s 需è¦ç™¾åˆ†å·ç¼–ç çš„字符串 + * @return 百分å·ç¼–ç åŽçš„字符串 + */ + public static String percentEncode(String s) throws UnsupportedEncodingException + { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); + return encode.replaceAll("\\+", "%20"); + } + + /** + * 获å–图åƒåŽç¼€ + * + * @param photoByte å›¾åƒæ•°æ® + * @return åŽç¼€å + */ + public static String getFileExtendName(byte[] photoByte) + { + String strFileExtendName = "jpg"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) + { + strFileExtendName = "gif"; + } + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) + { + strFileExtendName = "jpg"; + } + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) + { + strFileExtendName = "bmp"; + } + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) + { + strFileExtendName = "png"; + } + return strFileExtendName; + } + + /** + * èŽ·å–æ–‡ä»¶åç§° /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png + * + * @param fileName 路径åç§° + * @return 没有文件路径的åç§° + */ + public static String getName(String fileName) + { + if (fileName == null) + { + return null; + } + int lastUnixPos = fileName.lastIndexOf('/'); + int lastWindowsPos = fileName.lastIndexOf('\\'); + int index = Math.max(lastUnixPos, lastWindowsPos); + return fileName.substring(index + 1); + } + + /** + * 获å–ä¸å¸¦åŽç¼€æ–‡ä»¶åç§° /profile/upload/2022/04/16/ruoyi.png -- ruoyi + * + * @param fileName 路径åç§° + * @return 没有文件路径和åŽç¼€çš„åç§° + */ + public static String getNameNotSuffix(String fileName) + { + if (fileName == null) + { + return null; + } + String baseName = FilenameUtils.getBaseName(fileName); + return baseName; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java new file mode 100644 index 0000000..9687bf3 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java @@ -0,0 +1,98 @@ +package com.ruoyi.common.utils.file; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; + +/** + * 图片处ç†å·¥å…·ç±» + * + * @author ruoyi + */ +public class ImageUtils +{ + private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); + + public static byte[] getImage(String imagePath) + { + InputStream is = getFile(imagePath); + try + { + return IOUtils.toByteArray(is); + } + catch (Exception e) + { + log.error("图片加载异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(is); + } + } + + public static InputStream getFile(String imagePath) + { + try + { + byte[] result = readFile(imagePath); + result = Arrays.copyOf(result, result.length); + return new ByteArrayInputStream(result); + } + catch (Exception e) + { + log.error("获å–图片异常 {}", e); + } + return null; + } + + /** + * è¯»å–æ–‡ä»¶ä¸ºå­—èŠ‚æ•°æ® + * + * @param url åœ°å€ + * @return å­—èŠ‚æ•°æ® + */ + public static byte[] readFile(String url) + { + InputStream in = null; + try + { + if (url.startsWith("http")) + { + // ç½‘ç»œåœ°å€ + URL urlObj = new URL(url); + URLConnection urlConnection = urlObj.openConnection(); + urlConnection.setConnectTimeout(30 * 1000); + urlConnection.setReadTimeout(60 * 1000); + urlConnection.setDoInput(true); + in = urlConnection.getInputStream(); + } + else + { + // æœ¬æœºåœ°å€ + String localPath = RuoYiConfig.getProfile(); + String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX); + in = new FileInputStream(downloadPath); + } + return IOUtils.toByteArray(in); + } + catch (Exception e) + { + log.error("èŽ·å–æ–‡ä»¶è·¯å¾„异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(in); + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java new file mode 100644 index 0000000..5935815 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.utils.file; + +/** + * 媒体类型工具类 + * + * @author ruoyi + */ +public class MimeTypeUtils +{ + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; + + public static final String[] FLASH_EXTENSION = { "swf", "flv" }; + + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb" }; + + public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" }; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // è§†é¢‘æ ¼å¼ + "mp4", "avi", "rmvb", + // pdf + "pdf" }; + + public static String getExtension(String prefix) + { + switch (prefix) + { + case IMAGE_PNG: + return "png"; + case IMAGE_JPG: + return "jpg"; + case IMAGE_JPEG: + return "jpeg"; + case IMAGE_BMP: + return "bmp"; + case IMAGE_GIF: + return "gif"; + default: + return ""; + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java new file mode 100644 index 0000000..dda96c3 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java @@ -0,0 +1,167 @@ +package com.ruoyi.common.utils.html; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 转义和å转义工具类 + * + * @author ruoyi + */ +public class EscapeUtil +{ + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + + private static final char[][] TEXT = new char[64][]; + + static + { + for (int i = 0; i < 64; i++) + { + TEXT[i] = new char[] { (char) i }; + } + + // special HTML characters + TEXT['\''] = "'".toCharArray(); // å•å¼•å· + TEXT['"'] = """.toCharArray(); // åŒå¼•å· + TEXT['&'] = "&".toCharArray(); // &符 + TEXT['<'] = "<".toCharArray(); // å°äºŽå· + TEXT['>'] = ">".toCharArray(); // å¤§äºŽå· + } + + /** + * 转义文本中的HTML字符为安全的字符 + * + * @param text 被转义的文本 + * @return 转义åŽçš„æ–‡æœ¬ + */ + public static String escape(String text) + { + return encode(text); + } + + /** + * 还原被转义的HTML特殊字符 + * + * @param content 包å«è½¬ä¹‰ç¬¦çš„HTML内容 + * @return 转æ¢åŽçš„字符串 + */ + public static String unescape(String content) + { + return decode(content); + } + + /** + * 清除所有HTML标签,但是ä¸åˆ é™¤æ ‡ç­¾å†…的内容 + * + * @param content 文本 + * @return 清除标签åŽçš„æ–‡æœ¬ + */ + public static String clean(String content) + { + return new HTMLFilter().filter(content); + } + + /** + * Escapeç¼–ç  + * + * @param text 被编ç çš„æ–‡æœ¬ + * @return ç¼–ç åŽçš„字符 + */ + private static String encode(String text) + { + if (StringUtils.isEmpty(text)) + { + return StringUtils.EMPTY; + } + + final StringBuilder tmp = new StringBuilder(text.length() * 6); + char c; + for (int i = 0; i < text.length(); i++) + { + c = text.charAt(i); + if (c < 256) + { + tmp.append("%"); + if (c < 16) + { + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + else + { + tmp.append("%u"); + if (c <= 0xfff) + { + // issue#I49JU8@Gitee + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + } + return tmp.toString(); + } + + /** + * Escapeè§£ç  + * + * @param content 被转义的内容 + * @return è§£ç åŽçš„字符串 + */ + public static String decode(String content) + { + if (StringUtils.isEmpty(content)) + { + return content; + } + + StringBuilder tmp = new StringBuilder(content.length()); + int lastPos = 0, pos = 0; + char ch; + while (lastPos < content.length()) + { + pos = content.indexOf("%", lastPos); + if (pos == lastPos) + { + if (content.charAt(pos + 1) == 'u') + { + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); + tmp.append(ch); + lastPos = pos + 6; + } + else + { + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); + tmp.append(ch); + lastPos = pos + 3; + } + } + else + { + if (pos == -1) + { + tmp.append(content.substring(lastPos)); + lastPos = content.length(); + } + else + { + tmp.append(content.substring(lastPos, pos)); + lastPos = pos; + } + } + } + return tmp.toString(); + } + + public static void main(String[] args) + { + String html = ""; + String escape = EscapeUtil.escape(html); + // String html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println("clean: " + EscapeUtil.clean(html)); + System.out.println("escape: " + escape); + System.out.println("unescape: " + EscapeUtil.unescape(escape)); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java new file mode 100644 index 0000000..587ee6f --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java @@ -0,0 +1,570 @@ +package com.ruoyi.common.utils.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSSæ¼æ´žéšæ‚£ã€‚ + * + * @author ruoyi + */ +public final class HTMLFilter +{ + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" + * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() + { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[] { "img" }; + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; + vDisallowed = new String[] {}; + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. + vProtocolAtts = new String[] { "src", "href" }; + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) + { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() + { + vTagCounts.clear(); + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) + { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) + { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + // --------------------------------------------------------------- + + /** + * given a user submitted input String, filter out any invalid or restricted html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) + { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + // s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() + { + return alwaysMakeTags; + } + + public boolean isStripComments() + { + return stripComment; + } + + private String escapeComments(final String s) + { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) + { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) + { + if (alwaysMakeTags) + { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + // ä¸è¿½åŠ ç»“æŸæ ‡ç­¾ + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } + else + { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) + { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) + { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) + { + for (int ii = 0; ii < vTagCounts.get(key); ii++) + { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) + { + String result = s; + for (String tag : vRemoveBlanks) + { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) + { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) + { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) + { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) + { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) + { + if (!inArray(name, vSelfClosingTags)) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) + { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) + { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) + { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) + { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) + { + if (inArray(paramName, vProtocolAtts)) + { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\""); + } + } + + if (inArray(name, vSelfClosingTags)) + { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) + { + ending = ""; + } + + if (ending == null || ending.length() < 1) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } + else + { + vTagCounts.put(name, 1); + } + } + else + { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } + else + { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) + { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) + { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) + { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) + { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) + { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) + { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) + { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) + { + if (encodeQuotes) + { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 䏿›¿æ¢åŒå¼•å·ä¸º",防止jsonæ ¼å¼æ— æ•ˆ regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } + else + { + return s; + } + } + + private String checkEntity(final String preamble, final String term) + { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) + { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) + { + for (String item : array) + { + if (item != null && item.equals(s)) + { + return true; + } + } + return false; + } + + private boolean allowed(final String name) + { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) + { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java new file mode 100644 index 0000000..8baad38 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java @@ -0,0 +1,55 @@ +package com.ruoyi.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import javax.servlet.ServletRequest; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http工具å°è£… + * + * @author ruoyi + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题ï¼"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java new file mode 100644 index 0000000..f82bef6 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java @@ -0,0 +1,274 @@ +package com.ruoyi.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; + +/** + * 通用httpå‘逿–¹æ³• + * + * @author ruoyi + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 呿Œ‡å®š URL å‘é€GET方法的请求 + * + * @param url å‘é€è¯·æ±‚çš„ URL + * @return 所代表远程资æºçš„å“应结果 + */ + public static String sendGet(String url) + { + return sendGet(url, StringUtils.EMPTY); + } + + /** + * 呿Œ‡å®š URL å‘é€GET方法的请求 + * + * @param url å‘é€è¯·æ±‚çš„ URL + * @param param è¯·æ±‚å‚æ•°ï¼Œè¯·æ±‚傿•°åº”该是 name1=value1&name2=value2 的形å¼ã€‚ + * @return 所代表远程资æºçš„å“应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 呿Œ‡å®š URL å‘é€GET方法的请求 + * + * @param url å‘é€è¯·æ±‚çš„ URL + * @param param è¯·æ±‚å‚æ•°ï¼Œè¯·æ±‚傿•°åº”该是 name1=value1&name2=value2 的形å¼ã€‚ + * @param contentType ç¼–ç ç±»åž‹ + * @return 所代表远程资æºçš„å“应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 呿Œ‡å®š URL å‘é€POST方法的请求 + * + * @param url å‘é€è¯·æ±‚çš„ URL + * @param param è¯·æ±‚å‚æ•°ï¼Œè¯·æ±‚傿•°åº”该是 name1=value1&name2=value2 的形å¼ã€‚ + * @return 所代表远程资æºçš„å“应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java new file mode 100644 index 0000000..f95766e --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.utils.ip; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.http.HttpUtils; + +/** + * 获å–地å€ç±» + * + * @author ruoyi + */ +public class AddressUtils +{ + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + + // IPåœ°å€æŸ¥è¯¢ + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // æœªçŸ¥åœ°å€ + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) + { + // å†…ç½‘ä¸æŸ¥è¯¢ + if (IpUtils.internalIp(ip)) + { + return "内网IP"; + } + if (RuoYiConfig.isAddressEnabled()) + { + try + { + String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); + if (StringUtils.isEmpty(rspStr)) + { + log.error("获å–地ç†ä½ç½®å¼‚常 {}", ip); + return UNKNOWN; + } + JSONObject obj = JSON.parseObject(rspStr); + String region = obj.getString("pro"); + String city = obj.getString("city"); + return String.format("%s %s", region, city); + } + catch (Exception e) + { + log.error("获å–地ç†ä½ç½®å¼‚常 {}", ip); + } + } + return UNKNOWN; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java new file mode 100644 index 0000000..3316240 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java @@ -0,0 +1,382 @@ +package com.ruoyi.common.utils.ip; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * 获å–IP方法 + * + * @author ruoyi + */ +public class IpUtils +{ + public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; + // åŒ¹é… ip + public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")"; + public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))"; + // 匹é…网段 + public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")"; + + /** + * 获å–客户端IP + * + * @return IPåœ°å€ + */ + public static String getIpAddr() + { + return getIpAddr(ServletUtils.getRequest()); + } + + /** + * 获å–客户端IP + * + * @param request 请求对象 + * @return IPåœ°å€ + */ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + 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("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); + } + + /** + * 检查是å¦ä¸ºå†…部IPåœ°å€ + * + * @param ip IPåœ°å€ + * @return 结果 + */ + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + /** + * 检查是å¦ä¸ºå†…部IPåœ°å€ + * + * @param addr byteåœ°å€ + * @return 结果 + */ + private static boolean internalIp(byte[] addr) + { + if (StringUtils.isNull(addr) || addr.length < 2) + { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) + { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) + { + return true; + } + case SECTION_5: + switch (b1) + { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * å°†IPv4地å€è½¬æ¢æˆå­—节 + * + * @param text IPv4åœ°å€ + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) + { + if (text.length() == 0) + { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try + { + long l; + int i; + switch (elements.length) + { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) + { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) + { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) + { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } + catch (NumberFormatException e) + { + return null; + } + return bytes; + } + + /** + * 获å–IPåœ°å€ + * + * @return 本地IPåœ°å€ + */ + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + } + return "127.0.0.1"; + } + + /** + * 获å–主机å + * + * @return 本地主机å + */ + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + } + return "未知"; + } + + /** + * 从多级åå‘代ç†ä¸­èŽ·å¾—ç¬¬ä¸€ä¸ªéžunknown IPåœ°å€ + * + * @param ip 获得的IPåœ°å€ + * @return 第一个éžunknown IPåœ°å€ + */ + public static String getMultistageReverseProxyIp(String ip) + { + // 多级åå‘ä»£ç†æ£€æµ‹ + if (ip != null && ip.indexOf(",") > 0) + { + final String[] ips = ip.trim().split(","); + for (String subIp : ips) + { + if (false == isUnknown(subIp)) + { + ip = subIp; + break; + } + } + } + return StringUtils.substring(ip, 0, 255); + } + + /** + * 检测给定字符串是å¦ä¸ºæœªçŸ¥ï¼Œå¤šç”¨äºŽæ£€æµ‹HTTP请求相关 + * + * @param checkString 被检测的字符串 + * @return æ˜¯å¦æœªçŸ¥ + */ + public static boolean isUnknown(String checkString) + { + return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); + } + + /** + * 是å¦ä¸ºIP + */ + public static boolean isIP(String ip) + { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP); + } + + /** + * 是å¦ä¸ºIP,或 *为间隔的通é…ç¬¦åœ°å€ + */ + public static boolean isIpWildCard(String ip) + { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD); + } + + /** + * æ£€æµ‹å‚æ•°æ˜¯å¦åœ¨ip通é…符里 + */ + public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) + { + String[] s1 = ipWildCard.split("\\."); + String[] s2 = ip.split("\\."); + boolean isMatchedSeg = true; + for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) + { + if (!s1[i].equals(s2[i])) + { + isMatchedSeg = false; + break; + } + } + return isMatchedSeg; + } + + /** + * 是å¦ä¸ºç‰¹å®šæ ¼å¼å¦‚:“10.10.10.1-10.10.10.99â€çš„ip段字符串 + */ + public static boolean isIPSegment(String ipSeg) + { + return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG); + } + + /** + * 判断ip是å¦åœ¨æŒ‡å®šç½‘段中 + */ + public static boolean ipIsInNetNoCheck(String iparea, String ip) + { + int idx = iparea.indexOf('-'); + String[] sips = iparea.substring(0, idx).split("\\."); + String[] sipe = iparea.substring(idx + 1).split("\\."); + String[] sipt = ip.split("\\."); + long ips = 0L, ipe = 0L, ipt = 0L; + for (int i = 0; i < 4; ++i) + { + ips = ips << 8 | Integer.parseInt(sips[i]); + ipe = ipe << 8 | Integer.parseInt(sipe[i]); + ipt = ipt << 8 | Integer.parseInt(sipt[i]); + } + if (ips > ipe) + { + long t = ips; + ips = ipe; + ipe = t; + } + return ips <= ipt && ipt <= ipe; + } + + /** + * 校验ip是å¦ç¬¦åˆè¿‡æ»¤ä¸²è§„则 + * + * @param filter 过滤IP列表,支æŒåŽç¼€'*'通é…,支æŒç½‘段如:`10.10.10.1-10.10.10.99` + * @param ip 校验IPåœ°å€ + * @return boolean 结果 + */ + public static boolean isMatchedIp(String filter, String ip) + { + if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip)) + { + return false; + } + String[] ips = filter.split(";"); + for (String iStr : ips) + { + if (isIP(iStr) && iStr.equals(ip)) + { + return true; + } + else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)) + { + return true; + } + else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)) + { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java new file mode 100644 index 0000000..c9ca2d5 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.utils.poi; + +/** + * Excelæ•°æ®æ ¼å¼å¤„ç†é€‚é…器 + * + * @author ruoyi + */ +public interface ExcelHandlerAdapter +{ + /** + * æ ¼å¼åŒ– + * + * @param value å•元格数æ®å€¼ + * @param args excel注解args傿•°ç»„ + * + * @return 处ç†åŽçš„值 + */ + Object format(Object value, String[] args); +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java new file mode 100644 index 0000000..f6f734f --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -0,0 +1,1746 @@ +package com.ruoyi.common.utils.poi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.hssf.usermodel.HSSFPicture; +import org.apache.poi.hssf.usermodel.HSSFPictureData; +import org.apache.poi.hssf.usermodel.HSSFShape; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.apache.poi.xssf.usermodel.XSSFDrawing; +import org.apache.poi.xssf.usermodel.XSSFPicture; +import org.apache.poi.xssf.usermodel.XSSFShape; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.exception.UtilException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileTypeUtils; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.common.utils.file.ImageUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; + +/** + * Excelç›¸å…³å¤„ç† + * + * @author ruoyi + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; + + public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + + /** + * 用于dictType属性数æ®å­˜å‚¨ï¼Œé¿å…é‡å¤æŸ¥ç¼“å­˜ + */ + public Map sysDictMap = new HashMap(); + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表åç§° + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数æ®ï¼›IMPORT:导入模æ¿ï¼‰ + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * æ ·å¼åˆ—表 + */ + private Map styles; + + /** + * 导入导出数æ®åˆ—表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 当å‰è¡Œå· + */ + private int rownum; + + /** + * 标题 + */ + private String title; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * åˆå¹¶åŽæœ€åŽè¡Œæ•° + */ + private int subMergedLastRowNum = 0; + + /** + * åˆå¹¶åŽå¼€å§‹è¡Œæ•° + */ + private int subMergedFirstRowNum = 1; + + /** + * 对象的å­åˆ—表方法 + */ + private Method subMethod; + + /** + * 对象的å­åˆ—表属性 + */ + private List subFields; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * æ•°å­—æ ¼å¼ + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + /** + * éœ€è¦æŽ’é™¤åˆ—å±žæ€§ + */ + public String[] excludeFields; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + /** + * éšè—Excel中列属性 + * + * @param fields 列属性å 示例[å•个"name"/多个"id","name"] + * @throws Exception + */ + public void hideColumn(String... fields) + { + this.excludeFields = fields; + } + + public void init(List list, String sheetName, String title, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + this.title = title; + createExcelField(); + createWorkbook(); + createTitle(); + createSubHead(); + } + + /** + * 创建excel第一行标题 + */ + public void createTitle() + { + if (StringUtils.isNotEmpty(title)) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + int titleLastCol = this.fields.size() - 1; + if (isSubList()) + { + titleLastCol = titleLastCol + subFields.size() - 1; + } + Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); + titleRow.setHeightInPoints(30); + Cell titleCell = titleRow.createCell(0); + titleCell.setCellStyle(styles.get("title")); + titleCell.setCellValue(title); + sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); + } + } + + /** + * 创建对象的å­åˆ—表åç§° + */ + public void createSubHead() + { + if (isSubList()) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + Row subRow = sheet.createRow(rownum); + int excelNum = 0; + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Cell headCell1 = subRow.createCell(excelNum); + headCell1.setCellValue(attr.name()); + headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + excelNum++; + } + int headFirstRow = excelNum - 1; + int headLastRow = headFirstRow + subFields.size() - 1; + if (headLastRow > headFirstRow) + { + sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); + } + rownum++; + } + } + + /** + * 对excel表å•默认第一个索引åè½¬æ¢æˆlist + * + * @param is è¾“å…¥æµ + * @return 转æ¢åŽé›†åˆ + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(is, 0); + } + + /** + * 对excel表å•默认第一个索引åè½¬æ¢æˆlist + * + * @param is è¾“å…¥æµ + * @param titleNum 标题å ç”¨è¡Œæ•° + * @return 转æ¢åŽé›†åˆ + */ + public List importExcel(InputStream is, int titleNum) throws Exception + { + return importExcel(StringUtils.EMPTY, is, titleNum); + } + + /** + * 对excelè¡¨å•æŒ‡å®šè¡¨æ ¼ç´¢å¼•åè½¬æ¢æˆlist + * + * @param sheetName 表格索引å + * @param titleNum 标题å ç”¨è¡Œæ•° + * @param is è¾“å…¥æµ + * @return 转æ¢åŽé›†åˆ + */ + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + // 如果指定sheetå,åˆ™å–æŒ‡å®šsheet中的内容 å¦åˆ™é»˜è®¤æŒ‡å‘第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); + if (sheet == null) + { + throw new IOException("文件sheetä¸å­˜åœ¨"); + } + boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); + Map pictures; + if (isXSSFWorkbook) + { + pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); + } + else + { + pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); + } + // èŽ·å–æœ€åŽä¸€ä¸ªéžç©ºè¡Œçš„行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的åºå·å’Œfield. + Map cellMap = new HashMap(); + // 获å–表头 + Row heard = sheet.getRow(titleNum); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // æœ‰æ•°æ®æ—¶æ‰å¤„ç† å¾—åˆ°ç±»çš„æ‰€æœ‰field. + List fields = this.getFields(); + Map fieldsMap = new HashMap(); + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, objects); + } + } + for (int i = titleNum + 1; i <= rows; i++) + { + // 从第2è¡Œå¼€å§‹å–æ•°æ®,默认第一行是表头. + Row row = sheet.getRow(i); + // 判断当å‰è¡Œæ˜¯å¦æ˜¯ç©ºè¡Œ + if (isRowEmpty(row)) + { + continue; + } + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果ä¸å­˜åœ¨å®žä¾‹åˆ™æ–°å»º. + entity = (entity == null ? clazz.getDeclaredConstructor().newInstance() : entity); + // 从map中得到对应列的field. + Field field = (Field) entry.getValue()[0]; + Excel attr = (Excel) entry.getValue()[1]; + // å–得类型,å¹¶æ ¹æ®å¯¹è±¡ç±»åž‹è®¾ç½®å€¼. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = parseDateToStr(dateFormat, val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + val = dataFormatHandlerAdapter(val, attr); + } + else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) + { + PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); + if (image == null) + { + val = ""; + } + else + { + byte[] data = image.getData(); + val = FileUtils.writeImportBytes(data); + } + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param list 导出数æ®é›†åˆ + * @param sheetName 工作表的åç§° + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + return exportExcel(list, sheetName, StringUtils.EMPTY); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param list 导出数æ®é›†åˆ + * @param sheetName 工作表的åç§° + * @param title 标题 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName, String title) + { + this.init(list, sheetName, title, Type.EXPORT); + return exportExcel(); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param response è¿”å›žæ•°æ® + * @param list 导出数æ®é›†åˆ + * @param sheetName 工作表的åç§° + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName) + { + exportExcel(response, list, sheetName, StringUtils.EMPTY); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param response è¿”å›žæ•°æ® + * @param list 导出数æ®é›†åˆ + * @param sheetName 工作表的åç§° + * @param title 标题 + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(list, sheetName, title, Type.EXPORT); + exportExcel(response); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param sheetName 工作表的åç§° + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + return importTemplateExcel(sheetName, StringUtils.EMPTY); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param sheetName 工作表的åç§° + * @param title 标题 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName, String title) + { + this.init(null, sheetName, title, Type.IMPORT); + return exportExcel(); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param sheetName 工作表的åç§° + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName) + { + importTemplateExcel(response, sheetName, StringUtils.EMPTY); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @param sheetName 工作表的åç§° + * @param title 标题 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(null, sheetName, title, Type.IMPORT); + exportExcel(response); + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @return 结果 + */ + public void exportExcel(HttpServletResponse response) + { + try + { + writeSheet(); + wb.write(response.getOutputStream()); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + } + finally + { + IOUtils.closeQuietly(wb); + } + } + + /** + * 对listæ•°æ®æºå°†å…¶é‡Œé¢çš„æ•°æ®å¯¼å…¥åˆ°excelè¡¨å• + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + writeSheet(); + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new UtilException("导出Excel失败,请è”系网站管ç†å‘˜ï¼"); + } + finally + { + IOUtils.closeQuietly(wb); + IOUtils.closeQuietly(out); + } + } + + /** + * 创建写入数æ®åˆ°Sheet + */ + public void writeSheet() + { + // å–出一共有多少个sheet. + int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); + for (int index = 0; index < sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(rownum); + int column = 0; + // 写入å„个字段的列头åç§° + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType())) + { + for (Field subField : subFields) + { + Excel subExcel = subField.getAnnotation(Excel.class); + this.createHeadCell(subExcel, row, column++); + } + } + else + { + this.createHeadCell(excel, row, column++); + } + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + } + + /** + * å¡«å……excelæ•°æ® + * + * @param index åºå· + * @param row å•元格行 + */ + @SuppressWarnings("unchecked") + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + int rowNo = (1 + rownum) - startNo; + for (int i = startNo; i < endNo; i++) + { + rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; + row = sheet.createRow(rowNo); + // 得到导出对象. + T vo = (T) list.get(i); + Collection subList = null; + if (isSubList()) + { + if (isSubListValue(vo)) + { + subList = getListCellValue(vo); + subMergedLastRowNum = subMergedLastRowNum + subList.size(); + } + else + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + } + } + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) + { + boolean subFirst = false; + for (Object obj : subList) + { + if (subFirst) + { + rowNo++; + row = sheet.createRow(rowNo); + } + List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); + int subIndex = 0; + for (Field subField : subFields) + { + if (subField.isAnnotationPresent(Excel.class)) + { + subField.setAccessible(true); + Excel attr = subField.getAnnotation(Excel.class); + this.addCell(attr, row, (T) obj, subField, column + subIndex); + } + subIndex++; + } + subFirst = true; + } + this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); + } + else + { + this.addCell(excel, row, vo, field, column++); + } + } + } + } + + /** + * åˆ›å»ºè¡¨æ ¼æ ·å¼ + * + * @param wb 工作薄对象 + * @return æ ·å¼åˆ—表 + */ + private Map createStyles(Workbook wb) + { + // 写入儿¡è®°å½•,æ¯æ¡è®°å½•对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font titleFont = wb.createFont(); + titleFont.setFontName("Arial"); + titleFont.setFontHeightInPoints((short) 16); + titleFont.setBold(true); + style.setFont(titleFont); + styles.put("title", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + styles.putAll(annotationHeaderStyles(wb, styles)); + + styles.putAll(annotationDataStyles(wb)); + + return styles; + } + + /** + * æ ¹æ®Excelæ³¨è§£åˆ›å»ºè¡¨æ ¼å¤´æ ·å¼ + * + * @param wb 工作薄对象 + * @return 自定义样å¼åˆ—表 + */ + private Map annotationHeaderStyles(Workbook wb, Map styles) + { + Map headerStyles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); + if (!headerStyles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(excel.headerBackgroundColor().index); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(excel.headerColor().index); + style.setFont(headerFont); + headerStyles.put(key, style); + } + } + return headerStyles; + } + + /** + * æ ¹æ®Excelæ³¨è§£åˆ›å»ºè¡¨æ ¼åˆ—æ ·å¼ + * + * @param wb 工作薄对象 + * @return 自定义样å¼åˆ—表 + */ + private Map annotationDataStyles(Workbook wb) + { + Map styles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); + if (!styles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.setAlignment(excel.align()); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setFillForegroundColor(excel.backgroundColor().getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + dataFont.setColor(excel.color().index); + style.setFont(dataFont); + styles.put(key, style); + } + } + return styles; + } + + /** + * 创建å•元格 + */ + public Cell createHeadCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // å†™å…¥åˆ—ä¿¡æ¯ + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + if (isSubList()) + { + // 填充默认样å¼ï¼Œé˜²æ­¢åˆå¹¶å•元格样å¼å¤±æ•ˆ + sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + if (attr.needMerge()) + { + sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); + } + } + return cell; + } + + /** + * 设置å•å…ƒæ ¼ä¿¡æ¯ + * + * @param value å•元格值 + * @param attr 注解相关 + * @param cell å•å…ƒæ ¼ä¿¡æ¯ + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + String cellValue = Convert.toStr(value); + // 对于任何以表达å¼è§¦å‘字符 =-+@开头的å•元格,直接使用tab字符作为å‰ç¼€ï¼Œé˜²æ­¢CSV注入。 + if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) + { + cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); + } + if (value instanceof Collection && StringUtils.equals("[]", cellValue)) + { + cellValue = StringUtils.EMPTY; + } + cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + if (StringUtils.isNotNull(value)) + { + cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + } + else if (ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (StringUtils.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获å–画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获å–图片类型,设置图片æ’入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * åˆ›å»ºè¡¨æ ¼æ ·å¼ + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) + { + if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) + { + // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,é¿å…生æˆçš„æ¨¡æ¿ä¸‹æ‹‰å€¼èŽ·å–ä¸åˆ° + setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + else + { + // æç¤ºä¿¡æ¯æˆ–åªèƒ½é€‰æ‹©ä¸èƒ½è¾“入的列内容. + setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + } + } + + /** + * 添加å•元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // æ ¹æ®Excel中设置情况决定是å¦å¯¼å‡º,有些情况需è¦ä¿æŒä¸ºç©º,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) + { + CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); + sheet.addMergedRegion(cellAddress); + } + cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + + // 用于读å–对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + String dictType = attr.dictType(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(parseDateToStr(dateFormat, value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) + { + if (!sysDictMap.containsKey(dictType + value)) + { + String lable = convertDictByExp(Convert.toStr(value), dictType, separator); + sysDictMap.put(dictType + value, lable); + } + cell.setCellValue(sysDictMap.get(dictType + value)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + cell.setCellValue(dataFormatHandlerAdapter(value, attr)); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet å•元格æç¤ºæˆ–选择框 + * + * @param sheet è¡¨å• + * @param textlist 下拉框显示的内容 + * @param promptContent æç¤ºå†…容 + * @param firstRow 开始行 + * @param endRow 结æŸè¡Œ + * @param firstCol 开始列 + * @param endCol 结æŸåˆ— + */ + public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了æç¤ºä¿¡æ¯åˆ™é¼ æ ‡æ”¾ä¸ŠåŽ»æç¤º + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处ç†Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + sheet.addValidationData(dataValidation); + } + + /** + * 设置æŸäº›åˆ—的值åªèƒ½è¾“入预制的数æ®,显示下拉框(兼容超出一定数é‡çš„下拉框). + * + * @param sheet è¦è®¾ç½®çš„sheet. + * @param textlist 下拉框显示的内容 + * @param promptContent æç¤ºå†…容 + * @param firstRow 开始行 + * @param endRow 结æŸè¡Œ + * @param firstCol 开始列 + * @param endCol 结æŸåˆ— + */ + public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) + { + String hideSheetName = "combo_" + firstCol + "_" + endCol; + Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉èœå•æ•°æ® + for (int i = 0; i < textlist.length; i++) + { + hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); + } + // 创建å称,å¯è¢«å…¶ä»–å•元格引用 + Name name = wb.createName(); + name.setNameName(hideSheetName + "_data"); + name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); + // è®¾ç½®æ•°æ®æœ‰æ•ˆæ€§åŠ è½½åœ¨å“ªä¸ªå•元格上,å››ä¸ªå‚æ•°åˆ†åˆ«æ˜¯ï¼šèµ·å§‹è¡Œã€ç»ˆæ­¢è¡Œã€èµ·å§‹åˆ—ã€ç»ˆæ­¢åˆ— + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // æ•°æ®æœ‰æ•ˆæ€§å¯¹è±¡ + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了æç¤ºä¿¡æ¯åˆ™é¼ æ ‡æ”¾ä¸ŠåŽ»æç¤º + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处ç†Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + // 设置hiddenSheetéšè— + wb.setSheetHidden(wb.getSheetIndex(hideSheet), true); + } + + /** + * è§£æžå¯¼å‡ºå€¼ 0=ç”·,1=女,2=未知 + * + * @param propertyValue 傿•°å€¼ + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return è§£æžåŽå€¼ + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * åå‘è§£æžå€¼ ç”·=0,女=1,未知=2 + * + * @param propertyValue 傿•°å€¼ + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return è§£æžåŽå€¼ + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * è§£æžå­—典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String convertDictByExp(String dictValue, String dictType, String separator) + { + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * åå‘è§£æžå€¼å­—典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public static String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * æ•°æ®å¤„ç†å™¨ + * + * @param value æ•°æ®å€¼ + * @param excel æ•°æ®æ³¨è§£ + * @return + */ + public String dataFormatHandlerAdapter(Object value, Excel excel) + { + try + { + Object instance = excel.handler().getDeclaredConstructor().newInstance(); + Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); + value = formatMethod.invoke(instance, value, excel.args()); + } + catch (Exception e) + { + log.error("ä¸èƒ½æ ¼å¼åŒ–æ•°æ® " + excel.handler(), e.getMessage()); + } + return Convert.toStr(value); + } + + /** + * åˆè®¡ç»Ÿè®¡ä¿¡æ¯ + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + Cell cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("åˆè®¡"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * ç¼–ç æ–‡ä»¶å + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获å–下载路径 + * + * @param filename 文件åç§° + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = RuoYiConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获å–bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.contains(".")) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形å¼èŽ·å–值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = getFields(); + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 获å–å­—æ®µæ³¨è§£ä¿¡æ¯ + */ + public List getFields() + { + List fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) + { + // 啿³¨è§£ + if (field.isAnnotationPresent(Excel.class)) + { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + if (Collection.class.isAssignableFrom(field.getType())) + { + subMethod = getSubMethod(field.getName(), clazz); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class subClass = (Class) pt.getActualTypeArguments()[0]; + this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + } + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) + { + if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) + && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + } + } + } + } + return fields; + } + + /** + * æ ¹æ®æ³¨è§£èŽ·å–æœ€å¤§è¡Œé«˜ + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = Math.max(maxHeight, excel.height()); + } + return (short) (maxHeight * 20); + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + this.sheet = wb.createSheet(); + wb.setSheetName(0, sheetName); + this.styles = createStyles(wb); + } + + /** + * 创建工作表 + * + * @param sheetNo sheetæ•°é‡ + * @param index åºå· + */ + public void createSheet(int sheetNo, int index) + { + // 设置工作表的åç§°. + if (sheetNo > 1 && index > 0) + { + this.sheet = wb.createSheet(); + this.createTitle(); + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获å–å•元格值 + * + * @param row 获å–的行 + * @param column 获å–å•å…ƒæ ¼åˆ—å· + * @return å•元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格å¼è½¬æ¢ + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } + + /** + * åˆ¤æ–­æ˜¯å¦æ˜¯ç©ºè¡Œ + * + * @param row 判断的行 + * @return + */ + private boolean isRowEmpty(Row row) + { + if (row == null) + { + return true; + } + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) + { + Cell cell = row.getCell(i); + if (cell != null && cell.getCellType() != CellType.BLANK) + { + return false; + } + } + return true; + } + + /** + * 获å–Excel2003图片 + * + * @param sheet 当å‰sheet对象 + * @param workbook 工作簿对象 + * @return Map key:图片å•元格索引(1_1)String,value:图片æµPictureData + */ + public static Map getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) + { + Map sheetIndexPicMap = new HashMap(); + List pictures = workbook.getAllPictures(); + if (!pictures.isEmpty()) + { + for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) + { + HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); + if (shape instanceof HSSFPicture) + { + HSSFPicture pic = (HSSFPicture) shape; + int pictureIndex = pic.getPictureIndex() - 1; + HSSFPictureData picData = pictures.get(pictureIndex); + String picIndex = anchor.getRow1() + "_" + anchor.getCol1(); + sheetIndexPicMap.put(picIndex, picData); + } + } + return sheetIndexPicMap; + } + else + { + return sheetIndexPicMap; + } + } + + /** + * 获å–Excel2007图片 + * + * @param sheet 当å‰sheet对象 + * @param workbook 工作簿对象 + * @return Map key:图片å•元格索引(1_1)String,value:图片æµPictureData + */ + public static Map getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook) + { + Map sheetIndexPicMap = new HashMap(); + for (POIXMLDocumentPart dr : sheet.getRelations()) + { + if (dr instanceof XSSFDrawing) + { + XSSFDrawing drawing = (XSSFDrawing) dr; + List shapes = drawing.getShapes(); + for (XSSFShape shape : shapes) + { + if (shape instanceof XSSFPicture) + { + XSSFPicture pic = (XSSFPicture) shape; + XSSFClientAnchor anchor = pic.getPreferredSize(); + CTMarker ctMarker = anchor.getFrom(); + String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol(); + sheetIndexPicMap.put(picIndex, pic.getPictureData()); + } + } + } + } + return sheetIndexPicMap; + } + + /** + * æ ¼å¼åŒ–ä¸åŒç±»åž‹çš„æ—¥æœŸå¯¹è±¡ + * + * @param dateFormat æ—¥æœŸæ ¼å¼ + * @param val 被格å¼åŒ–的日期对象 + * @return æ ¼å¼åŒ–åŽçš„æ—¥æœŸå­—符 + */ + public String parseDateToStr(String dateFormat, Object val) + { + if (val == null) + { + return ""; + } + String str; + if (val instanceof Date) + { + str = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else if (val instanceof LocalDateTime) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val)); + } + else if (val instanceof LocalDate) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val)); + } + else + { + str = val.toString(); + } + return str; + } + + /** + * æ˜¯å¦æœ‰å¯¹è±¡çš„å­åˆ—表 + */ + public boolean isSubList() + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0; + } + + /** + * æ˜¯å¦æœ‰å¯¹è±¡çš„å­åˆ—表,集åˆä¸ä¸ºç©º + */ + public boolean isSubListValue(T vo) + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; + } + + /** + * 获å–集åˆçš„值 + */ + public Collection getListCellValue(Object obj) + { + Object value; + try + { + value = subMethod.invoke(obj, new Object[] {}); + } + catch (Exception e) + { + return new ArrayList(); + } + return (Collection) value; + } + + /** + * 获å–对象的å­åˆ—表方法 + * + * @param name åç§° + * @param pojoClass 类对象 + * @return å­åˆ—表方法 + */ + public Method getSubMethod(String name, Class pojoClass) + { + StringBuffer getMethodName = new StringBuffer("get"); + getMethodName.append(name.substring(0, 1).toUpperCase()); + getMethodName.append(name.substring(1)); + Method method = null; + try + { + method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); + } + catch (Exception e) + { + log.error("获å–对象异常{}", e.getMessage()); + } + return method; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java new file mode 100644 index 0000000..69f36a9 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java @@ -0,0 +1,435 @@ +package com.ruoyi.common.utils.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.AccessibleObject; +import java.util.Date; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.apache.poi.ss.usermodel.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.DateUtils; + +/** + * å射工具类. æä¾›è°ƒç”¨getter/setter方法, è®¿é—®ç§æœ‰å˜é‡, è°ƒç”¨ç§æœ‰æ–¹æ³•, èŽ·å–æ³›åž‹ç±»åž‹Class, 被AOP过的真实类等工具函数. + * + * @author ruoyi + */ +@SuppressWarnings("rawtypes") +public class ReflectUtils +{ + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); + + /** + * 调用Getter方法. + * 支æŒå¤šçº§ï¼Œå¦‚:对象å.对象å.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter(Object obj, String propertyName) + { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return (E) object; + } + + /** + * 调用Setter方法, ä»…åŒ¹é…æ–¹æ³•å。 + * 支æŒå¤šçº§ï¼Œå¦‚:对象å.对象å.方法 + */ + public static void invokeSetter(Object obj, String propertyName, E value) + { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0; i < names.length; i++) + { + if (i < names.length - 1) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + else + { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[] { value }); + } + } + } + + /** + * 直接读å–对象属性值, 无视private/protected修饰符, ä¸ç»è¿‡getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue(final Object obj, final String fieldName) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try + { + result = (E) field.get(obj); + } + catch (IllegalAccessException e) + { + logger.error("ä¸å¯èƒ½æŠ›å‡ºçš„异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, ä¸ç»è¿‡setter函数. + */ + public static void setFieldValue(final Object obj, final String fieldName, final E value) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try + { + field.set(obj, value); + } + catch (IllegalAccessException e) + { + logger.error("ä¸å¯èƒ½æŠ›å‡ºçš„异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,å¦åˆ™åº”使用getAccessibleMethod()函数获得MethodåŽåå¤è°ƒç”¨. + * åŒæ—¶åŒ¹é…方法å+傿•°ç±»åž‹ï¼Œ + */ + + @SuppressWarnings("unchecked") + public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) + { + if (obj == null || methodName == null) + { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,å¦åˆ™åº”使用getAccessibleMethodByName()函数获得MethodåŽåå¤è°ƒç”¨. + * åªåŒ¹é…函数å,如果有多个åŒå函数调用第一个。 + */ + + @SuppressWarnings("unchecked") + public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) + { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) + { + // å¦‚æžœä¸ºç©ºä¸æŠ¥é”™ï¼Œç›´æŽ¥è¿”å›žç©ºã€‚ + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + // 类型转æ¢ï¼ˆå°†å‚æ•°æ•°æ®ç±»åž‹è½¬æ¢ä¸ºç›®æ ‡æ–¹æ³•傿•°ç±»åž‹ï¼‰ + Class[] cs = method.getParameterTypes(); + for (int i = 0; i < cs.length; i++) + { + if (args[i] != null && !args[i].getClass().equals(cs[i])) + { + if (cs[i] == String.class) + { + args[i] = Convert.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) + { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } + else if (cs[i] == Integer.class) + { + args[i] = Convert.toInt(args[i]); + } + else if (cs[i] == Long.class) + { + args[i] = Convert.toLong(args[i]); + } + else if (cs[i] == Double.class) + { + args[i] = Convert.toDouble(args[i]); + } + else if (cs[i] == Float.class) + { + args[i] = Convert.toFloat(args[i]); + } + else if (cs[i] == Date.class) + { + if (args[i] instanceof String) + { + args[i] = DateUtils.parseDate(args[i]); + } + else + { + args[i] = DateUtil.getJavaDate((Double) args[i]); + } + } + else if (cs[i] == boolean.class || cs[i] == Boolean.class) + { + args[i] = Convert.toBool(args[i]); + } + } + } + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环å‘上转型, 获å–对象的DeclaredField, 并强制设置为å¯è®¿é—®. + * 如å‘上转型到Object仿— æ³•找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) + { + // ä¸ºç©ºä¸æŠ¥é”™ã€‚ç›´æŽ¥è¿”å›ž null + if (obj == null) + { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) + { + try + { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } + catch (NoSuchFieldException e) + { + continue; + } + } + return null; + } + + /** + * 循环å‘上转型, 获å–对象的DeclaredMethod,并强制设置为å¯è®¿é—®. + * 如å‘上转型到Object仿— æ³•找到, 返回null. + * 匹é…函数å+傿•°ç±»åž‹ã€‚ + * 用于方法需è¦è¢«å¤šæ¬¡è°ƒç”¨çš„æƒ…况. 先使用本函数先å–å¾—Method,ç„¶åŽè°ƒç”¨Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class... parameterTypes) + { + // ä¸ºç©ºä¸æŠ¥é”™ã€‚ç›´æŽ¥è¿”å›ž null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + try + { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } + catch (NoSuchMethodException e) + { + continue; + } + } + return null; + } + + /** + * 循环å‘上转型, 获å–对象的DeclaredMethod,并强制设置为å¯è®¿é—®. + * 如å‘上转型到Object仿— æ³•找到, 返回null. + * åªåŒ¹é…函数å。 + * 用于方法需è¦è¢«å¤šæ¬¡è°ƒç”¨çš„æƒ…况. 先使用本函数先å–å¾—Method,ç„¶åŽè°ƒç”¨Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) + { + // ä¸ºç©ºä¸æŠ¥é”™ã€‚ç›´æŽ¥è¿”å›ž null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) + { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改å˜private/protected的方法为public,尽é‡ä¸è°ƒç”¨å®žé™…改动的语å¥ï¼Œé¿å…JDKçš„SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) + { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !isAccessible(method)) + { + method.setAccessible(true); + } + } + + /** + * 改å˜private/protectedçš„æˆå‘˜å˜é‡ä¸ºpublic,尽é‡ä¸è°ƒç”¨å®žé™…改动的语å¥ï¼Œé¿å…JDKçš„SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) + { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers())) && !isAccessible(field)) + { + field.setAccessible(true); + } + } + + /** + * 检查AccessibleObject是å¦å¯è®¿é—®ï¼Œå…¼å®¹Java 1.8å’ŒJava 9+版本 + * @param accessibleObject AccessibleObject实例 + * @return 是å¦å¯è®¿é—® + */ + private static boolean isAccessible(AccessibleObject accessibleObject) { + try { + // Java 9+ 使用canAccess方法 + Method canAccessMethod = AccessibleObject.class.getMethod("canAccess", Object.class); + return (Boolean) canAccessMethod.invoke(accessibleObject, new Object[] { null }); + } catch (Exception e) { + // Java 8 使用å射调用isAccessible方法æ¥é¿å…编译警告 + try { + Method isAccessibleMethod = AccessibleObject.class.getMethod("isAccessible"); + return (Boolean) isAccessibleMethod.invoke(accessibleObject); + } catch (Exception ex) { + // å¦‚æžœä¸¤ç§æ–¹æ³•都失败,默认返回false + return false; + } + } + } + + /** + * 通过åå°„, 获得Classå®šä¹‰ä¸­å£°æ˜Žçš„æ³›åž‹å‚æ•°çš„类型, æ³¨æ„æ³›åž‹å¿…须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) + { + return getClassGenricType(clazz, 0); + } + + /** + * 通过åå°„, 获得Classå®šä¹‰ä¸­å£°æ˜Žçš„çˆ¶ç±»çš„æ³›åž‹å‚æ•°çš„类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType(final Class clazz, final int index) + { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) + { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) + { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) + { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass(Object instance) + { + if (instance == null) + { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) + { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) + { + return superClass; + } + } + return clazz; + + } + + /** + * å°†åå°„æ—¶çš„checked exception转æ¢ä¸ºunchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) + { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) + { + return new IllegalArgumentException(msg, e); + } + else if (e instanceof InvocationTargetException) + { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java new file mode 100644 index 0000000..f2c1bfe --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java @@ -0,0 +1,291 @@ +package com.ruoyi.common.utils.sign; + +/** + * Base64工具类 + * + * @author ruoyi + */ +public final class Base64 +{ + static private final int BASELENGTH = 128; + static private final int LOOKUPLENGTH = 64; + static private final int TWENTYFOURBITGROUP = 24; + static private final int EIGHTBIT = 8; + static private final int SIXTEENBIT = 16; + static private final int FOURBYTE = 4; + static private final int SIGN = -128; + static private final char PAD = '='; + static final private byte[] base64Alphabet = new byte[BASELENGTH]; + static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; + + static + { + for (int i = 0; i < BASELENGTH; ++i) + { + base64Alphabet[i] = -1; + } + for (int i = 'Z'; i >= 'A'; i--) + { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) + { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) + { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i <= 25; i++) + { + lookUpBase64Alphabet[i] = (char) ('A' + i); + } + + for (int i = 26, j = 0; i <= 51; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('a' + j); + } + + for (int i = 52, j = 0; i <= 61; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('0' + j); + } + lookUpBase64Alphabet[62] = (char) '+'; + lookUpBase64Alphabet[63] = (char) '/'; + } + + private static boolean isWhiteSpace(char octect) + { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + private static boolean isPad(char octect) + { + return (octect == PAD); + } + + private static boolean isData(char octect) + { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) + { + if (binaryData == null) + { + return null; + } + + int lengthDataBits = binaryData.length * EIGHTBIT; + if (lengthDataBits == 0) + { + return ""; + } + + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet * 4]; + + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; + + int encodedIndex = 0; + int dataIndex = 0; + + for (int i = 0; i < numberTriplets; i++) + { + b1 = binaryData[dataIndex++]; + b2 = binaryData[dataIndex++]; + b3 = binaryData[dataIndex++]; + + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; + } + + // form integral number of 6-bit groups + if (fewerThan24bits == EIGHTBIT) + { + b1 = binaryData[dataIndex]; + k = (byte) (b1 & 0x03); + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; + encodedData[encodedIndex++] = PAD; + encodedData[encodedIndex++] = PAD; + } + else if (fewerThan24bits == SIXTEENBIT) + { + b1 = binaryData[dataIndex]; + b2 = binaryData[dataIndex + 1]; + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; + encodedData[encodedIndex++] = PAD; + } + return new String(encodedData); + } + + /** + * Decodes Base64 data into octects + * + * @param encoded string containing Base64 data + * @return Array containind decoded data. + */ + public static byte[] decode(String encoded) + { + if (encoded == null) + { + return null; + } + + char[] base64Data = encoded.toCharArray(); + // remove white spaces + int len = removeWhiteSpace(base64Data); + + if (len % FOURBYTE != 0) + { + return null;// should be divisible by four + } + + int numberQuadruple = (len / FOURBYTE); + + if (numberQuadruple == 0) + { + return new byte[0]; + } + + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; + + int i = 0; + int encodedIndex = 0; + int dataIndex = 0; + decodedData = new byte[(numberQuadruple) * 3]; + + for (; i < numberQuadruple - 1; i++) + { + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) + || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) + { + return null; + } // if found "no data" just return null + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + } + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) + { + return null;// if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData((d3)) || !isData((d4))) + {// Check if they are PAD characters + if (isPad(d3) && isPad(d4)) + { + if ((b2 & 0xf) != 0)// last 4 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 1]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + return tmp; + } + else if (!isPad(d3) && isPad(d4)) + { + b3 = base64Alphabet[d3]; + if ((b3 & 0x3) != 0)// last 2 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 2]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + return tmp; + } + else + { + return null; + } + } + else + { // No PAD e.g 3cQl + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + + } + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data the byte array of base64 data (with WS) + * @return the new length + */ + private static int removeWhiteSpace(char[] data) + { + if (data == null) + { + return 0; + } + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) + { + if (!isWhiteSpace(data[i])) + { + data[newSize++] = data[i]; + } + } + return newSize; + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java new file mode 100644 index 0000000..8fb0fc5 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java @@ -0,0 +1,67 @@ +package com.ruoyi.common.utils.sign; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Md5加密方法 + * + * @author ruoyi + */ +public class Md5Utils +{ + private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); + + private static byte[] md5(String s) + { + MessageDigest algorithm; + try + { + algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(s.getBytes("UTF-8")); + byte[] messageDigest = algorithm.digest(); + return messageDigest; + } + catch (Exception e) + { + log.error("MD5 Error...", e); + } + return null; + } + + private static final String toHex(byte hash[]) + { + if (hash == null) + { + return null; + } + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) + { + if ((hash[i] & 0xff) < 0x10) + { + buf.append("0"); + } + buf.append(Long.toString(hash[i] & 0xff, 16)); + } + return buf.toString(); + } + + public static String hash(String s) + { + try + { + return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + } + catch (Exception e) + { + log.error("not supported charset...{}", e); + return s; + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java new file mode 100644 index 0000000..2c251a9 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java @@ -0,0 +1,158 @@ +package com.ruoyi.common.utils.spring; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.StringUtils; + +/** + * spring工具类 方便在éžspring管ç†çŽ¯å¢ƒä¸­èŽ·å–bean + * + * @author ruoyi + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获å–对象 + * + * @param name + * @return Object 一个以所给å字注册的bean的实例 + * @throws org.springframework.beans.BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获å–类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包å«ä¸€ä¸ªä¸Žæ‰€ç»™å称匹é…çš„bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定å字注册的bean定义是一个singleton还是一个prototype。 如果与给定å字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的beanå字在bean定义中有别å,则返回这些别å + * + * @param name + * @return + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获å–aop代ç†å¯¹è±¡ + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获å–当å‰çš„环境é…置,无é…置返回null + * + * @return 当å‰çš„环境é…ç½® + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获å–当å‰çš„环境é…置,当有多个环境é…置时,åªèŽ·å–第一个 + * + * @return 当å‰çš„环境é…ç½® + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } + + /** + * 获å–é…置文件中的值 + * + * @param key é…置文件的key + * @return 当å‰çš„é…置文件的值 + * + */ + public static String getRequiredProperty(String key) + { + return applicationContext.getEnvironment().getRequiredProperty(key); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java new file mode 100644 index 0000000..40a800d --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java @@ -0,0 +1,61 @@ +package com.ruoyi.common.utils.sql; + +import com.ruoyi.common.exception.UtilException; +import com.ruoyi.common.utils.StringUtils; + +/** + * sqlæ“作工具类 + * + * @author ruoyi + */ +public class SqlUtil +{ + /** + * 定义常用的 sql关键字 + */ + public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()"; + + /** + * 仅支æŒå­—æ¯ã€æ•°å­—ã€ä¸‹åˆ’线ã€ç©ºæ ¼ã€é€—å·ã€å°æ•°ç‚¹ï¼ˆæ”¯æŒå¤šä¸ªå­—段排åºï¼‰ + */ + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new UtilException("傿•°ä¸ç¬¦åˆè§„范,ä¸èƒ½è¿›è¡ŒæŸ¥è¯¢"); + } + return value; + } + + /** + * éªŒè¯ order by 语法是å¦ç¬¦åˆè§„范 + */ + public static boolean isValidOrderBySql(String value) + { + return value.matches(SQL_PATTERN); + } + + /** + * SQL关键字检查 + */ + public static void filterKeyword(String value) + { + if (StringUtils.isEmpty(value)) + { + return; + } + String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); + for (String sqlKeyword : sqlKeywords) + { + if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) + { + throw new UtilException("傿•°å­˜åœ¨SQL注入风险"); + } + } + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java new file mode 100644 index 0000000..0256511 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.utils.uuid; + +/** + * ID生æˆå™¨å·¥å…·ç±» + * + * @author ruoyi + */ +public class IdUtils +{ + /** + * 获å–éšæœºUUID + * + * @return éšæœºUUID + */ + public static String randomUUID() + { + return UUID.randomUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线 + * + * @return 简化的UUID,去掉了横线 + */ + public static String simpleUUID() + { + return UUID.randomUUID().toString(true); + } + + /** + * 获å–éšæœºUUID,使用性能更好的ThreadLocalRandom生æˆUUID + * + * @return éšæœºUUID + */ + public static String fastUUID() + { + return UUID.fastUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生æˆUUID + * + * @return 简化的UUID,去掉了横线 + */ + public static String fastSimpleUUID() + { + return UUID.fastUUID().toString(true); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java new file mode 100644 index 0000000..3f621d5 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java @@ -0,0 +1,86 @@ +package com.ruoyi.common.utils.uuid; + +import java.util.concurrent.atomic.AtomicInteger; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * @author ruoyi åºåˆ—生æˆç±» + */ +public class Seq +{ + // 通用åºåˆ—类型 + public static final String commSeqType = "COMMON"; + + // 上传åºåˆ—类型 + public static final String uploadSeqType = "UPLOAD"; + + // 通用接å£åºåˆ—æ•° + private static AtomicInteger commSeq = new AtomicInteger(1); + + // 上传接å£åºåˆ—æ•° + private static AtomicInteger uploadSeq = new AtomicInteger(1); + + // 机器标识 + private static final String machineCode = "A"; + + /** + * 获å–通用åºåˆ—å· + * + * @return åºåˆ—值 + */ + public static String getId() + { + return getId(commSeqType); + } + + /** + * 默认16ä½åºåˆ—å· yyMMddHHmmss + 䏀使œºå™¨æ ‡è¯† + 3长度循环递增字符串 + * + * @return åºåˆ—值 + */ + public static String getId(String type) + { + AtomicInteger atomicInt = commSeq; + if (uploadSeqType.equals(type)) + { + atomicInt = uploadSeq; + } + return getId(atomicInt, 3); + } + + /** + * 通用接å£åºåˆ—å· yyMMddHHmmss + 䏀使œºå™¨æ ‡è¯† + length长度循环递增字符串 + * + * @param atomicInt åºåˆ—æ•° + * @param length 数值长度 + * @return åºåˆ—值 + */ + public static String getId(AtomicInteger atomicInt, int length) + { + String result = DateUtils.dateTimeNow(); + result += machineCode; + result += getSeq(atomicInt, length); + return result; + } + + /** + * åºåˆ—循环递增字符串[1, 10 çš„ (length)幂次方), 用0左补é½length使•° + * + * @return åºåˆ—值 + */ + private synchronized static String getSeq(AtomicInteger atomicInt, int length) + { + // å…ˆå–值å†+1 + int value = atomicInt.getAndIncrement(); + + // 如果更新åŽå€¼>=10 çš„ (length)幂次方则é‡ç½®ä¸º1 + int maxSeq = (int) Math.pow(10, length); + if (atomicInt.get() >= maxSeq) + { + atomicInt.set(1); + } + // 转字符串,用0å·¦è¡¥é½ + return StringUtils.padl(value, length); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java new file mode 100644 index 0000000..97497f2 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java @@ -0,0 +1,484 @@ +package com.ruoyi.common.utils.uuid; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import com.ruoyi.common.exception.UtilException; + +/** + * æä¾›é€šç”¨å”¯ä¸€è¯†åˆ«ç ï¼ˆuniversally unique identifier)(UUID)实现 + * + * @author ruoyi + */ +public final class UUID implements java.io.Serializable, Comparable +{ + private static final long serialVersionUID = -1185015143654744140L; + + /** + * SecureRandom çš„å•例 + * + */ + private static class Holder + { + static final SecureRandom numberGenerator = getSecureRandom(); + } + + /** æ­¤UUID的最高64æœ‰æ•ˆä½ */ + private final long mostSigBits; + + /** æ­¤UUID的最低64æœ‰æ•ˆä½ */ + private final long leastSigBits; + + /** + * ç§æœ‰æž„造 + * + * @param data æ•°æ® + */ + private UUID(byte[] data) + { + long msb = 0; + long lsb = 0; + assert data.length == 16 : "data must be 16 bytes in length"; + for (int i = 0; i < 8; i++) + { + msb = (msb << 8) | (data[i] & 0xff); + } + for (int i = 8; i < 16; i++) + { + lsb = (lsb << 8) | (data[i] & 0xff); + } + this.mostSigBits = msb; + this.leastSigBits = lsb; + } + + /** + * ä½¿ç”¨æŒ‡å®šçš„æ•°æ®æž„造新的 UUID。 + * + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 ä½ + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 ä½ + */ + public UUID(long mostSigBits, long leastSigBits) + { + this.mostSigBits = mostSigBits; + this.leastSigBits = leastSigBits; + } + + /** + * 获å–类型 4ï¼ˆä¼ªéšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚ã€‚ + * + * @return éšæœºç”Ÿæˆçš„ {@code UUID} + */ + public static UUID fastUUID() + { + return randomUUID(false); + } + + /** + * 获å–类型 4ï¼ˆä¼ªéšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚ã€‚ ä½¿ç”¨åŠ å¯†çš„å¼ºä¼ªéšæœºæ•°ç”Ÿæˆå™¨ç”Ÿæˆè¯¥ UUID。 + * + * @return éšæœºç”Ÿæˆçš„ {@code UUID} + */ + public static UUID randomUUID() + { + return randomUUID(true); + } + + /** + * 获å–类型 4ï¼ˆä¼ªéšæœºç”Ÿæˆçš„)UUID çš„é™æ€å·¥åŽ‚ã€‚ ä½¿ç”¨åŠ å¯†çš„å¼ºä¼ªéšæœºæ•°ç”Ÿæˆå™¨ç”Ÿæˆè¯¥ UUID。 + * + * @param isSecure 是å¦ä½¿ç”¨{@link SecureRandom}如果是å¯ä»¥èŽ·å¾—æ›´å®‰å…¨çš„éšæœºç ï¼Œå¦åˆ™å¯ä»¥å¾—到更好的性能 + * @return éšæœºç”Ÿæˆçš„ {@code UUID} + */ + public static UUID randomUUID(boolean isSecure) + { + final Random ng = isSecure ? Holder.numberGenerator : getRandom(); + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; /* clear version */ + randomBytes[6] |= 0x40; /* set to version 4 */ + randomBytes[8] &= 0x3f; /* clear variant */ + randomBytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(randomBytes); + } + + /** + * æ ¹æ®æŒ‡å®šçš„字节数组获å–类型 3(基于å称的)UUID çš„é™æ€å·¥åŽ‚ã€‚ + * + * @param name 用于构造 UUID 的字节数组。 + * + * @return æ ¹æ®æŒ‡å®šæ•°ç»„生æˆçš„ {@code UUID} + */ + public static UUID nameUUIDFromBytes(byte[] name) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException nsae) + { + throw new InternalError("MD5 not supported"); + } + byte[] md5Bytes = md.digest(name); + md5Bytes[6] &= 0x0f; /* clear version */ + md5Bytes[6] |= 0x30; /* set to version 3 */ + md5Bytes[8] &= 0x3f; /* clear variant */ + md5Bytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(md5Bytes); + } + + /** + * æ ¹æ® {@link #toString()} 方法中æè¿°çš„字符串标准表示形å¼åˆ›å»º{@code UUID}。 + * + * @param name 指定 {@code UUID} 字符串 + * @return 具有指定值的 {@code UUID} + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中æè¿°çš„字符串表示形å¼ä¸ç¬¦æŠ›å‡ºæ­¤å¼‚常 + * + */ + public static UUID fromString(String name) + { + String[] components = name.split("-"); + if (components.length != 5) + { + throw new IllegalArgumentException("Invalid UUID string: " + name); + } + for (int i = 0; i < 5; i++) + { + components[i] = "0x" + components[i]; + } + + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new UUID(mostSigBits, leastSigBits); + } + + /** + * 返回此 UUID çš„ 128 ä½å€¼ä¸­çš„æœ€ä½Žæœ‰æ•ˆ 64 ä½ã€‚ + * + * @return æ­¤ UUID çš„ 128 ä½å€¼ä¸­çš„æœ€ä½Žæœ‰æ•ˆ 64 ä½ã€‚ + */ + public long getLeastSignificantBits() + { + return leastSigBits; + } + + /** + * 返回此 UUID çš„ 128 ä½å€¼ä¸­çš„æœ€é«˜æœ‰æ•ˆ 64 ä½ã€‚ + * + * @return æ­¤ UUID çš„ 128 ä½å€¼ä¸­æœ€é«˜æœ‰æ•ˆ 64 ä½ã€‚ + */ + public long getMostSignificantBits() + { + return mostSigBits; + } + + /** + * 与此 {@code UUID} 相关è”的版本å·. ç‰ˆæœ¬å·æè¿°æ­¤ {@code UUID} 是如何生æˆçš„。 + *

+ * 版本å·å…·æœ‰ä»¥ä¸‹å«æ„: + *

    + *
  • 1 基于时间的 UUID + *
  • 2 DCE 安全 UUID + *
  • 3 基于åç§°çš„ UUID + *
  • 4 éšæœºç”Ÿæˆçš„ UUID + *
+ * + * @return æ­¤ {@code UUID} çš„ç‰ˆæœ¬å· + */ + public int version() + { + // Version is bits masked by 0x000000000000F000 in MS long + return (int) ((mostSigBits >> 12) & 0x0f); + } + + /** + * 与此 {@code UUID} 相关è”çš„å˜ä½“å·ã€‚å˜ä½“å·æè¿° {@code UUID} 的布局。 + *

+ * å˜ä½“å·å…·æœ‰ä»¥ä¸‹å«æ„: + *

    + *
  • 0 为 NCS å‘åŽå…¼å®¹ä¿ç•™ + *
  • 2 IETF RFC 4122(Leach-Salz), 用于此类 + *
  • 6 ä¿ç•™ï¼Œå¾®è½¯å‘åŽå…¼å®¹ + *
  • 7 ä¿ç•™ä¾›ä»¥åŽå®šä¹‰ä½¿ç”¨ + *
+ * + * @return æ­¤ {@code UUID} 相关è”çš„å˜ä½“å· + */ + public int variant() + { + // This field is composed of a varying number of bits. + // 0 - - Reserved for NCS backward compatibility + // 1 0 - The IETF aka Leach-Salz variant (used by this class) + // 1 1 0 Reserved, Microsoft backward compatibility + // 1 1 1 Reserved for future definition. + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); + } + + /** + * 与此 UUID 相关è”的时间戳值。 + * + *

+ * 60 ä½çš„æ—¶é—´æˆ³å€¼æ ¹æ®æ­¤ {@code UUID} çš„ time_lowã€time_mid å’Œ time_hi 字段构造。
+ * 所得到的时间戳以 100 毫微秒为å•ä½ï¼Œä»Ž UTC(通用å调时间) 1582 å¹´ 10 月 15 日零时开始。 + * + *

+ * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1ï¼‰ä¸­æ‰æœ‰æ„义。
+ * 如果此 {@code UUID} 䏿˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出 UnsupportedOperationException。 + * + * @throws UnsupportedOperationException 如果此 {@code UUID} 䏿˜¯ version 为 1 çš„ UUID。 + */ + public long timestamp() throws UnsupportedOperationException + { + checkTimeBase(); + return (mostSigBits & 0x0FFFL) << 48// + | ((mostSigBits >> 16) & 0x0FFFFL) << 32// + | mostSigBits >>> 32; + } + + /** + * 与此 UUID 相关è”的时钟åºåˆ—值。 + * + *

+ * 14 ä½çš„æ—¶é’Ÿåºåˆ—å€¼æ ¹æ®æ­¤ UUID çš„ clock_seq 字段构造。clock_seq 字段用于ä¿è¯åœ¨åŸºäºŽæ—¶é—´çš„ UUID 中的时间唯一性。 + *

+ * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1ï¼‰ä¸­æ‰æœ‰æ„义。 如果此 UUID 䏿˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出 + * UnsupportedOperationException。 + * + * @return æ­¤ {@code UUID} 的时钟åºåˆ— + * + * @throws UnsupportedOperationException 如果此 UUID çš„ version ä¸ä¸º 1 + */ + public int clockSequence() throws UnsupportedOperationException + { + checkTimeBase(); + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + + /** + * 与此 UUID 相关的节点值。 + * + *

+ * 48 ä½çš„èŠ‚ç‚¹å€¼æ ¹æ®æ­¤ UUID çš„ node 字段构造。此字段旨在用于ä¿å­˜æœºå™¨çš„ IEEE 802 地å€ï¼Œè¯¥åœ°å€ç”¨äºŽç”Ÿæˆæ­¤ UUID 以ä¿è¯ç©ºé—´å”¯ä¸€æ€§ã€‚ + *

+ * 节点值仅在基于时间的 UUID(其 version 类型为 1ï¼‰ä¸­æ‰æœ‰æ„义。
+ * 如果此 UUID 䏿˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出 UnsupportedOperationException。 + * + * @return æ­¤ {@code UUID} 的节点值 + * + * @throws UnsupportedOperationException 如果此 UUID çš„ version ä¸ä¸º 1 + */ + public long node() throws UnsupportedOperationException + { + checkTimeBase(); + return leastSigBits & 0x0000FFFFFFFFFFFFL; + } + + /** + * 返回此{@code UUID} 的字符串表现形å¼ã€‚ + * + *

+ * UUID 的字符串表示形å¼ç”±æ­¤ BNF æè¿°ï¼š + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @return æ­¤{@code UUID} çš„å­—ç¬¦ä¸²è¡¨çŽ°å½¢å¼ + * @see #toString(boolean) + */ + @Override + public String toString() + { + return toString(false); + } + + /** + * 返回此{@code UUID} 的字符串表现形å¼ã€‚ + * + *

+ * UUID 的字符串表示形å¼ç”±æ­¤ BNF æè¿°ï¼š + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @param isSimple 是å¦ç®€å•模å¼ï¼Œç®€å•模å¼ä¸ºä¸å¸¦'-'çš„UUID字符串 + * @return æ­¤{@code UUID} çš„å­—ç¬¦ä¸²è¡¨çŽ°å½¢å¼ + */ + public String toString(boolean isSimple) + { + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); + // time_low + builder.append(digits(mostSigBits >> 32, 8)); + if (!isSimple) + { + builder.append('-'); + } + // time_mid + builder.append(digits(mostSigBits >> 16, 4)); + if (!isSimple) + { + builder.append('-'); + } + // time_high_and_version + builder.append(digits(mostSigBits, 4)); + if (!isSimple) + { + builder.append('-'); + } + // variant_and_sequence + builder.append(digits(leastSigBits >> 48, 4)); + if (!isSimple) + { + builder.append('-'); + } + // node + builder.append(digits(leastSigBits, 12)); + + return builder.toString(); + } + + /** + * 返回此 UUID 的哈希ç ã€‚ + * + * @return UUID 的哈希ç å€¼ã€‚ + */ + @Override + public int hashCode() + { + long hilo = mostSigBits ^ leastSigBits; + return ((int) (hilo >> 32)) ^ (int) hilo; + } + + /** + * 将此对象与指定对象比较。 + *

+ * 当䏔仅当傿•°ä¸ä¸º {@code null}ã€è€Œæ˜¯ä¸€ä¸ª UUID 对象ã€å…·æœ‰ä¸Žæ­¤ UUID 相åŒçš„ varriantã€åŒ…å«ç›¸åŒçš„值(æ¯ä¸€ä½å‡ç›¸åŒï¼‰æ—¶ï¼Œç»“æžœæ‰ä¸º {@code true}。 + * + * @param obj è¦ä¸Žä¹‹æ¯”较的对象 + * + * @return 如果对象相åŒï¼Œåˆ™è¿”回 {@code true}ï¼›å¦åˆ™è¿”回 {@code false} + */ + @Override + public boolean equals(Object obj) + { + if ((null == obj) || (obj.getClass() != UUID.class)) + { + return false; + } + UUID id = (UUID) obj; + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); + } + + // Comparison Operations + + /** + * 将此 UUID 与指定的 UUID 比较。 + * + *

+ * 如果两个 UUID ä¸åŒï¼Œä¸”第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 + * + * @param val 与此 UUID 比较的 UUID + * + * @return 在此 UUID å°äºŽã€ç­‰äºŽæˆ–大于 val 时,分别返回 -1ã€0 或 1。 + * + */ + @Override + public int compareTo(UUID val) + { + // The ordering is intentionally set up so that the UUIDs + // can simply be numerically compared as two numbers + return (this.mostSigBits < val.mostSigBits ? -1 : // + (this.mostSigBits > val.mostSigBits ? 1 : // + (this.leastSigBits < val.leastSigBits ? -1 : // + (this.leastSigBits > val.leastSigBits ? 1 : // + 0)))); + } + + // ------------------------------------------------------------------------------------------------------------------- + // Private method start + /** + * 返回指定数字对应的hex值 + * + * @param val 值 + * @param digits ä½ + * @return 值 + */ + private static String digits(long val, int digits) + { + long hi = 1L << (digits * 4); + return Long.toHexString(hi | (val & (hi - 1))).substring(1); + } + + /** + * 检查是å¦ä¸ºtime-based版本UUID + */ + private void checkTimeBase() + { + if (version() != 1) + { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + } + + /** + * 获å–{@link SecureRandom},类æä¾›åŠ å¯†çš„å¼ºéšæœºæ•°ç”Ÿæˆå™¨ (RNG) + * + * @return {@link SecureRandom} + */ + public static SecureRandom getSecureRandom() + { + try + { + return SecureRandom.getInstance("SHA1PRNG"); + } + catch (NoSuchAlgorithmException e) + { + throw new UtilException(e); + } + } + + /** + * 获å–éšæœºæ•°ç”Ÿæˆå™¨å¯¹è±¡
+ * ThreadLocalRandom是JDK 7ä¹‹åŽæä¾›å¹¶å‘äº§ç”Ÿéšæœºæ•°ï¼Œèƒ½å¤Ÿè§£å†³å¤šä¸ªçº¿ç¨‹å‘生的竞争争夺。 + * + * @return {@link ThreadLocalRandom} + */ + public static ThreadLocalRandom getRandom() + { + return ThreadLocalRandom.current(); + } +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java new file mode 100644 index 0000000..14e43dc --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java @@ -0,0 +1,27 @@ +package com.ruoyi.common.xss; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义xss校验注解 + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER }) +@Constraint(validatedBy = { XssValidator.class }) +public @interface Xss +{ + String message() + + default "ä¸å…许任何脚本è¿è¡Œ"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java new file mode 100644 index 0000000..34d0700 --- /dev/null +++ b/examapi/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.xss; + +import com.ruoyi.common.utils.StringUtils; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 自定义xss校验注解实现 + * + * @author ruoyi + */ +public class XssValidator implements ConstraintValidator +{ + private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />"; + + @Override + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) + { + if (StringUtils.isBlank(value)) + { + return true; + } + return !containsHtml(value); + } + + public static boolean containsHtml(String value) + { + Pattern pattern = Pattern.compile(HTML_PATTERN); + Matcher matcher = pattern.matcher(value); + return matcher.matches(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-framework/pom.xml b/examapi/ruoyi-framework/pom.xml new file mode 100644 index 0000000..0ea71fc --- /dev/null +++ b/examapi/ruoyi-framework/pom.xml @@ -0,0 +1,70 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-framework + + + framework框架核心 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + com.alibaba + druid-spring-boot-starter + + + + + pro.fessional + kaptcha + + + servlet-api + javax.servlet + + + + + + + com.github.oshi + oshi-core + + + + + com.ruoyi + ruoyi-system + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java new file mode 100644 index 0000000..35a6b50 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -0,0 +1,174 @@ +package com.ruoyi.framework.aspectj; + +import java.util.ArrayList; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.security.context.PermissionContextHolder; + +/** + * æ•°æ®è¿‡æ»¤å¤„ç† + * + * @author ruoyi + */ +@Aspect +@Component +public class DataScopeAspect +{ + /** + * å…¨éƒ¨æ•°æ®æƒé™ + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * è‡ªå®šæ•°æ®æƒé™ + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * éƒ¨é—¨æ•°æ®æƒé™ + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门åŠä»¥ä¸‹æ•°æ®æƒé™ + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * ä»…æœ¬äººæ•°æ®æƒé™ + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * æ•°æ®æƒé™è¿‡æ»¤å…³é”®å­— + */ + public static final String DATA_SCOPE = "dataScope"; + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable + { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) + { + // 获å–当å‰çš„用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管ç†å‘˜ï¼Œåˆ™ä¸è¿‡æ»¤æ•°æ® + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias(), permission); + } + } + } + + /** + * æ•°æ®èŒƒå›´è¿‡æ»¤ + * + * @param joinPoint 切点 + * @param user 用户 + * @param deptAlias 部门别å + * @param userAlias 用户别å + * @param permission æƒé™å­—符 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission) + { + StringBuilder sqlString = new StringBuilder(); + List conditions = new ArrayList(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) + { + continue; + } + if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) + && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) + { + continue; + } + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + conditions.add(dataScope); + break; + } + else if (DATA_SCOPE_CUSTOM.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } + else if (DATA_SCOPE_DEPT.equals(dataScope)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } + else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } + else if (DATA_SCOPE_SELF.equals(dataScope)) + { + if (StringUtils.isNotBlank(userAlias)) + { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } + else + { + // æ•°æ®æƒé™ä¸ºä»…本人且没有userAlias别å䏿Ÿ¥è¯¢ä»»ä½•æ•°æ® + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + + // 多角色情况下,所有角色都ä¸åŒ…å«ä¼ é€’过æ¥çš„æƒé™å­—符,这个时候sqlString也会为空,所以è¦é™åˆ¶ä¸€ä¸‹,䏿Ÿ¥è¯¢ä»»ä½•æ•°æ® + if (StringUtils.isEmpty(conditions)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + + if (StringUtils.isNotBlank(sqlString.toString())) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 拼接æƒé™sqlå‰å…ˆæ¸…空params.dataScope傿•°é˜²æ­¢æ³¨å…¥ + */ + private void clearDataScope(final JoinPoint joinPoint) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java new file mode 100644 index 0000000..4648fcd --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java @@ -0,0 +1,72 @@ +package com.ruoyi.framework.aspectj; + +import java.util.Objects; +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 org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataSource; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; + +/** + * å¤šæ•°æ®æºå¤„ç† + * + * @author ruoyi + */ +@Aspect +@Order(1) +@Component +public class DataSourceAspect +{ + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" + + "|| @within(com.ruoyi.common.annotation.DataSource)") + public void dsPointCut() + { + + } + + @Around("dsPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable + { + DataSource dataSource = getDataSource(point); + + if (StringUtils.isNotNull(dataSource)) + { + DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); + } + + try + { + return point.proceed(); + } + finally + { + // é”€æ¯æ•°æ®æº åœ¨æ‰§è¡Œæ–¹æ³•ä¹‹åŽ + DynamicDataSourceContextHolder.clearDataSourceType(); + } + } + + /** + * 获å–需è¦åˆ‡æ¢çš„æ•°æ®æº + */ + public DataSource getDataSource(ProceedingJoinPoint point) + { + MethodSignature signature = (MethodSignature) point.getSignature(); + DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); + if (Objects.nonNull(dataSource)) + { + return dataSource; + } + + return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java new file mode 100644 index 0000000..006a8b9 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -0,0 +1,249 @@ +package com.ruoyi.framework.aspectj; + +import java.util.Collection; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.NamedThreadLocal; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessStatus; +import com.ruoyi.common.enums.HttpMethod; +import com.ruoyi.common.filter.PropertyPreExcludeFilter; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.system.domain.SysOperLog; + +/** + * æ“ä½œæ—¥å¿—è®°å½•å¤„ç† + * + * @author ruoyi + */ +@Aspect +@Component +public class LogAspect +{ + private static final Logger log = LoggerFactory.getLogger(LogAspect.class); + + /** æŽ’é™¤æ•æ„Ÿå±žæ€§å­—段 */ + public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; + + /** 计算æ“作消耗时间 */ + private static final ThreadLocal TIME_THREADLOCAL = new NamedThreadLocal("Cost Time"); + + /** + * 处ç†è¯·æ±‚剿‰§è¡Œ + */ + @Before(value = "@annotation(controllerLog)") + public void boBefore(JoinPoint joinPoint, Log controllerLog) + { + TIME_THREADLOCAL.set(System.currentTimeMillis()); + } + + /** + * 处ç†å®Œè¯·æ±‚åŽæ‰§è¡Œ + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) + { + handleLog(joinPoint, controllerLog, null, jsonResult); + } + + /** + * 拦截异常æ“作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) + { + handleLog(joinPoint, controllerLog, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) + { + try + { + // 获å–当å‰çš„用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // *========æ•°æ®åº“日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // è¯·æ±‚çš„åœ°å€ + String ip = IpUtils.getIpAddr(); + operLog.setOperIp(ip); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); + if (loginUser != null) + { + operLog.setOperName(loginUser.getUsername()); + } + + if (e != null) + { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法åç§° + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // è®¾ç½®è¯·æ±‚æ–¹å¼ + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处ç†è®¾ç½®æ³¨è§£ä¸Šçš„傿•° + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 设置消耗时间 + operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get()); + // ä¿å­˜æ•°æ®åº“ + AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("异常信æ¯:{}", exp.getMessage()); + exp.printStackTrace(); + } + finally + { + TIME_THREADLOCAL.remove(); + } + } + + /** + * èŽ·å–æ³¨è§£ä¸­å¯¹æ–¹æ³•çš„æè¿°ä¿¡æ¯ 用于Controller层注解 + * + * @param log 日志 + * @param operLog æ“作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception + { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置æ“作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是å¦éœ€è¦ä¿å­˜requestï¼Œå‚æ•°å’Œå€¼ + if (log.isSaveRequestData()) + { + // 获å–傿•°çš„ä¿¡æ¯ï¼Œä¼ å…¥åˆ°æ•°æ®åº“中。 + setRequestValue(joinPoint, operLog, log.excludeParamNames()); + } + // 是å¦éœ€è¦ä¿å­˜responseï¼Œå‚æ•°å’Œå€¼ + if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) + { + operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); + } + } + + /** + * 获å–è¯·æ±‚çš„å‚æ•°ï¼Œæ”¾åˆ°log中 + * + * @param operLog æ“作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception + { + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); + String requestMethod = operLog.getRequestMethod(); + if (StringUtils.isEmpty(paramsMap) + && (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))) + { + String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000)); + } + } + + /** + * 傿•°æ‹¼è£… + */ + private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (Object o : paramsArray) + { + if (StringUtils.isNotNull(o) && !isFilterObject(o)) + { + try + { + String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); + params += jsonObj.toString() + " "; + } + catch (Exception e) + { + } + } + } + } + return params.trim(); + } + + /** + * å¿½ç•¥æ•æ„Ÿå±žæ€§ + */ + public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames) + { + return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames)); + } + + /** + * 判断是å¦éœ€è¦è¿‡æ»¤çš„对象。 + * + * @param o 对象信æ¯ã€‚ + * @return 如果是需è¦è¿‡æ»¤çš„对象,则返回trueï¼›å¦åˆ™è¿”回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Object value : collection) + { + return value instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Object value : map.entrySet()) + { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java new file mode 100644 index 0000000..a2015d7 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -0,0 +1,89 @@ +package com.ruoyi.framework.aspectj; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.RateLimiter; +import com.ruoyi.common.enums.LimitType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; + +/** + * 陿µå¤„ç† + * + * @author ruoyi + */ +@Aspect +@Component +public class RateLimiterAspect +{ + private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); + + private RedisTemplate redisTemplate; + + private RedisScript limitScript; + + @Autowired + public void setRedisTemplate1(RedisTemplate redisTemplate) + { + this.redisTemplate = redisTemplate; + } + + @Autowired + public void setLimitScript(RedisScript limitScript) + { + this.limitScript = limitScript; + } + + @Before("@annotation(rateLimiter)") + public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable + { + int time = rateLimiter.time(); + int count = rateLimiter.count(); + + String combineKey = getCombineKey(rateLimiter, point); + List keys = Collections.singletonList(combineKey); + try + { + Long number = redisTemplate.execute(limitScript, keys, count, time); + if (StringUtils.isNull(number) || number.intValue() > count) + { + throw new ServiceException("访问过于频ç¹ï¼Œè¯·ç¨å€™å†è¯•"); + } + log.info("é™åˆ¶è¯·æ±‚'{}',当å‰è¯·æ±‚'{}',缓存key'{}'", count, number.intValue(), combineKey); + } + catch (ServiceException e) + { + throw e; + } + catch (Exception e) + { + throw new RuntimeException("æœåС噍陿µå¼‚常,请ç¨å€™å†è¯•"); + } + } + + public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) + { + StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); + if (rateLimiter.limitType() == LimitType.IP) + { + stringBuffer.append(IpUtils.getIpAddr()).append("-"); + } + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + Class targetClass = method.getDeclaringClass(); + stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); + return stringBuffer.toString(); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java new file mode 100644 index 0000000..4f53e70 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -0,0 +1,30 @@ +package com.ruoyi.framework.config; + +import java.util.TimeZone; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * ç¨‹åºæ³¨è§£é…ç½® + * + * @author ruoyi + */ +@Configuration +// 表示通过aop框架暴露该代ç†å¯¹è±¡,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// æŒ‡å®šè¦æ‰«æçš„Mapper类的包的路径 +@MapperScan({"com.ruoyi.**.mapper", "com.yanzhu.exam.**.mapper"}) +public class ApplicationConfig +{ + /** + * 时区é…ç½® + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java new file mode 100644 index 0000000..43e78ae --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package com.ruoyi.framework.config; + +import java.util.Properties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import static com.google.code.kaptcha.Constants.*; + +/** + * 验è¯ç é…ç½® + * + * @author ruoyi + */ +@Configuration +public class CaptchaConfig +{ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // æ˜¯å¦æœ‰è¾¹æ¡† 默认为true 我们å¯ä»¥è‡ªå·±è®¾ç½®yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 验è¯ç æ–‡æœ¬å­—符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 验è¯ç å›¾ç‰‡å®½åº¦ 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验è¯ç å›¾ç‰‡é«˜åº¦ 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验è¯ç æ–‡æœ¬å­—ç¬¦å¤§å° é»˜è®¤ä¸º40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 验è¯ç æ–‡æœ¬å­—符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 验è¯ç æ–‡æœ¬å­—ä½“æ ·å¼ é»˜è®¤ä¸ºnew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // å›¾ç‰‡æ ·å¼ æ°´çº¹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // æ˜¯å¦æœ‰è¾¹æ¡† 默认为true 我们å¯ä»¥è‡ªå·±è®¾ç½®yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 边框颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 验è¯ç æ–‡æœ¬å­—符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 验è¯ç å›¾ç‰‡å®½åº¦ 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验è¯ç å›¾ç‰‡é«˜åº¦ 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验è¯ç æ–‡æœ¬å­—ç¬¦å¤§å° é»˜è®¤ä¸º40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 验è¯ç æ–‡æœ¬ç”Ÿæˆå™¨ + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator"); + // 验è¯ç æ–‡æœ¬å­—ç¬¦é—´è· é»˜è®¤ä¸º2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 验è¯ç æ–‡æœ¬å­—符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 验è¯ç æ–‡æœ¬å­—ä½“æ ·å¼ é»˜è®¤ä¸ºnew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 验è¯ç å™ªç‚¹é¢œè‰² 默认为Color.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 干扰实现类 + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // å›¾ç‰‡æ ·å¼ æ°´çº¹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java new file mode 100644 index 0000000..f671b3a --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java @@ -0,0 +1,126 @@ +package com.ruoyi.framework.config; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.sql.DataSource; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.util.Utils; +import com.ruoyi.common.enums.DataSourceType; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.framework.config.properties.DruidProperties; +import com.ruoyi.framework.datasource.DynamicDataSource; + +/** + * druid é…ç½®å¤šæ•°æ®æº + * + * @author ruoyi + */ +@Configuration +public class DruidConfig +{ + @Bean + @ConfigurationProperties("spring.datasource.druid.master") + public DataSource masterDataSource(DruidProperties druidProperties) + { + DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); + return druidProperties.dataSource(dataSource); + } + + @Bean + @ConfigurationProperties("spring.datasource.druid.slave") + @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") + public DataSource slaveDataSource(DruidProperties druidProperties) + { + DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); + return druidProperties.dataSource(dataSource); + } + + @Bean(name = "dynamicDataSource") + @Primary + public DynamicDataSource dataSource(DataSource masterDataSource) + { + Map targetDataSources = new HashMap<>(); + targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); + setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); + return new DynamicDataSource(masterDataSource, targetDataSources); + } + + /** + * è®¾ç½®æ•°æ®æº + * + * @param targetDataSources å¤‡é€‰æ•°æ®æºé›†åˆ + * @param sourceName æ•°æ®æºåç§° + * @param beanName beanåç§° + */ + public void setDataSource(Map targetDataSources, String sourceName, String beanName) + { + try + { + DataSource dataSource = SpringUtils.getBean(beanName); + targetDataSources.put(sourceName, dataSource); + } + catch (Exception e) + { + } + } + + /** + * 去除监控页é¢åº•部的广告 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") + public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) + { + // 获å–web监控页é¢çš„傿•° + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); + // æå–common.jsçš„é…置路径 + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); + final String filePath = "support/http/resources/js/common.js"; + // 创建filter进行过滤 + Filter filter = new Filter() + { + @Override + public void init(javax.servlet.FilterConfig filterConfig) throws ServletException + { + } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + chain.doFilter(request, response); + // é‡ç½®ç¼“冲区,å“应头ä¸ä¼šè¢«é‡ç½® + response.resetBuffer(); + // 获å–common.js + String text = Utils.readFromResource(filePath); + // 正则替æ¢banner, é™¤åŽ»åº•éƒ¨çš„å¹¿å‘Šä¿¡æ¯ + text = text.replaceAll("
", ""); + text = text.replaceAll("powered.*?shrek.wang", ""); + response.getWriter().write(text); + } + @Override + public void destroy() + { + } + }; + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(filter); + registrationBean.addUrlPatterns(commonJsPattern); + return registrationBean; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..9503f25 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,48 @@ +package com.ruoyi.framework.config; + +import java.nio.charset.Charset; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; + +/** + * Redis使用FastJsonåºåˆ—化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + public FastJson2JsonRedisSerializer(Class clazz) + { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException + { + if (t == null) + { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException + { + if (bytes == null || bytes.length <= 0) + { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java new file mode 100644 index 0000000..610807a --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java @@ -0,0 +1,58 @@ +package com.ruoyi.framework.config; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.ruoyi.common.filter.RepeatableFilter; +import com.ruoyi.common.filter.XssFilter; +import com.ruoyi.common.utils.StringUtils; + +/** + * Filteré…ç½® + * + * @author ruoyi + */ +@Configuration +public class FilterConfig +{ + @Value("${xss.excludes}") + private String excludes; + + @Value("${xss.urlPatterns}") + private String urlPatterns; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") + public FilterRegistrationBean xssFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); + registration.setName("xssFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap(); + initParameters.put("excludes", excludes); + registration.setInitParameters(initParameters); + return registration; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean someFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new RepeatableFilter()); + registration.addUrlPatterns("/*"); + registration.setName("repeatableFilter"); + registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); + return registration; + } + +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java new file mode 100644 index 0000000..7f8e1d5 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java @@ -0,0 +1,68 @@ +package com.ruoyi.framework.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 验è¯ç æ–‡æœ¬ç”Ÿæˆå™¨ + * + * @author ruoyi + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = random.nextInt(3); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if ((x != 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else + { + if (x >= y) + { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } + else + { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java new file mode 100644 index 0000000..e30fe74 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java @@ -0,0 +1,132 @@ +package com.ruoyi.framework.config; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import javax.sql.DataSource; +import org.apache.ibatis.io.VFS; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.util.ClassUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * Mybatis支æŒ*åŒ¹é…æ‰«æåŒ… + * + * @author ruoyi + */ +@Configuration +public class MyBatisConfig +{ + @Autowired + private Environment env; + + static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; + + public static String setTypeAliasesPackage(String typeAliasesPackage) + { + ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver(); + MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); + List allResult = new ArrayList(); + try + { + for (String aliasesPackage : typeAliasesPackage.split(",")) + { + List result = new ArrayList(); + aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN; + Resource[] resources = resolver.getResources(aliasesPackage); + if (resources != null && resources.length > 0) + { + MetadataReader metadataReader = null; + for (Resource resource : resources) + { + if (resource.isReadable()) + { + metadataReader = metadataReaderFactory.getMetadataReader(resource); + try + { + result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); + } + catch (ClassNotFoundException e) + { + e.printStackTrace(); + } + } + } + } + if (result.size() > 0) + { + HashSet hashResult = new HashSet(result); + allResult.addAll(hashResult); + } + } + if (allResult.size() > 0) + { + typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0])); + } + else + { + throw new RuntimeException("mybatis typeAliasesPackage 路径扫æé”™è¯¯,傿•°typeAliasesPackage:" + typeAliasesPackage + "未找到任何包"); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + return typeAliasesPackage; + } + + public Resource[] resolveMapperLocations(String[] mapperLocations) + { + ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); + List resources = new ArrayList(); + if (mapperLocations != null) + { + for (String mapperLocation : mapperLocations) + { + try + { + Resource[] mappers = resourceResolver.getResources(mapperLocation); + resources.addAll(Arrays.asList(mappers)); + } + catch (IOException e) + { + // ignore + } + } + } + return resources.toArray(new Resource[resources.size()]); + } + + @Bean + public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception + { + String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage"); + String mapperLocations = env.getProperty("mybatis.mapperLocations"); + String configLocation = env.getProperty("mybatis.configLocation"); + typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage); + VFS.addImplClass(SpringBootVFS.class); + + final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setTypeAliasesPackage(typeAliasesPackage); + sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ","))); + sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); + return sessionFactory.getObject(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java new file mode 100644 index 0000000..b188ac2 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -0,0 +1,69 @@ +package com.ruoyi.framework.config; + +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redisé…ç½® + * + * @author ruoyi + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport +{ + @Bean + @SuppressWarnings(value = { "unchecked", "rawtypes" }) + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) + { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + // 使用StringRedisSerializeræ¥åºåˆ—化和ååºåˆ—化redisçš„key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + + // Hashçš„key也采用StringRedisSerializerçš„åºåˆ—åŒ–æ–¹å¼ + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } + + @Bean + public DefaultRedisScript limitScript() + { + DefaultRedisScript redisScript = new DefaultRedisScript<>(); + redisScript.setScriptText(limitScriptText()); + redisScript.setResultType(Long.class); + return redisScript; + } + + /** + * 陿µè„šæœ¬ + */ + private String limitScriptText() + { + return "local key = KEYS[1]\n" + + "local count = tonumber(ARGV[1])\n" + + "local time = tonumber(ARGV[2])\n" + + "local current = redis.call('get', key);\n" + + "if current and tonumber(current) > count then\n" + + " return tonumber(current);\n" + + "end\n" + + "current = redis.call('incr', key)\n" + + "if tonumber(current) == 1 then\n" + + " redis.call('expire', key, time)\n" + + "end\n" + + "return tonumber(current);"; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java new file mode 100644 index 0000000..4e067a7 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.framework.config; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 通用é…ç½® + * + * @author ruoyi + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer +{ + @Autowired + private RepeatSubmitInterceptor repeatSubmitInterceptor; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**") + .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); + + /** swaggeré…ç½® */ + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/") + .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());; + } + + /** + * 自定义拦截规则 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); + } + + /** + * 跨域é…ç½® + */ + @Bean + public CorsFilter corsFilter() + { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问æºåœ°å€ + config.addAllowedOriginPattern("*"); + // 设置访问æºè¯·æ±‚头 + config.addAllowedHeader("*"); + // 设置访问æºè¯·æ±‚方法 + config.addAllowedMethod("*"); + // 有效期 1800ç§’ + config.setMaxAge(1800L); + // 添加映射路径,拦截一切请求 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + // 返回新的CorsFilter + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java new file mode 100644 index 0000000..bdb7199 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -0,0 +1,148 @@ +package com.ruoyi.framework.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.web.filter.CorsFilter; +import com.ruoyi.framework.config.properties.PermitAllUrlProperties; +import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; +import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; +import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; + +/** + * spring securityé…ç½® + * + * @author ruoyi + */ +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter +{ + /** + * 自定义用户认è¯é€»è¾‘ + */ + @Autowired + private UserDetailsService userDetailsService; + + /** + * 认è¯å¤±è´¥å¤„ç†ç±» + */ + @Autowired + private AuthenticationEntryPointImpl unauthorizedHandler; + + /** + * 退出处ç†ç±» + */ + @Autowired + private LogoutSuccessHandlerImpl logoutSuccessHandler; + + /** + * token认è¯è¿‡æ»¤å™¨ + */ + @Autowired + private JwtAuthenticationTokenFilter authenticationTokenFilter; + + /** + * 跨域过滤器 + */ + @Autowired + private CorsFilter corsFilter; + + /** + * å…许匿åè®¿é—®çš„åœ°å€ + */ + @Autowired + private PermitAllUrlProperties permitAllUrl; + + /** + * 解决 无法直接注入 AuthenticationManager + * + * @return + * @throws Exception + */ + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception + { + return super.authenticationManagerBean(); + } + + /** + * anyRequest | åŒ¹é…æ‰€æœ‰è¯·æ±‚路径 + * access | SpringEl表达å¼ç»“果为trueæ—¶å¯ä»¥è®¿é—® + * anonymous | 匿åå¯ä»¥è®¿é—® + * denyAll | 用户ä¸èƒ½è®¿é—® + * fullyAuthenticated | 用户完全认è¯å¯ä»¥è®¿é—®ï¼ˆéžremember-me下自动登录) + * hasAnyAuthority | å¦‚æžœæœ‰å‚æ•°ï¼Œå‚数表示æƒé™ï¼Œåˆ™å…¶ä¸­ä»»ä½•一个æƒé™å¯ä»¥è®¿é—® + * hasAnyRole | å¦‚æžœæœ‰å‚æ•°ï¼Œå‚数表示角色,则其中任何一个角色å¯ä»¥è®¿é—® + * hasAuthority | å¦‚æžœæœ‰å‚æ•°ï¼Œå‚数表示æƒé™ï¼Œåˆ™å…¶æƒé™å¯ä»¥è®¿é—® + * hasIpAddress | å¦‚æžœæœ‰å‚æ•°ï¼Œå‚数表示IP地å€ï¼Œå¦‚果用户IPå’Œå‚æ•°åŒ¹é…,则å¯ä»¥è®¿é—® + * hasRole | å¦‚æžœæœ‰å‚æ•°ï¼Œå‚数表示角色,则其角色å¯ä»¥è®¿é—® + * permitAll | 用户å¯ä»¥ä»»æ„访问 + * rememberMe | å…许通过remember-me登录的用户访问 + * authenticated | 用户登录åŽå¯è®¿é—® + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception + { + // 注解标记å…许匿å访问的url + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests(); + permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll()); + + httpSecurity + // CSRFç¦ç”¨ï¼Œå› ä¸ºä¸ä½¿ç”¨session + .csrf().disable() + // ç¦ç”¨HTTPå“应标头 + .headers().cacheControl().disable().and() + // 认è¯å¤±è´¥å¤„ç†ç±» + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以ä¸éœ€è¦session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 注册register 验è¯ç captchaImage å…许匿å访问 + .antMatchers("/login", "/register", "/captchaImage").permitAll() + // 陿€èµ„æºï¼Œå¯åŒ¿å访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + // 除上é¢å¤–的所有请求全部需è¦é‰´æƒè®¤è¯ + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + // 添加Logout filter + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + // 添加CORS filter + httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); + httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); + } + + /** + * 强散列哈希加密实现 + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() + { + return new BCryptPasswordEncoder(); + } + + /** + * èº«ä»½è®¤è¯æŽ¥å£ + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception + { + auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java new file mode 100644 index 0000000..157e9f4 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java @@ -0,0 +1,32 @@ +package com.ruoyi.framework.config; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.ServletUtils; + +/** + * æœåŠ¡ç›¸å…³é…ç½® + * + * @author ruoyi + */ +@Component +public class ServerConfig +{ + /** + * 获å–完整的请求路径,包括:域å,端å£ï¼Œä¸Šä¸‹æ–‡è®¿é—®è·¯å¾„ + * + * @return æœåŠ¡åœ°å€ + */ + public String getUrl() + { + HttpServletRequest request = ServletUtils.getRequest(); + return getDomain(request); + } + + public static String getDomain(HttpServletRequest request) + { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java new file mode 100644 index 0000000..63739f9 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java @@ -0,0 +1,63 @@ +package com.ruoyi.framework.config; + +import com.ruoyi.common.utils.Threads; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 线程池é…ç½® + * + * @author ruoyi + **/ +@Configuration +public class ThreadPoolConfig +{ + // æ ¸å¿ƒçº¿ç¨‹æ± å¤§å° + private int corePoolSize = 50; + + // 最大å¯åˆ›å»ºçš„线程数 + private int maxPoolSize = 200; + + // 队列最大长度 + private int queueCapacity = 1000; + + // 线程池维护线程所å…许的空闲时间 + private int keepAliveSeconds = 300; + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() + { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒ç»ä»»åŠ¡(无线程å¯ç”¨)的处ç†ç­–ç•¥ + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() + { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + new ThreadPoolExecutor.CallerRunsPolicy()) + { + @Override + protected void afterExecute(Runnable r, Throwable t) + { + super.afterExecute(r, t); + Threads.printException(r, t); + } + }; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java new file mode 100644 index 0000000..2dd49ab --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java @@ -0,0 +1,89 @@ +package com.ruoyi.framework.config.properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import com.alibaba.druid.pool.DruidDataSource; + +/** + * druid é…置属性 + * + * @author ruoyi + */ +@Configuration +public class DruidProperties +{ + @Value("${spring.datasource.druid.initialSize}") + private int initialSize; + + @Value("${spring.datasource.druid.minIdle}") + private int minIdle; + + @Value("${spring.datasource.druid.maxActive}") + private int maxActive; + + @Value("${spring.datasource.druid.maxWait}") + private int maxWait; + + @Value("${spring.datasource.druid.connectTimeout}") + private int connectTimeout; + + @Value("${spring.datasource.druid.socketTimeout}") + private int socketTimeout; + + @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") + private int timeBetweenEvictionRunsMillis; + + @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") + private int minEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") + private int maxEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.validationQuery}") + private String validationQuery; + + @Value("${spring.datasource.druid.testWhileIdle}") + private boolean testWhileIdle; + + @Value("${spring.datasource.druid.testOnBorrow}") + private boolean testOnBorrow; + + @Value("${spring.datasource.druid.testOnReturn}") + private boolean testOnReturn; + + public DruidDataSource dataSource(DruidDataSource datasource) + { + /** é…ç½®åˆå§‹åŒ–大å°ã€æœ€å°ã€æœ€å¤§ */ + datasource.setInitialSize(initialSize); + datasource.setMaxActive(maxActive); + datasource.setMinIdle(minIdle); + + /** é…置获å–连接等待超时的时间 */ + datasource.setMaxWait(maxWait); + + /** é…置驱动连接超时时间,检测数æ®åº“建立连接的超时时间,å•使˜¯æ¯«ç§’ */ + datasource.setConnectTimeout(connectTimeout); + + /** é…置网络超时时间,等待数æ®åº“æ“作完æˆçš„网络超时时间,å•使˜¯æ¯«ç§’ */ + datasource.setSocketTimeout(socketTimeout); + + /** é…置间隔多久æ‰è¿›è¡Œä¸€æ¬¡æ£€æµ‹ï¼Œæ£€æµ‹éœ€è¦å…³é—­çš„空闲连接,å•使˜¯æ¯«ç§’ */ + datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + + /** é…置一个连接在池中最å°ã€æœ€å¤§ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•使˜¯æ¯«ç§’ */ + datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); + + /** + * ç”¨æ¥æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆçš„sqlï¼Œè¦æ±‚是一个查询语å¥ï¼Œå¸¸ç”¨select 'x'。如果validationQuery为null,testOnBorrowã€testOnReturnã€testWhileIdle都ä¸ä¼šèµ·ä½œç”¨ã€‚ + */ + datasource.setValidationQuery(validationQuery); + /** 建议é…置为true,ä¸å½±å“性能,并且ä¿è¯å®‰å…¨æ€§ã€‚申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQueryæ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆã€‚ */ + datasource.setTestWhileIdle(testWhileIdle); + /** 申请连接时执行validationQueryæ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆï¼Œåšäº†è¿™ä¸ªé…置会é™ä½Žæ€§èƒ½ã€‚ */ + datasource.setTestOnBorrow(testOnBorrow); + /** 归还连接时执行validationQueryæ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆï¼Œåšäº†è¿™ä¸ªé…置会é™ä½Žæ€§èƒ½ã€‚ */ + datasource.setTestOnReturn(testOnReturn); + return datasource; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java new file mode 100644 index 0000000..f1dcbfc --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java @@ -0,0 +1,73 @@ +package com.ruoyi.framework.config.properties; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Pattern; +import org.apache.commons.lang3.RegExUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import com.ruoyi.common.annotation.Anonymous; + +/** + * 设置Anonymous注解å…许匿å访问的url + * + * @author ruoyi + */ +@Configuration +public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware +{ + private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); + + private ApplicationContext applicationContext; + + private List urls = new ArrayList<>(); + + public String ASTERISK = "*"; + + @Override + public void afterPropertiesSet() + { + RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class); + Map map = mapping.getHandlerMethods(); + + map.keySet().forEach(info -> { + HandlerMethod handlerMethod = map.get(info); + + // èŽ·å–æ–¹æ³•上边的注解 替代path variable 为 * + Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); + Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns()) + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + + // 获å–类上边的注解, 替代path variable 为 * + Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); + Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns()) + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + }); + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException + { + this.applicationContext = context; + } + + public List getUrls() + { + return urls; + } + + public void setUrls(List urls) + { + this.urls = urls; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java new file mode 100644 index 0000000..014ae38 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java @@ -0,0 +1,26 @@ +package com.ruoyi.framework.datasource; + +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * åŠ¨æ€æ•°æ®æº + * + * @author ruoyi + */ +public class DynamicDataSource extends AbstractRoutingDataSource +{ + public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) + { + super.setDefaultTargetDataSource(defaultTargetDataSource); + super.setTargetDataSources(targetDataSources); + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() + { + return DynamicDataSourceContextHolder.getDataSourceType(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..859a782 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java @@ -0,0 +1,45 @@ +package com.ruoyi.framework.datasource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * æ•°æ®æºåˆ‡æ¢å¤„ç† + * + * @author ruoyi + */ +public class DynamicDataSourceContextHolder +{ + public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); + + /** + * 使用ThreadLocal维护å˜é‡ï¼ŒThreadLocal为æ¯ä¸ªä½¿ç”¨è¯¥å˜é‡çš„线程æä¾›ç‹¬ç«‹çš„å˜é‡å‰¯æœ¬ï¼Œ + * 所以æ¯ä¸€ä¸ªçº¿ç¨‹éƒ½å¯ä»¥ç‹¬ç«‹åœ°æ”¹å˜è‡ªå·±çš„副本,而ä¸ä¼šå½±å“其它线程所对应的副本。 + */ + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * è®¾ç½®æ•°æ®æºçš„å˜é‡ + */ + public static void setDataSourceType(String dsType) + { + log.info("切æ¢åˆ°{}æ•°æ®æº", dsType); + CONTEXT_HOLDER.set(dsType); + } + + /** + * èŽ·å¾—æ•°æ®æºçš„å˜é‡ + */ + public static String getDataSourceType() + { + return CONTEXT_HOLDER.get(); + } + + /** + * æ¸…ç©ºæ•°æ®æºå˜é‡ + */ + public static void clearDataSourceType() + { + CONTEXT_HOLDER.remove(); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..05fff7b --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,55 @@ +package com.ruoyi.framework.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 防止é‡å¤æäº¤æ‹¦æˆªå™¨ + * + * @author ruoyi + */ +@Component +public abstract class RepeatSubmitInterceptor implements HandlerInterceptor +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (handler instanceof HandlerMethod) + { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) + { + if (this.isRepeatSubmit(request, annotation)) + { + AjaxResult ajaxResult = AjaxResult.error(annotation.message()); + ServletUtils.renderString(response, JSON.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return true; + } + } + + /** + * éªŒè¯æ˜¯å¦é‡å¤æäº¤ç”±å­ç±»å®žçŽ°å…·ä½“çš„é˜²é‡å¤æäº¤çš„规则 + * + * @param request + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java new file mode 100644 index 0000000..316a370 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -0,0 +1,110 @@ +package com.ruoyi.framework.interceptor.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.filter.RepeatedlyRequestWrapper; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.http.HttpHelper; +import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 判断请求urlå’Œæ•°æ®æ˜¯å¦å’Œä¸Šä¸€æ¬¡ç›¸åŒï¼Œ + * 如果和上次相åŒï¼Œåˆ™æ˜¯é‡å¤æäº¤è¡¨å•。 有效时间为10秒内。 + * + * @author ruoyi + */ +@Component +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor +{ + public final String REPEAT_PARAMS = "repeatParams"; + + public final String REPEAT_TIME = "repeatTime"; + + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + @Autowired + private RedisCache redisCache; + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) + { + String nowParams = ""; + if (request instanceof RepeatedlyRequestWrapper) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + nowParams = HttpHelper.getBodyString(repeatedlyRequest); + } + + // body傿•°ä¸ºç©ºï¼ŒèŽ·å–Parameterçš„æ•°æ® + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSON.toJSONString(request.getParameterMap()); + } + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + + // 请求地å€ï¼ˆä½œä¸ºå­˜æ”¾cacheçš„key值) + String url = request.getRequestURI(); + + // 唯一值(没有消æ¯å¤´åˆ™ä½¿ç”¨è¯·æ±‚地å€ï¼‰ + String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); + + // 唯一标识(指定key + url + 消æ¯å¤´ï¼‰ + String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; + + Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); + if (sessionObj != null) + { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) + { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } + + /** + * åˆ¤æ–­å‚æ•°æ˜¯å¦ç›¸åŒ + */ + private boolean compareParams(Map nowMap, Map preMap) + { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap, int interval) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < interval) + { + return true; + } + return false; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java new file mode 100644 index 0000000..6ed6d5b --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java @@ -0,0 +1,55 @@ +package com.ruoyi.framework.manager; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import com.ruoyi.common.utils.Threads; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 异步任务管ç†å™¨ + * + * @author ruoyi + */ +public class AsyncManager +{ + /** + * æ“作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步æ“作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * å•ä¾‹æ¨¡å¼ + */ + private AsyncManager(){} + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() + { + return me; + } + + /** + * 执行任务 + * + * @param task 任务 + */ + public void execute(TimerTask task) + { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** + * åœæ­¢ä»»åŠ¡çº¿ç¨‹æ±  + */ + public void shutdown() + { + Threads.shutdownAndAwaitTermination(executor); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java new file mode 100644 index 0000000..8d8fb5a --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java @@ -0,0 +1,39 @@ +package com.ruoyi.framework.manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import javax.annotation.PreDestroy; + +/** + * ç¡®ä¿åº”用退出时能关闭åŽå°çº¿ç¨‹ + * + * @author ruoyi + */ +@Component +public class ShutdownManager +{ + private static final Logger logger = LoggerFactory.getLogger("sys-user"); + + @PreDestroy + public void destroy() + { + shutdownAsyncManager(); + } + + /** + * åœæ­¢å¼‚步执行任务 + */ + private void shutdownAsyncManager() + { + try + { + logger.info("====关闭åŽå°ä»»åŠ¡ä»»åŠ¡çº¿ç¨‹æ± ===="); + AsyncManager.me().shutdown(); + } + catch (Exception e) + { + logger.error(e.getMessage(), e); + } + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java new file mode 100644 index 0000000..98517b7 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java @@ -0,0 +1,102 @@ +package com.ruoyi.framework.manager.factory; + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.LogUtils; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysLogininforService; +import com.ruoyi.system.service.ISysOperLogService; +import eu.bitwalker.useragentutils.UserAgent; + +/** + * 异步工厂(产生任务用) + * + * @author ruoyi + */ +public class AsyncFactory +{ + private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); + + /** + * è®°å½•ç™»å½•ä¿¡æ¯ + * + * @param username 用户å + * @param status çŠ¶æ€ + * @param message æ¶ˆæ¯ + * @param args 列表 + * @return 任务task + */ + public static TimerTask recordLogininfor(final String username, final String status, final String message, + final Object... args) + { + final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + final String ip = IpUtils.getIpAddr(); + return new TimerTask() + { + @Override + public void run() + { + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(LogUtils.getBlock(ip)); + s.append(address); + s.append(LogUtils.getBlock(username)); + s.append(LogUtils.getBlock(status)); + s.append(LogUtils.getBlock(message)); + // 打å°ä¿¡æ¯åˆ°æ—¥å¿— + sys_user_logger.info(s.toString(), args); + // 获å–客户端æ“作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获å–客户端æµè§ˆå™¨ + String browser = userAgent.getBrowser().getName(); + // å°è£…对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(message); + // æ—¥å¿—çŠ¶æ€ + if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) + { + logininfor.setStatus(Constants.SUCCESS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.FAIL); + } + // æ’å…¥æ•°æ® + SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); + } + }; + } + + /** + * æ“作日志记录 + * + * @param operLog æ“ä½œæ—¥å¿—ä¿¡æ¯ + * @return 任务task + */ + public static TimerTask recordOper(final SysOperLog operLog) + { + return new TimerTask() + { + @Override + public void run() + { + // 远程查询æ“作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); + } + }; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java new file mode 100644 index 0000000..5ee5bbd --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java @@ -0,0 +1,28 @@ +package com.ruoyi.framework.security.context; + +import org.springframework.security.core.Authentication; + +/** + * 身份验è¯ä¿¡æ¯ + * + * @author ruoyi + */ +public class AuthenticationContextHolder +{ + private static final ThreadLocal contextHolder = new ThreadLocal<>(); + + public static Authentication getContext() + { + return contextHolder.get(); + } + + public static void setContext(Authentication context) + { + contextHolder.set(context); + } + + public static void clearContext() + { + contextHolder.remove(); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java new file mode 100644 index 0000000..2fcd65b --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java @@ -0,0 +1,27 @@ +package com.ruoyi.framework.security.context; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import com.ruoyi.common.core.text.Convert; + +/** + * æƒé™ä¿¡æ¯ + * + * @author ruoyi + */ +public class PermissionContextHolder +{ + private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT"; + + public static void setContext(String permission) + { + RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission, + RequestAttributes.SCOPE_REQUEST); + } + + public static String getContext() + { + return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES, + RequestAttributes.SCOPE_REQUEST)); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..75fd00d --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,44 @@ +package com.ruoyi.framework.security.filter; + +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.TokenService; + +/** + * token过滤器 验è¯token有效性 + * + * @author ruoyi + */ +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter +{ + @Autowired + private TokenService tokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) + { + tokenService.verifyToken(loginUser); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + chain.doFilter(request, response); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..9d86fea --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java @@ -0,0 +1,34 @@ +package com.ruoyi.framework.security.handle; + +import java.io.IOException; +import java.io.Serializable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * 认è¯å¤±è´¥å¤„ç†ç±» è¿”å›žæœªæŽˆæƒ + * + * @author ruoyi + */ +@Component +public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable +{ + private static final long serialVersionUID = -8970718410437077606L; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) + throws IOException + { + int code = HttpStatus.UNAUTHORIZED; + String msg = StringUtils.format("请求访问:{},认è¯å¤±è´¥ï¼Œæ— æ³•访问系统资æº", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..50e7d36 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java @@ -0,0 +1,52 @@ +package com.ruoyi.framework.security.handle; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.web.service.TokenService; + +/** + * 自定义退出处ç†ç±» 返回æˆåŠŸ + * + * @author ruoyi + */ +@Configuration +public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler +{ + @Autowired + private TokenService tokenService; + + /** + * é€€å‡ºå¤„ç† + * + * @return + */ + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser)) + { + String userName = loginUser.getUsername(); + // 删除用户缓存记录 + tokenService.delLoginUser(loginUser.getToken()); + // 记录用户退出日志 + AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出æˆåŠŸ")); + } + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出æˆåŠŸ"))); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java new file mode 100644 index 0000000..30a1957 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java @@ -0,0 +1,240 @@ +package com.ruoyi.framework.web.domain; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.web.domain.server.Cpu; +import com.ruoyi.framework.web.domain.server.Jvm; +import com.ruoyi.framework.web.domain.server.Mem; +import com.ruoyi.framework.web.domain.server.Sys; +import com.ruoyi.framework.web.domain.server.SysFile; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * æœåŠ¡å™¨ç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class Server +{ + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPUç›¸å…³ä¿¡æ¯ + */ + private Cpu cpu = new Cpu(); + + /** + * å…§å­˜ç›¸å…³ä¿¡æ¯ + */ + private Mem mem = new Mem(); + + /** + * JVMç›¸å…³ä¿¡æ¯ + */ + private Jvm jvm = new Jvm(); + + /** + * æœåŠ¡å™¨ç›¸å…³ä¿¡æ¯ + */ + private Sys sys = new Sys(); + + /** + * ç£ç›˜ç›¸å…³ä¿¡æ¯ + */ + private List sysFiles = new LinkedList(); + + public Cpu getCpu() + { + return cpu; + } + + public void setCpu(Cpu cpu) + { + this.cpu = cpu; + } + + public Mem getMem() + { + return mem; + } + + public void setMem(Mem mem) + { + this.mem = mem; + } + + public Jvm getJvm() + { + return jvm; + } + + public void setJvm(Jvm jvm) + { + this.jvm = jvm; + } + + public Sys getSys() + { + return sys; + } + + public void setSys(Sys sys) + { + this.sys = sys; + } + + public List getSysFiles() + { + return sysFiles; + } + + public void setSysFiles(List sysFiles) + { + this.sysFiles = sysFiles; + } + + public void copyTo() throws Exception + { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPUä¿¡æ¯ + */ + private void setCpuInfo(CentralProcessor processor) + { + // CPUä¿¡æ¯ + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * è®¾ç½®å†…å­˜ä¿¡æ¯ + */ + private void setMemInfo(GlobalMemory memory) + { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置æœåŠ¡å™¨ä¿¡æ¯ + */ + private void setSysInfo() + { + Properties props = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException + { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置ç£ç›˜ä¿¡æ¯ + */ + private void setSysFiles(OperatingSystem os) + { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) + { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * å­—èŠ‚è½¬æ¢ + * + * @param size å­—èŠ‚å¤§å° + * @return 转æ¢åŽå€¼ + */ + public String convertFileSize(long size) + { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) + { + return String.format("%.1f GB", (float) size / gb); + } + else if (size >= mb) + { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } + else if (size >= kb) + { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } + else + { + return String.format("%d B", size); + } + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java new file mode 100644 index 0000000..cf7b46e --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java @@ -0,0 +1,101 @@ +package com.ruoyi.framework.web.domain.server; + +import com.ruoyi.common.utils.Arith; + +/** + * CPUç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class Cpu +{ + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当å‰ç­‰å¾…率 + */ + private double wait; + + /** + * CPU当å‰ç©ºé—²çއ + */ + private double free; + + public int getCpuNum() + { + return cpuNum; + } + + public void setCpuNum(int cpuNum) + { + this.cpuNum = cpuNum; + } + + public double getTotal() + { + return Arith.round(Arith.mul(total, 100), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getSys() + { + return Arith.round(Arith.mul(sys / total, 100), 2); + } + + public void setSys(double sys) + { + this.sys = sys; + } + + public double getUsed() + { + return Arith.round(Arith.mul(used / total, 100), 2); + } + + public void setUsed(double used) + { + this.used = used; + } + + public double getWait() + { + return Arith.round(Arith.mul(wait / total, 100), 2); + } + + public void setWait(double wait) + { + this.wait = wait; + } + + public double getFree() + { + return Arith.round(Arith.mul(free / total, 100), 2); + } + + public void setFree(double free) + { + this.free = free; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java new file mode 100644 index 0000000..8e142ac --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java @@ -0,0 +1,130 @@ +package com.ruoyi.framework.web.domain.server; + +import java.lang.management.ManagementFactory; +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.DateUtils; + +/** + * JVMç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class Jvm +{ + /** + * 当å‰JVMå ç”¨çš„内存总数(M) + */ + private double total; + + /** + * JVM最大å¯ç”¨å†…存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getMax() + { + return Arith.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) + { + this.max = max; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) + { + this.free = free; + } + + public double getUsed() + { + return Arith.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() + { + return Arith.mul(Arith.div(total - free, total, 4), 100); + } + + /** + * 获å–JDKåç§° + */ + public String getName() + { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getHome() + { + return home; + } + + public void setHome(String home) + { + this.home = home; + } + + /** + * JDKå¯åŠ¨æ—¶é—´ + */ + public String getStartTime() + { + return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); + } + + /** + * JDKè¿è¡Œæ—¶é—´ + */ + public String getRunTime() + { + return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate()); + } + + /** + * è¿è¡Œå‚æ•° + */ + public String getInputArgs() + { + return ManagementFactory.getRuntimeMXBean().getInputArguments().toString(); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java new file mode 100644 index 0000000..ac71504 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java @@ -0,0 +1,61 @@ +package com.ruoyi.framework.web.domain.server; + +import com.ruoyi.common.utils.Arith; + +/** + * å…§å­˜ç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class Mem +{ + /** + * å†…å­˜æ€»é‡ + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) + { + this.total = total; + } + + public double getUsed() + { + return Arith.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) + { + this.used = used; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) + { + this.free = free; + } + + public double getUsage() + { + return Arith.mul(Arith.div(used, total, 4), 100); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java new file mode 100644 index 0000000..a5f65e4 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java @@ -0,0 +1,84 @@ +package com.ruoyi.framework.web.domain.server; + +/** + * ç³»ç»Ÿç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class Sys +{ + /** + * æœåС噍åç§° + */ + private String computerName; + + /** + * æœåС噍Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * æ“作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + + public String getComputerName() + { + return computerName; + } + + public void setComputerName(String computerName) + { + this.computerName = computerName; + } + + public String getComputerIp() + { + return computerIp; + } + + public void setComputerIp(String computerIp) + { + this.computerIp = computerIp; + } + + public String getUserDir() + { + return userDir; + } + + public void setUserDir(String userDir) + { + this.userDir = userDir; + } + + public String getOsName() + { + return osName; + } + + public void setOsName(String osName) + { + this.osName = osName; + } + + public String getOsArch() + { + return osArch; + } + + public void setOsArch(String osArch) + { + this.osArch = osArch; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java new file mode 100644 index 0000000..47ecf3f --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java @@ -0,0 +1,114 @@ +package com.ruoyi.framework.web.domain.server; + +/** + * ç³»ç»Ÿæ–‡ä»¶ç›¸å…³ä¿¡æ¯ + * + * @author ruoyi + */ +public class SysFile +{ + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * æ€»å¤§å° + */ + private String total; + + /** + * å‰©ä½™å¤§å° + */ + private String free; + + /** + * å·²ç»ä½¿ç”¨é‡ + */ + private String used; + + /** + * 资æºçš„使用率 + */ + private double usage; + + public String getDirName() + { + return dirName; + } + + public void setDirName(String dirName) + { + this.dirName = dirName; + } + + public String getSysTypeName() + { + return sysTypeName; + } + + public void setSysTypeName(String sysTypeName) + { + this.sysTypeName = sysTypeName; + } + + public String getTypeName() + { + return typeName; + } + + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTotal() + { + return total; + } + + public void setTotal(String total) + { + this.total = total; + } + + public String getFree() + { + return free; + } + + public void setFree(String free) + { + this.free = free; + } + + public String getUsed() + { + return used; + } + + public void setUsed(String used) + { + this.used = used; + } + + public double getUsage() + { + return usage; + } + + public void setUsage(double usage) + { + this.usage = usage; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..bf0a7ed --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,114 @@ +package com.ruoyi.framework.web.exception; + +import javax.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.DemoModeException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; + +/** + * 全局异常处ç†å™¨ + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler +{ + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * æƒé™æ ¡éªŒå¼‚常 + */ + @ExceptionHandler(AccessDeniedException.class) + public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地å€'{}',æƒé™æ ¡éªŒå¤±è´¥'{}'", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有æƒé™ï¼Œè¯·è”系管ç†å‘˜æŽˆæƒ"); + } + + /** + * 请求方å¼ä¸æ”¯æŒ + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地å€'{}',䏿”¯æŒ'{}'请求", requestURI, e.getMethod()); + return AjaxResult.error(e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) + { + log.error(e.getMessage(), e); + Integer code = e.getCode(); + return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); + } + + /** + * 拦截未知的è¿è¡Œæ—¶å¼‚常 + */ + @ExceptionHandler(RuntimeException.class) + public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地å€'{}',å‘生未知异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地å€'{}',å‘生系统异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验è¯å¼‚常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult handleBindException(BindException e) + { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验è¯å¼‚常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) + { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 演示模å¼å¼‚常 + */ + @ExceptionHandler(DemoModeException.class) + public AjaxResult handleDemoModeException(DemoModeException e) + { + return AjaxResult.error("演示模å¼ï¼Œä¸å…许æ“作"); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java new file mode 100644 index 0000000..5043e39 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java @@ -0,0 +1,168 @@ +package com.ruoyi.framework.web.service; + +import java.util.Set; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.security.context.PermissionContextHolder; + +/** + * RuoYi首创 自定义æƒé™å®žçŽ°ï¼Œsså–自SpringSecurityé¦–å­—æ¯ + * + * @author ruoyi + */ +@Service("ss") +public class PermissionService +{ + /** 所有æƒé™æ ‡è¯† */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管ç†å‘˜è§’色æƒé™æ ‡è¯† */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + /** + * 验è¯ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™ + * + * @param permission æƒé™å­—符串 + * @return 用户是å¦å…·å¤‡æŸæƒé™ + */ + public boolean hasPermi(String permission) + { + if (StringUtils.isEmpty(permission)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permission); + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验è¯ç”¨æˆ·æ˜¯å¦ä¸å…·å¤‡æŸæƒé™ï¼Œä¸Ž hasPermi逻辑相å + * + * @param permission æƒé™å­—符串 + * @return 用户是å¦ä¸å…·å¤‡æŸæƒé™ + */ + public boolean lacksPermi(String permission) + { + return hasPermi(permission) != true; + } + + /** + * 验è¯ç”¨æˆ·æ˜¯å¦å…·æœ‰ä»¥ä¸‹ä»»æ„一个æƒé™ + * + * @param permissions 以 PERMISSION_DELIMETER 为分隔符的æƒé™åˆ—表 + * @return 用户是å¦å…·æœ‰ä»¥ä¸‹ä»»æ„一个æƒé™ + */ + public boolean hasAnyPermi(String permissions) + { + if (StringUtils.isEmpty(permissions)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permissions); + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) + { + if (permission != null && hasPermissions(authorities, permission)) + { + return true; + } + } + return false; + } + + /** + * åˆ¤æ–­ç”¨æˆ·æ˜¯å¦æ‹¥æœ‰æŸä¸ªè§’色 + * + * @param role 角色字符串 + * @return 用户是å¦å…·å¤‡æŸè§’色 + */ + public boolean hasRole(String role) + { + if (StringUtils.isEmpty(role)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (SysRole sysRole : loginUser.getUser().getRoles()) + { + String roleKey = sysRole.getRoleKey(); + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) + { + return true; + } + } + return false; + } + + /** + * 验è¯ç”¨æˆ·æ˜¯å¦ä¸å…·å¤‡æŸè§’色,与 isRole逻辑相å。 + * + * @param role 角色åç§° + * @return 用户是å¦ä¸å…·å¤‡æŸè§’色 + */ + public boolean lacksRole(String role) + { + return hasRole(role) != true; + } + + /** + * 验è¯ç”¨æˆ·æ˜¯å¦å…·æœ‰ä»¥ä¸‹ä»»æ„一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是å¦å…·æœ‰ä»¥ä¸‹ä»»æ„一个角色 + */ + public boolean hasAnyRoles(String roles) + { + if (StringUtils.isEmpty(roles)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) + { + if (hasRole(role)) + { + return true; + } + } + return false; + } + + /** + * 判断是å¦åŒ…嫿ƒé™ + * + * @param permissions æƒé™åˆ—表 + * @param permission æƒé™å­—符串 + * @return 用户是å¦å…·å¤‡æŸæƒé™ + */ + private boolean hasPermissions(Set permissions, String permission) + { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java new file mode 100644 index 0000000..4831849 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -0,0 +1,181 @@ +package com.ruoyi.framework.web.service; + +import javax.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.exception.user.BlackListException; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.exception.user.UserNotExistsException; +import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.security.context.AuthenticationContextHolder; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 登录校验方法 + * + * @author ruoyi + */ +@Component +public class SysLoginService +{ + @Autowired + private TokenService tokenService; + + @Resource + private AuthenticationManager authenticationManager; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + /** + * ç™»å½•éªŒè¯ + * + * @param username 用户å + * @param password å¯†ç  + * @param code 验è¯ç  + * @param uuid 唯一标识 + * @return 结果 + */ + public String login(String username, String password, String code, String uuid) + { + // 验è¯ç æ ¡éªŒ + validateCaptcha(username, code, uuid); + // 登录å‰ç½®æ ¡éªŒ + loginPreCheck(username, password); + // ç”¨æˆ·éªŒè¯ + Authentication authentication = null; + try + { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + AuthenticationContextHolder.setContext(authenticationToken); + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager.authenticate(authenticationToken); + } + catch (Exception e) + { + if (e instanceof BadCredentialsException) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } + else + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new ServiceException(e.getMessage()); + } + } + finally + { + AuthenticationContextHolder.clearContext(); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + recordLoginInfo(loginUser.getUserId()); + // 生æˆtoken + return tokenService.createToken(loginUser); + } + + /** + * 校验验è¯ç  + * + * @param username 用户å + * @param code 验è¯ç  + * @param uuid 唯一标识 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String uuid) + { + boolean captchaEnabled = configService.selectCaptchaEnabled(); + if (captchaEnabled) + { + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); + throw new CaptchaException(); + } + } + } + + /** + * 登录å‰ç½®æ ¡éªŒ + * @param username 用户å + * @param password ç”¨æˆ·å¯†ç  + */ + public void loginPreCheck(String username, String password) + { + // ç”¨æˆ·åæˆ–密ç ä¸ºç©º 错误 + if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"))); + throw new UserNotExistsException(); + } + // 密ç å¦‚æžœä¸åœ¨æŒ‡å®šèŒƒå›´å†… 错误 + if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } + // 用户åä¸åœ¨æŒ‡å®šèŒƒå›´å†… 错误 + if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } + // IP黑å啿 ¡éªŒ + String blackStr = configService.selectConfigByKey("sys.login.blackIPList"); + if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked"))); + throw new BlackListException(); + } + } + + /** + * è®°å½•ç™»å½•ä¿¡æ¯ + * + * @param userId 用户ID + */ + public void recordLoginInfo(Long userId) + { + SysUser sysUser = new SysUser(); + sysUser.setUserId(userId); + sysUser.setLoginIp(IpUtils.getIpAddr()); + sysUser.setLoginDate(DateUtils.getNowDate()); + userService.updateUserProfile(sysUser); + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java new file mode 100644 index 0000000..a68dbc8 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java @@ -0,0 +1,94 @@ +package com.ruoyi.framework.web.service; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.security.context.AuthenticationContextHolder; + +/** + * ç™»å½•å¯†ç æ–¹æ³• + * + * @author ruoyi + */ +@Component +public class SysPasswordService +{ + @Autowired + private RedisCache redisCache; + + @Value(value = "${user.password.maxRetryCount}") + private int maxRetryCount; + + @Value(value = "${user.password.lockTime}") + private int lockTime; + + /** + * 登录账户密ç é”™è¯¯æ¬¡æ•°ç¼“存键å + * + * @param username 用户å + * @return 缓存键key + */ + private String getCacheKey(String username) + { + return CacheConstants.PWD_ERR_CNT_KEY + username; + } + + public void validate(SysUser user) + { + Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); + String username = usernamePasswordAuthenticationToken.getName(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + + Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); + throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); + } + + if (!matches(user, password)) + { + retryCount = retryCount + 1; + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new UserPasswordNotMatchException(); + } + else + { + clearLoginRecordCache(username); + } + } + + public boolean matches(SysUser user, String rawPassword) + { + return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); + } + + public void clearLoginRecordCache(String loginName) + { + if (redisCache.hasKey(getCacheKey(loginName))) + { + redisCache.deleteObject(getCacheKey(loginName)); + } + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java new file mode 100644 index 0000000..6400750 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java @@ -0,0 +1,83 @@ +package com.ruoyi.framework.web.service; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.system.service.ISysMenuService; +import com.ruoyi.system.service.ISysRoleService; + +/** + * 用户æƒé™å¤„ç† + * + * @author ruoyi + */ +@Component +public class SysPermissionService +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysMenuService menuService; + + /** + * 获å–è§’è‰²æ•°æ®æƒé™ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 角色æƒé™ä¿¡æ¯ + */ + public Set getRolePermission(SysUser user) + { + Set roles = new HashSet(); + // 管ç†å‘˜æ‹¥æœ‰æ‰€æœ‰æƒé™ + if (user.isAdmin()) + { + roles.add("admin"); + } + else + { + roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); + } + return roles; + } + + /** + * 获å–èœå•æ•°æ®æƒé™ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return èœå•æƒé™ä¿¡æ¯ + */ + public Set getMenuPermission(SysUser user) + { + Set perms = new HashSet(); + // 管ç†å‘˜æ‹¥æœ‰æ‰€æœ‰æƒé™ + if (user.isAdmin()) + { + perms.add("*:*:*"); + } + else + { + List roles = user.getRoles(); + if (!CollectionUtils.isEmpty(roles)) + { + // 多角色设置permissionså±žæ€§ï¼Œä»¥ä¾¿æ•°æ®æƒé™åŒ¹é…æƒé™ + for (SysRole role : roles) + { + Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); + role.setPermissions(rolePerms); + perms.addAll(rolePerms); + } + } + else + { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + } + return perms; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java new file mode 100644 index 0000000..6093515 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java @@ -0,0 +1,115 @@ +package com.ruoyi.framework.web.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.RegisterBody; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 注册校验方法 + * + * @author ruoyi + */ +@Component +public class SysRegisterService +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + @Autowired + private RedisCache redisCache; + + /** + * 注册 + */ + public String register(RegisterBody registerBody) + { + String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); + SysUser sysUser = new SysUser(); + sysUser.setUserName(username); + + // 验è¯ç å¼€å…³ + boolean captchaEnabled = configService.selectCaptchaEnabled(); + if (captchaEnabled) + { + validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); + } + + if (StringUtils.isEmpty(username)) + { + msg = "用户åä¸èƒ½ä¸ºç©º"; + } + else if (StringUtils.isEmpty(password)) + { + msg = "用户密ç ä¸èƒ½ä¸ºç©º"; + } + else if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + msg = "账户长度必须在2到20个字符之间"; + } + else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + msg = "密ç é•¿åº¦å¿…须在5到20个字符之间"; + } + else if (!userService.checkUserNameUnique(sysUser)) + { + msg = "ä¿å­˜ç”¨æˆ·'" + username + "'失败,注册账å·å·²å­˜åœ¨"; + } + else + { + sysUser.setNickName(username); + sysUser.setPassword(SecurityUtils.encryptPassword(password)); + boolean regFlag = userService.registerUser(sysUser); + if (!regFlag) + { + msg = "注册失败,请è”系系统管ç†äººå‘˜"; + } + else + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"))); + } + } + return msg; + } + + /** + * 校验验è¯ç  + * + * @param username 用户å + * @param code 验è¯ç  + * @param uuid 唯一标识 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String uuid) + { + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) + { + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) + { + throw new CaptchaException(); + } + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java new file mode 100644 index 0000000..4b190d0 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -0,0 +1,226 @@ +package com.ruoyi.framework.web.service; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * token验è¯å¤„ç† + * + * @author ruoyi + */ +@Component +public class TokenService +{ + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + // 令牌秘钥 + @Value("${token.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Autowired + private RedisCache redisCache; + + /** + * 获å–ç”¨æˆ·èº«ä»½ä¿¡æ¯ + * + * @return ç”¨æˆ·ä¿¡æ¯ + */ + public LoginUser getLoginUser(HttpServletRequest request) + { + // 获å–请求æºå¸¦çš„令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) + { + try + { + Claims claims = parseToken(token); + // è§£æžå¯¹åº”çš„æƒé™ä»¥åŠç”¨æˆ·ä¿¡æ¯ + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user; + } + catch (Exception e) + { + } + } + return null; + } + + /** + * è®¾ç½®ç”¨æˆ·èº«ä»½ä¿¡æ¯ + */ + public void setLoginUser(LoginUser loginUser) + { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) + { + refreshToken(loginUser); + } + } + + /** + * åˆ é™¤ç”¨æˆ·èº«ä»½ä¿¡æ¯ + */ + public void delLoginUser(String token) + { + if (StringUtils.isNotEmpty(token)) + { + String userKey = getTokenKey(token); + redisCache.deleteObject(userKey); + } + } + + /** + * 创建令牌 + * + * @param loginUser ç”¨æˆ·ä¿¡æ¯ + * @return 令牌 + */ + public String createToken(LoginUser loginUser) + { + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + } + + /** + * 验è¯ä»¤ç‰Œæœ‰æ•ˆæœŸï¼Œç›¸å·®ä¸è¶³20分钟,自动刷新缓存 + * + * @param loginUser + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) + { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) + { + refreshToken(loginUser); + } + } + + /** + * 刷新令牌有效期 + * + * @param loginUser ç™»å½•ä¿¡æ¯ + */ + public void refreshToken(LoginUser loginUser) + { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + // æ ¹æ®uuidå°†loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + } + + /** + * 设置用户代ç†ä¿¡æ¯ + * + * @param loginUser ç™»å½•ä¿¡æ¯ + */ + public void setUserAgent(LoginUser loginUser) + { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(); + loginUser.setIpaddr(ip); + loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + loginUser.setBrowser(userAgent.getBrowser().getName()); + loginUser.setOs(userAgent.getOperatingSystem().getName()); + } + + /** + * 从数æ®å£°æ˜Žç”Ÿæˆä»¤ç‰Œ + * + * @param claims æ•°æ®å£°æ˜Ž + * @return 令牌 + */ + private String createToken(Map claims) + { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * ä»Žä»¤ç‰Œä¸­èŽ·å–æ•°æ®å£°æ˜Ž + * + * @param token 令牌 + * @return æ•°æ®å£°æ˜Ž + */ + private Claims parseToken(String token) + { + return Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } + + /** + * 从令牌中获å–用户å + * + * @param token 令牌 + * @return 用户å + */ + public String getUsernameFromToken(String token) + { + Claims claims = parseToken(token); + return claims.getSubject(); + } + + /** + * 获å–请求token + * + * @param request + * @return token + */ + private String getToken(HttpServletRequest request) + { + String token = request.getHeader(header); + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) + { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + return token; + } + + private String getTokenKey(String uuid) + { + return CacheConstants.LOGIN_TOKEN_KEY + uuid; + } +} diff --git a/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..234a502 --- /dev/null +++ b/examapi/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java @@ -0,0 +1,65 @@ +package com.ruoyi.framework.web.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.UserStatus; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysUserService; + +/** + * 用户验è¯å¤„ç† + * + * @author ruoyi + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService +{ + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private ISysUserService userService; + + @Autowired + private SysPasswordService passwordService; + + @Autowired + private SysPermissionService permissionService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException + { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) + { + log.info("登录用户:{} ä¸å­˜åœ¨.", username); + throw new ServiceException("登录用户:" + username + " ä¸å­˜åœ¨"); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new ServiceException("对ä¸èµ·ï¼Œæ‚¨çš„è´¦å·ï¼š" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被åœç”¨.", username); + throw new ServiceException("对ä¸èµ·ï¼Œæ‚¨çš„è´¦å·ï¼š" + username + " å·²åœç”¨"); + } + + passwordService.validate(user); + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) + { + return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); + } +} diff --git a/examapi/ruoyi-generator/pom.xml b/examapi/ruoyi-generator/pom.xml new file mode 100644 index 0000000..cea4f67 --- /dev/null +++ b/examapi/ruoyi-generator/pom.xml @@ -0,0 +1,40 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-generator + + + generator代ç ç”Ÿæˆ + + + + + + + org.apache.velocity + velocity-engine-core + + + + + commons-collections + commons-collections + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java new file mode 100644 index 0000000..1b144de --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.generator.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +/** + * 读å–代ç ç”Ÿæˆç›¸å…³é…ç½® + * + * @author ruoyi + */ +@Component +@ConfigurationProperties(prefix = "gen") +@PropertySource(value = { "classpath:generator.yml" }) +public class GenConfig +{ + /** 作者 */ + public static String author; + + /** 生æˆåŒ…路径 */ + public static String packageName; + + /** 自动去除表å‰ç¼€ï¼Œé»˜è®¤æ˜¯false */ + public static boolean autoRemovePre; + + /** 表å‰ç¼€(ç±»åä¸ä¼šåŒ…å«è¡¨å‰ç¼€) */ + public static String tablePrefix; + + public static String getAuthor() + { + return author; + } + + @Value("${author}") + public void setAuthor(String author) + { + GenConfig.author = author; + } + + public static String getPackageName() + { + return packageName; + } + + @Value("${packageName}") + public void setPackageName(String packageName) + { + GenConfig.packageName = packageName; + } + + public static boolean getAutoRemovePre() + { + return autoRemovePre; + } + + @Value("${autoRemovePre}") + public void setAutoRemovePre(boolean autoRemovePre) + { + GenConfig.autoRemovePre = autoRemovePre; + } + + public static String getTablePrefix() + { + return tablePrefix; + } + + @Value("${tablePrefix}") + public void setTablePrefix(String tablePrefix) + { + GenConfig.tablePrefix = tablePrefix; + } +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java new file mode 100644 index 0000000..af9f4ee --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java @@ -0,0 +1,214 @@ +package com.ruoyi.generator.controller; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.service.IGenTableColumnService; +import com.ruoyi.generator.service.IGenTableService; + +/** + * 代ç ç”Ÿæˆ æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/tool/gen") +public class GenController extends BaseController +{ + @Autowired + private IGenTableService genTableService; + + @Autowired + private IGenTableColumnService genTableColumnService; + + /** + * 查询代ç ç”Ÿæˆåˆ—表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping("/list") + public TableDataInfo genList(GenTable genTable) + { + startPage(); + List list = genTableService.selectGenTableList(genTable); + return getDataTable(list); + } + + /** + * 修改代ç ç”Ÿæˆä¸šåŠ¡ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:query')") + @GetMapping(value = "/{tableId}") + public AjaxResult getInfo(@PathVariable Long tableId) + { + GenTable table = genTableService.selectGenTableById(tableId); + List tables = genTableService.selectGenTableAll(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + Map map = new HashMap(); + map.put("info", table); + map.put("rows", list); + map.put("tables", tables); + return success(map); + } + + /** + * 查询数æ®åº“列表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping("/db/list") + public TableDataInfo dataList(GenTable genTable) + { + startPage(); + List list = genTableService.selectDbTableList(genTable); + return getDataTable(list); + } + + /** + * 查询数æ®è¡¨å­—段列表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping(value = "/column/{tableId}") + public TableDataInfo columnList(Long tableId) + { + TableDataInfo dataInfo = new TableDataInfo(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + dataInfo.setRows(list); + dataInfo.setTotal(list.size()); + return dataInfo; + } + + /** + * 导入表结构(ä¿å­˜ï¼‰ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:import')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.IMPORT) + @PostMapping("/importTable") + public AjaxResult importTableSave(String tables) + { + String[] tableNames = Convert.toStrArray(tables); + // æŸ¥è¯¢è¡¨ä¿¡æ¯ + List tableList = genTableService.selectDbTableListByNames(tableNames); + genTableService.importGenTable(tableList); + return success(); + } + + /** + * 修改ä¿å­˜ä»£ç ç”Ÿæˆä¸šåŠ¡ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:edit')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult editSave(@Validated @RequestBody GenTable genTable) + { + genTableService.validateEdit(genTable); + genTableService.updateGenTable(genTable); + return success(); + } + + /** + * 删除代ç ç”Ÿæˆ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:remove')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.DELETE) + @DeleteMapping("/{tableIds}") + public AjaxResult remove(@PathVariable Long[] tableIds) + { + genTableService.deleteGenTableByIds(tableIds); + return success(); + } + + /** + * é¢„è§ˆä»£ç  + */ + @PreAuthorize("@ss.hasPermi('tool:gen:preview')") + @GetMapping("/preview/{tableId}") + public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException + { + Map dataMap = genTableService.previewCode(tableId); + return success(dataMap); + } + + /** + * 生æˆä»£ç ï¼ˆä¸‹è½½æ–¹å¼ï¼‰ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.GENCODE) + @GetMapping("/download/{tableName}") + public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException + { + byte[] data = genTableService.downloadCode(tableName); + genCode(response, data); + } + + /** + * 生æˆä»£ç ï¼ˆè‡ªå®šä¹‰è·¯å¾„) + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.GENCODE) + @GetMapping("/genCode/{tableName}") + public AjaxResult genCode(@PathVariable("tableName") String tableName) + { + genTableService.generatorCode(tableName); + return success(); + } + + /** + * åŒæ­¥æ•°æ®åº“ + */ + @PreAuthorize("@ss.hasPermi('tool:gen:edit')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.UPDATE) + @GetMapping("/synchDb/{tableName}") + public AjaxResult synchDb(@PathVariable("tableName") String tableName) + { + genTableService.synchDb(tableName); + return success(); + } + + /** + * 批é‡ç”Ÿæˆä»£ç  + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代ç ç”Ÿæˆ", businessType = BusinessType.GENCODE) + @GetMapping("/batchGenCode") + public void batchGenCode(HttpServletResponse response, String tables) throws IOException + { + String[] tableNames = Convert.toStrArray(tables); + byte[] data = genTableService.downloadCode(tableNames); + genCode(response, data); + } + + /** + * 生æˆzip文件 + */ + private void genCode(HttpServletResponse response, byte[] data) throws IOException + { + response.reset(); + response.addHeader("Access-Control-Allow-Origin", "*"); + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\""); + response.addHeader("Content-Length", "" + data.length); + response.setContentType("application/octet-stream; charset=UTF-8"); + IOUtils.write(data, response.getOutputStream()); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java new file mode 100644 index 0000000..2abb94f --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java @@ -0,0 +1,372 @@ +package com.ruoyi.generator.domain; + +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.apache.commons.lang3.ArrayUtils; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; + +/** + * 业务表 gen_table + * + * @author ruoyi + */ +public class GenTable extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ç¼–å· */ + private Long tableId; + + /** 表åç§° */ + @NotBlank(message = "表åç§°ä¸èƒ½ä¸ºç©º") + private String tableName; + + /** 表æè¿° */ + @NotBlank(message = "表æè¿°ä¸èƒ½ä¸ºç©º") + private String tableComment; + + /** å…³è”父表的表å */ + private String subTableName; + + /** 本表关è”父表的外键å */ + private String subTableFkName; + + /** 实体类åç§°(首字æ¯å¤§å†™) */ + @NotBlank(message = "实体类åç§°ä¸èƒ½ä¸ºç©º") + private String className; + + /** 使用的模æ¿ï¼ˆcrudå•表æ“作 tree树表æ“作 sub主å­è¡¨æ“作) */ + private String tplCategory; + + /** 生æˆåŒ…路径 */ + @NotBlank(message = "生æˆåŒ…路径ä¸èƒ½ä¸ºç©º") + private String packageName; + + /** ç”Ÿæˆæ¨¡å—å */ + @NotBlank(message = "ç”Ÿæˆæ¨¡å—åä¸èƒ½ä¸ºç©º") + private String moduleName; + + /** 生æˆä¸šåŠ¡å */ + @NotBlank(message = "生æˆä¸šåŠ¡åä¸èƒ½ä¸ºç©º") + private String businessName; + + /** 生æˆåŠŸèƒ½å */ + @NotBlank(message = "生æˆåŠŸèƒ½åä¸èƒ½ä¸ºç©º") + private String functionName; + + /** 生æˆä½œè€… */ + @NotBlank(message = "作者ä¸èƒ½ä¸ºç©º") + private String functionAuthor; + + /** 生æˆä»£ç æ–¹å¼ï¼ˆ0zip压缩包 1自定义路径) */ + private String genType; + + /** 生æˆè·¯å¾„(ä¸å¡«é»˜è®¤é¡¹ç›®è·¯å¾„) */ + private String genPath; + + /** ä¸»é”®ä¿¡æ¯ */ + private GenTableColumn pkColumn; + + /** å­è¡¨ä¿¡æ¯ */ + private GenTable subTable; + + /** è¡¨åˆ—ä¿¡æ¯ */ + @Valid + private List columns; + + /** 其它生æˆé€‰é¡¹ */ + private String options; + + /** æ ‘ç¼–ç å­—段 */ + private String treeCode; + + /** 树父编ç å­—段 */ + private String treeParentCode; + + /** æ ‘å称字段 */ + private String treeName; + + /** 上级èœå•ID字段 */ + private String parentMenuId; + + /** 上级èœå•å称字段 */ + private String parentMenuName; + + public Long getTableId() + { + return tableId; + } + + public void setTableId(Long tableId) + { + this.tableId = tableId; + } + + public String getTableName() + { + return tableName; + } + + public void setTableName(String tableName) + { + this.tableName = tableName; + } + + public String getTableComment() + { + return tableComment; + } + + public void setTableComment(String tableComment) + { + this.tableComment = tableComment; + } + + public String getSubTableName() + { + return subTableName; + } + + public void setSubTableName(String subTableName) + { + this.subTableName = subTableName; + } + + public String getSubTableFkName() + { + return subTableFkName; + } + + public void setSubTableFkName(String subTableFkName) + { + this.subTableFkName = subTableFkName; + } + + public String getClassName() + { + return className; + } + + public void setClassName(String className) + { + this.className = className; + } + + public String getTplCategory() + { + return tplCategory; + } + + public void setTplCategory(String tplCategory) + { + this.tplCategory = tplCategory; + } + + public String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + this.packageName = packageName; + } + + public String getModuleName() + { + return moduleName; + } + + public void setModuleName(String moduleName) + { + this.moduleName = moduleName; + } + + public String getBusinessName() + { + return businessName; + } + + public void setBusinessName(String businessName) + { + this.businessName = businessName; + } + + public String getFunctionName() + { + return functionName; + } + + public void setFunctionName(String functionName) + { + this.functionName = functionName; + } + + public String getFunctionAuthor() + { + return functionAuthor; + } + + public void setFunctionAuthor(String functionAuthor) + { + this.functionAuthor = functionAuthor; + } + + public String getGenType() + { + return genType; + } + + public void setGenType(String genType) + { + this.genType = genType; + } + + public String getGenPath() + { + return genPath; + } + + public void setGenPath(String genPath) + { + this.genPath = genPath; + } + + public GenTableColumn getPkColumn() + { + return pkColumn; + } + + public void setPkColumn(GenTableColumn pkColumn) + { + this.pkColumn = pkColumn; + } + + public GenTable getSubTable() + { + return subTable; + } + + public void setSubTable(GenTable subTable) + { + this.subTable = subTable; + } + + public List getColumns() + { + return columns; + } + + public void setColumns(List columns) + { + this.columns = columns; + } + + public String getOptions() + { + return options; + } + + public void setOptions(String options) + { + this.options = options; + } + + public String getTreeCode() + { + return treeCode; + } + + public void setTreeCode(String treeCode) + { + this.treeCode = treeCode; + } + + public String getTreeParentCode() + { + return treeParentCode; + } + + public void setTreeParentCode(String treeParentCode) + { + this.treeParentCode = treeParentCode; + } + + public String getTreeName() + { + return treeName; + } + + public void setTreeName(String treeName) + { + this.treeName = treeName; + } + + public String getParentMenuId() + { + return parentMenuId; + } + + public void setParentMenuId(String parentMenuId) + { + this.parentMenuId = parentMenuId; + } + + public String getParentMenuName() + { + return parentMenuName; + } + + public void setParentMenuName(String parentMenuName) + { + this.parentMenuName = parentMenuName; + } + + public boolean isSub() + { + return isSub(this.tplCategory); + } + + public static boolean isSub(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory); + } + + public boolean isTree() + { + return isTree(this.tplCategory); + } + + public static boolean isTree(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); + } + + public boolean isCrud() + { + return isCrud(this.tplCategory); + } + + public static boolean isCrud(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); + } + + public boolean isSuperColumn(String javaField) + { + return isSuperColumn(this.tplCategory, javaField); + } + + public static boolean isSuperColumn(String tplCategory, String javaField) + { + if (isTree(tplCategory)) + { + return StringUtils.equalsAnyIgnoreCase(javaField, + ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY)); + } + return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java new file mode 100644 index 0000000..9140d4d --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -0,0 +1,373 @@ +package com.ruoyi.generator.domain; + +import javax.validation.constraints.NotBlank; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; + +/** + * 代ç ç”Ÿæˆä¸šåŠ¡å­—æ®µè¡¨ gen_table_column + * + * @author ruoyi + */ +public class GenTableColumn extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ç¼–å· */ + private Long columnId; + + /** å½’å±žè¡¨ç¼–å· */ + private Long tableId; + + /** 列åç§° */ + private String columnName; + + /** 列æè¿° */ + private String columnComment; + + /** 列类型 */ + private String columnType; + + /** JAVA类型 */ + private String javaType; + + /** JAVA字段å */ + @NotBlank(message = "Java属性ä¸èƒ½ä¸ºç©º") + private String javaField; + + /** 是å¦ä¸»é”®ï¼ˆ1是) */ + private String isPk; + + /** 是å¦è‡ªå¢žï¼ˆ1是) */ + private String isIncrement; + + /** 是å¦å¿…填(1是) */ + private String isRequired; + + /** 是å¦ä¸ºæ’入字段(1是) */ + private String isInsert; + + /** 是å¦ç¼–辑字段(1是) */ + private String isEdit; + + /** 是å¦åˆ—表字段(1是) */ + private String isList; + + /** æ˜¯å¦æŸ¥è¯¢å­—段(1是) */ + private String isQuery; + + /** 查询方å¼ï¼ˆEQ等于ã€NEä¸ç­‰äºŽã€GT大于ã€LTå°äºŽã€LIKE模糊ã€BETWEEN范围) */ + private String queryType; + + /** 显示类型(input文本框ã€textarea文本域ã€select下拉框ã€checkboxå¤é€‰æ¡†ã€radioå•选框ã€datetime日期控件ã€image图片上传控件ã€upload文件上传控件ã€editor富文本控件) */ + private String htmlType; + + /** 字典类型 */ + private String dictType; + + /** æŽ’åº */ + private Integer sort; + + public void setColumnId(Long columnId) + { + this.columnId = columnId; + } + + public Long getColumnId() + { + return columnId; + } + + public void setTableId(Long tableId) + { + this.tableId = tableId; + } + + public Long getTableId() + { + return tableId; + } + + public void setColumnName(String columnName) + { + this.columnName = columnName; + } + + public String getColumnName() + { + return columnName; + } + + public void setColumnComment(String columnComment) + { + this.columnComment = columnComment; + } + + public String getColumnComment() + { + return columnComment; + } + + public void setColumnType(String columnType) + { + this.columnType = columnType; + } + + public String getColumnType() + { + return columnType; + } + + public void setJavaType(String javaType) + { + this.javaType = javaType; + } + + public String getJavaType() + { + return javaType; + } + + public void setJavaField(String javaField) + { + this.javaField = javaField; + } + + public String getJavaField() + { + return javaField; + } + + public String getCapJavaField() + { + return StringUtils.capitalize(javaField); + } + + public void setIsPk(String isPk) + { + this.isPk = isPk; + } + + public String getIsPk() + { + return isPk; + } + + public boolean isPk() + { + return isPk(this.isPk); + } + + public boolean isPk(String isPk) + { + return isPk != null && StringUtils.equals("1", isPk); + } + + public String getIsIncrement() + { + return isIncrement; + } + + public void setIsIncrement(String isIncrement) + { + this.isIncrement = isIncrement; + } + + public boolean isIncrement() + { + return isIncrement(this.isIncrement); + } + + public boolean isIncrement(String isIncrement) + { + return isIncrement != null && StringUtils.equals("1", isIncrement); + } + + public void setIsRequired(String isRequired) + { + this.isRequired = isRequired; + } + + public String getIsRequired() + { + return isRequired; + } + + public boolean isRequired() + { + return isRequired(this.isRequired); + } + + public boolean isRequired(String isRequired) + { + return isRequired != null && StringUtils.equals("1", isRequired); + } + + public void setIsInsert(String isInsert) + { + this.isInsert = isInsert; + } + + public String getIsInsert() + { + return isInsert; + } + + public boolean isInsert() + { + return isInsert(this.isInsert); + } + + public boolean isInsert(String isInsert) + { + return isInsert != null && StringUtils.equals("1", isInsert); + } + + public void setIsEdit(String isEdit) + { + this.isEdit = isEdit; + } + + public String getIsEdit() + { + return isEdit; + } + + public boolean isEdit() + { + return isInsert(this.isEdit); + } + + public boolean isEdit(String isEdit) + { + return isEdit != null && StringUtils.equals("1", isEdit); + } + + public void setIsList(String isList) + { + this.isList = isList; + } + + public String getIsList() + { + return isList; + } + + public boolean isList() + { + return isList(this.isList); + } + + public boolean isList(String isList) + { + return isList != null && StringUtils.equals("1", isList); + } + + public void setIsQuery(String isQuery) + { + this.isQuery = isQuery; + } + + public String getIsQuery() + { + return isQuery; + } + + public boolean isQuery() + { + return isQuery(this.isQuery); + } + + public boolean isQuery(String isQuery) + { + return isQuery != null && StringUtils.equals("1", isQuery); + } + + public void setQueryType(String queryType) + { + this.queryType = queryType; + } + + public String getQueryType() + { + return queryType; + } + + public String getHtmlType() + { + return htmlType; + } + + public void setHtmlType(String htmlType) + { + this.htmlType = htmlType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getDictType() + { + return dictType; + } + + public void setSort(Integer sort) + { + this.sort = sort; + } + + public Integer getSort() + { + return sort; + } + + public boolean isSuperColumn() + { + return isSuperColumn(this.javaField); + } + + public static boolean isSuperColumn(String javaField) + { + return StringUtils.equalsAnyIgnoreCase(javaField, + // BaseEntity + "createBy", "createTime", "updateBy", "updateTime", "remark", + // TreeEntity + "parentName", "parentId", "orderNum", "ancestors"); + } + + public boolean isUsableColumn() + { + return isUsableColumn(javaField); + } + + public static boolean isUsableColumn(String javaField) + { + // isSuperColumn()中的åå•用于é¿å…生æˆå¤šä½™Domain属性,若æŸäº›å±žæ€§åœ¨ç”Ÿæˆé¡µé¢æ—¶éœ€è¦ç”¨åˆ°ä¸èƒ½å¿½ç•¥ï¼Œåˆ™æ”¾åœ¨æ­¤å¤„白åå• + return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark"); + } + + public String readConverterExp() + { + String remarks = StringUtils.substringBetween(this.columnComment, "(", ")"); + StringBuffer sb = new StringBuffer(); + if (StringUtils.isNotEmpty(remarks)) + { + for (String value : remarks.split(" ")) + { + if (StringUtils.isNotEmpty(value)) + { + Object startStr = value.subSequence(0, 1); + String endStr = value.substring(1); + sb.append("").append(startStr).append("=").append(endStr).append(","); + } + } + return sb.deleteCharAt(sb.length() - 1).toString(); + } + else + { + return this.columnComment; + } + } +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java new file mode 100644 index 0000000..0dc3428 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java @@ -0,0 +1,60 @@ +package com.ruoyi.generator.mapper; + +import java.util.List; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 业务字段 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface GenTableColumnMapper +{ + /** + * æ ¹æ®è¡¨åç§°æŸ¥è¯¢åˆ—ä¿¡æ¯ + * + * @param tableName 表åç§° + * @return åˆ—ä¿¡æ¯ + */ + public List selectDbTableColumnsByName(String tableName); + + /** + * 查询业务字段列表 + * + * @param tableId ä¸šåŠ¡å­—æ®µç¼–å· + * @return ä¸šåŠ¡å­—æ®µé›†åˆ + */ + public List selectGenTableColumnListByTableId(Long tableId); + + /** + * 新增业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + public int insertGenTableColumn(GenTableColumn genTableColumn); + + /** + * 修改业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + public int updateGenTableColumn(GenTableColumn genTableColumn); + + /** + * 删除业务字段 + * + * @param genTableColumns åˆ—æ•°æ® + * @return 结果 + */ + public int deleteGenTableColumns(List genTableColumns); + + /** + * 批é‡åˆ é™¤ä¸šåŠ¡å­—æ®µ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteGenTableColumnByIds(Long[] ids); +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java new file mode 100644 index 0000000..c2fdf71 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java @@ -0,0 +1,83 @@ +package com.ruoyi.generator.mapper; + +import java.util.List; +import com.ruoyi.generator.domain.GenTable; + +/** + * 业务 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface GenTableMapper +{ + /** + * 查询业务列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return ä¸šåŠ¡é›†åˆ + */ + public List selectGenTableList(GenTable genTable); + + /** + * 查询æ®åº“列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + public List selectDbTableList(GenTable genTable); + + /** + * 查询æ®åº“列表 + * + * @param tableNames 表å称组 + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + public List selectDbTableListByNames(String[] tableNames); + + /** + * æŸ¥è¯¢æ‰€æœ‰è¡¨ä¿¡æ¯ + * + * @return 表信æ¯é›†åˆ + */ + public List selectGenTableAll(); + + /** + * 查询表IDä¸šåŠ¡ä¿¡æ¯ + * + * @param id 业务ID + * @return ä¸šåŠ¡ä¿¡æ¯ + */ + public GenTable selectGenTableById(Long id); + + /** + * 查询表åç§°ä¸šåŠ¡ä¿¡æ¯ + * + * @param tableName 表åç§° + * @return ä¸šåŠ¡ä¿¡æ¯ + */ + public GenTable selectGenTableByName(String tableName); + + /** + * 新增业务 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return 结果 + */ + public int insertGenTable(GenTable genTable); + + /** + * 修改业务 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return 结果 + */ + public int updateGenTable(GenTable genTable); + + /** + * 批é‡åˆ é™¤ä¸šåŠ¡ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteGenTableByIds(Long[] ids); +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java new file mode 100644 index 0000000..3a2d66a --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java @@ -0,0 +1,68 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; + +/** + * 业务字段 æœåŠ¡å±‚å®žçŽ° + * + * @author ruoyi + */ +@Service +public class GenTableColumnServiceImpl implements IGenTableColumnService +{ + @Autowired + private GenTableColumnMapper genTableColumnMapper; + + /** + * 查询业务字段列表 + * + * @param tableId ä¸šåŠ¡å­—æ®µç¼–å· + * @return ä¸šåŠ¡å­—æ®µé›†åˆ + */ + @Override + public List selectGenTableColumnListByTableId(Long tableId) + { + return genTableColumnMapper.selectGenTableColumnListByTableId(tableId); + } + + /** + * 新增业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertGenTableColumn(GenTableColumn genTableColumn) + { + return genTableColumnMapper.insertGenTableColumn(genTableColumn); + } + + /** + * 修改业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateGenTableColumn(GenTableColumn genTableColumn) + { + return genTableColumnMapper.updateGenTableColumn(genTableColumn); + } + + /** + * 删除业务字段对象 + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + @Override + public int deleteGenTableColumnByIds(String ids) + { + return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids)); + } +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java new file mode 100644 index 0000000..1620995 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -0,0 +1,521 @@ +package com.ruoyi.generator.service; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.core.text.CharsetKit; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; +import com.ruoyi.generator.mapper.GenTableMapper; +import com.ruoyi.generator.util.GenUtils; +import com.ruoyi.generator.util.VelocityInitializer; +import com.ruoyi.generator.util.VelocityUtils; + +/** + * 业务 æœåŠ¡å±‚å®žçŽ° + * + * @author ruoyi + */ +@Service +public class GenTableServiceImpl implements IGenTableService +{ + private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class); + + @Autowired + private GenTableMapper genTableMapper; + + @Autowired + private GenTableColumnMapper genTableColumnMapper; + + /** + * æŸ¥è¯¢ä¸šåŠ¡ä¿¡æ¯ + * + * @param id 业务ID + * @return ä¸šåŠ¡ä¿¡æ¯ + */ + @Override + public GenTable selectGenTableById(Long id) + { + GenTable genTable = genTableMapper.selectGenTableById(id); + setTableFromOptions(genTable); + return genTable; + } + + /** + * 查询业务列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return ä¸šåŠ¡é›†åˆ + */ + @Override + public List selectGenTableList(GenTable genTable) + { + return genTableMapper.selectGenTableList(genTable); + } + + /** + * 查询æ®åº“列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + @Override + public List selectDbTableList(GenTable genTable) + { + return genTableMapper.selectDbTableList(genTable); + } + + /** + * 查询æ®åº“列表 + * + * @param tableNames 表å称组 + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + @Override + public List selectDbTableListByNames(String[] tableNames) + { + return genTableMapper.selectDbTableListByNames(tableNames); + } + + /** + * æŸ¥è¯¢æ‰€æœ‰è¡¨ä¿¡æ¯ + * + * @return 表信æ¯é›†åˆ + */ + @Override + public List selectGenTableAll() + { + return genTableMapper.selectGenTableAll(); + } + + /** + * 修改业务 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public void updateGenTable(GenTable genTable) + { + String options = JSON.toJSONString(genTable.getParams()); + genTable.setOptions(options); + int row = genTableMapper.updateGenTable(genTable); + if (row > 0) + { + for (GenTableColumn cenTableColumn : genTable.getColumns()) + { + genTableColumnMapper.updateGenTableColumn(cenTableColumn); + } + } + } + + /** + * 删除业务对象 + * + * @param tableIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + @Override + @Transactional + public void deleteGenTableByIds(Long[] tableIds) + { + genTableMapper.deleteGenTableByIds(tableIds); + genTableColumnMapper.deleteGenTableColumnByIds(tableIds); + } + + /** + * 导入表结构 + * + * @param tableList 导入表列表 + */ + @Override + @Transactional + public void importGenTable(List tableList) + { + String operName = SecurityUtils.getUsername(); + try + { + for (GenTable table : tableList) + { + String tableName = table.getTableName(); + GenUtils.initTable(table, operName); + int row = genTableMapper.insertGenTable(table); + if (row > 0) + { + // ä¿å­˜åˆ—ä¿¡æ¯ + List genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); + for (GenTableColumn column : genTableColumns) + { + GenUtils.initColumnField(column, table); + genTableColumnMapper.insertGenTableColumn(column); + } + } + } + } + catch (Exception e) + { + throw new ServiceException("导入失败:" + e.getMessage()); + } + } + + /** + * é¢„è§ˆä»£ç  + * + * @param tableId è¡¨ç¼–å· + * @return 预览数æ®åˆ—表 + */ + @Override + public Map previewCode(Long tableId) + { + Map dataMap = new LinkedHashMap<>(); + // æŸ¥è¯¢è¡¨ä¿¡æ¯ + GenTable table = genTableMapper.selectGenTableById(tableId); + // 设置主å­è¡¨ä¿¡æ¯ + setSubTable(table); + // è®¾ç½®ä¸»é”®åˆ—ä¿¡æ¯ + setPkColumn(table); + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // èŽ·å–æ¨¡æ¿åˆ—表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + // æ¸²æŸ“æ¨¡æ¿ + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + dataMap.put(template, sw.toString()); + } + return dataMap; + } + + /** + * 生æˆä»£ç ï¼ˆä¸‹è½½æ–¹å¼ï¼‰ + * + * @param tableName 表åç§° + * @return æ•°æ® + */ + @Override + public byte[] downloadCode(String tableName) + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + generatorCode(tableName, zip); + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + /** + * 生æˆä»£ç ï¼ˆè‡ªå®šä¹‰è·¯å¾„) + * + * @param tableName 表åç§° + */ + @Override + public void generatorCode(String tableName) + { + // æŸ¥è¯¢è¡¨ä¿¡æ¯ + GenTable table = genTableMapper.selectGenTableByName(tableName); + // 设置主å­è¡¨ä¿¡æ¯ + setSubTable(table); + // è®¾ç½®ä¸»é”®åˆ—ä¿¡æ¯ + setPkColumn(table); + + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // èŽ·å–æ¨¡æ¿åˆ—表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) + { + // æ¸²æŸ“æ¨¡æ¿ + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + try + { + String path = getGenPath(table, template); + FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8); + } + catch (IOException e) + { + throw new ServiceException("渲染模æ¿å¤±è´¥ï¼Œè¡¨å:" + table.getTableName()); + } + } + } + } + + /** + * åŒæ­¥æ•°æ®åº“ + * + * @param tableName 表åç§° + */ + @Override + @Transactional + public void synchDb(String tableName) + { + GenTable table = genTableMapper.selectGenTableByName(tableName); + List tableColumns = table.getColumns(); + Map tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity())); + + List dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); + if (StringUtils.isEmpty(dbTableColumns)) + { + throw new ServiceException("åŒæ­¥æ•°æ®å¤±è´¥ï¼ŒåŽŸè¡¨ç»“æž„ä¸å­˜åœ¨"); + } + List dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); + + dbTableColumns.forEach(column -> { + GenUtils.initColumnField(column, table); + if (tableColumnMap.containsKey(column.getColumnName())) + { + GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName()); + column.setColumnId(prevColumn.getColumnId()); + if (column.isList()) + { + // 如果是列表,继续ä¿ç•™æŸ¥è¯¢æ–¹å¼/字典类型选项 + column.setDictType(prevColumn.getDictType()); + column.setQueryType(prevColumn.getQueryType()); + } + if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk() + && (column.isInsert() || column.isEdit()) + && ((column.isUsableColumn()) || (!column.isSuperColumn()))) + { + // 如果是(新增/修改&éžä¸»é”®/éžå¿½ç•¥åŠçˆ¶å±žæ€§),继续ä¿ç•™å¿…å¡«/显示类型选项 + column.setIsRequired(prevColumn.getIsRequired()); + column.setHtmlType(prevColumn.getHtmlType()); + } + genTableColumnMapper.updateGenTableColumn(column); + } + else + { + genTableColumnMapper.insertGenTableColumn(column); + } + }); + + List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); + if (StringUtils.isNotEmpty(delColumns)) + { + genTableColumnMapper.deleteGenTableColumns(delColumns); + } + } + + /** + * 批é‡ç”Ÿæˆä»£ç ï¼ˆä¸‹è½½æ–¹å¼ï¼‰ + * + * @param tableNames 表数组 + * @return æ•°æ® + */ + @Override + public byte[] downloadCode(String[] tableNames) + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + for (String tableName : tableNames) + { + generatorCode(tableName, zip); + } + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + /** + * 查询表信æ¯å¹¶ç”Ÿæˆä»£ç  + */ + private void generatorCode(String tableName, ZipOutputStream zip) + { + // æŸ¥è¯¢è¡¨ä¿¡æ¯ + GenTable table = genTableMapper.selectGenTableByName(tableName); + // 设置主å­è¡¨ä¿¡æ¯ + setSubTable(table); + // è®¾ç½®ä¸»é”®åˆ—ä¿¡æ¯ + setPkColumn(table); + + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // èŽ·å–æ¨¡æ¿åˆ—表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + // æ¸²æŸ“æ¨¡æ¿ + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + try + { + // 添加到zip + zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); + IOUtils.write(sw.toString(), zip, Constants.UTF8); + IOUtils.closeQuietly(sw); + zip.flush(); + zip.closeEntry(); + } + catch (IOException e) + { + log.error("渲染模æ¿å¤±è´¥ï¼Œè¡¨å:" + table.getTableName(), e); + } + } + } + + /** + * 修改ä¿å­˜å‚数校验 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + */ + @Override + public void validateEdit(GenTable genTable) + { + if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) + { + String options = JSON.toJSONString(genTable.getParams()); + JSONObject paramsObj = JSON.parseObject(options); + if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) + { + throw new ServiceException("æ ‘ç¼–ç å­—段ä¸èƒ½ä¸ºç©º"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) + { + throw new ServiceException("树父编ç å­—段ä¸èƒ½ä¸ºç©º"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) + { + throw new ServiceException("æ ‘å称字段ä¸èƒ½ä¸ºç©º"); + } + else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) + { + if (StringUtils.isEmpty(genTable.getSubTableName())) + { + throw new ServiceException("å…³è”å­è¡¨çš„表åä¸èƒ½ä¸ºç©º"); + } + else if (StringUtils.isEmpty(genTable.getSubTableFkName())) + { + throw new ServiceException("å­è¡¨å…³è”的外键åä¸èƒ½ä¸ºç©º"); + } + } + } + } + + /** + * è®¾ç½®ä¸»é”®åˆ—ä¿¡æ¯ + * + * @param table ä¸šåŠ¡è¡¨ä¿¡æ¯ + */ + public void setPkColumn(GenTable table) + { + for (GenTableColumn column : table.getColumns()) + { + if (column.isPk()) + { + table.setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getPkColumn())) + { + table.setPkColumn(table.getColumns().get(0)); + } + if (GenConstants.TPL_SUB.equals(table.getTplCategory())) + { + for (GenTableColumn column : table.getSubTable().getColumns()) + { + if (column.isPk()) + { + table.getSubTable().setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getSubTable().getPkColumn())) + { + table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0)); + } + } + } + + /** + * 设置主å­è¡¨ä¿¡æ¯ + * + * @param table ä¸šåŠ¡è¡¨ä¿¡æ¯ + */ + public void setSubTable(GenTable table) + { + String subTableName = table.getSubTableName(); + if (StringUtils.isNotEmpty(subTableName)) + { + table.setSubTable(genTableMapper.selectGenTableByName(subTableName)); + } + } + + /** + * 设置代ç ç”Ÿæˆå…¶ä»–选项值 + * + * @param genTable 设置åŽçš„生æˆå¯¹è±¡ + */ + public void setTableFromOptions(GenTable genTable) + { + JSONObject paramsObj = JSON.parseObject(genTable.getOptions()); + if (StringUtils.isNotNull(paramsObj)) + { + String treeCode = paramsObj.getString(GenConstants.TREE_CODE); + String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID); + String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME); + + genTable.setTreeCode(treeCode); + genTable.setTreeParentCode(treeParentCode); + genTable.setTreeName(treeName); + genTable.setParentMenuId(parentMenuId); + genTable.setParentMenuName(parentMenuName); + } + } + + /** + * 获å–代ç ç”Ÿæˆåœ°å€ + * + * @param table ä¸šåŠ¡è¡¨ä¿¡æ¯ + * @param template æ¨¡æ¿æ–‡ä»¶è·¯å¾„ + * @return 生æˆåœ°å€ + */ + public static String getGenPath(GenTable table, String template) + { + String genPath = table.getGenPath(); + if (StringUtils.equals(genPath, "/")) + { + return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table); + } + return genPath + File.separator + VelocityUtils.getFileName(template, table); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java new file mode 100644 index 0000000..2130d04 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java @@ -0,0 +1,44 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 业务字段 æœåС层 + * + * @author ruoyi + */ +public interface IGenTableColumnService +{ + /** + * 查询业务字段列表 + * + * @param tableId ä¸šåŠ¡å­—æ®µç¼–å· + * @return ä¸šåŠ¡å­—æ®µé›†åˆ + */ + public List selectGenTableColumnListByTableId(Long tableId); + + /** + * 新增业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + public int insertGenTableColumn(GenTableColumn genTableColumn); + + /** + * 修改业务字段 + * + * @param genTableColumn ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * @return 结果 + */ + public int updateGenTableColumn(GenTableColumn genTableColumn); + + /** + * åˆ é™¤ä¸šåŠ¡å­—æ®µä¿¡æ¯ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteGenTableColumnByIds(String ids); +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java new file mode 100644 index 0000000..955b326 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java @@ -0,0 +1,121 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import java.util.Map; +import com.ruoyi.generator.domain.GenTable; + +/** + * 业务 æœåС层 + * + * @author ruoyi + */ +public interface IGenTableService +{ + /** + * 查询业务列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return ä¸šåŠ¡é›†åˆ + */ + public List selectGenTableList(GenTable genTable); + + /** + * 查询æ®åº“列表 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + public List selectDbTableList(GenTable genTable); + + /** + * 查询æ®åº“列表 + * + * @param tableNames 表å称组 + * @return æ•°æ®åº“è¡¨é›†åˆ + */ + public List selectDbTableListByNames(String[] tableNames); + + /** + * æŸ¥è¯¢æ‰€æœ‰è¡¨ä¿¡æ¯ + * + * @return 表信æ¯é›†åˆ + */ + public List selectGenTableAll(); + + /** + * æŸ¥è¯¢ä¸šåŠ¡ä¿¡æ¯ + * + * @param id 业务ID + * @return ä¸šåŠ¡ä¿¡æ¯ + */ + public GenTable selectGenTableById(Long id); + + /** + * 修改业务 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + * @return 结果 + */ + public void updateGenTable(GenTable genTable); + + /** + * åˆ é™¤ä¸šåŠ¡ä¿¡æ¯ + * + * @param tableIds 需è¦åˆ é™¤çš„表数æ®ID + * @return 结果 + */ + public void deleteGenTableByIds(Long[] tableIds); + + /** + * 导入表结构 + * + * @param tableList 导入表列表 + */ + public void importGenTable(List tableList); + + /** + * é¢„è§ˆä»£ç  + * + * @param tableId è¡¨ç¼–å· + * @return 预览数æ®åˆ—表 + */ + public Map previewCode(Long tableId); + + /** + * 生æˆä»£ç ï¼ˆä¸‹è½½æ–¹å¼ï¼‰ + * + * @param tableName 表åç§° + * @return æ•°æ® + */ + public byte[] downloadCode(String tableName); + + /** + * 生æˆä»£ç ï¼ˆè‡ªå®šä¹‰è·¯å¾„) + * + * @param tableName 表åç§° + * @return æ•°æ® + */ + public void generatorCode(String tableName); + + /** + * åŒæ­¥æ•°æ®åº“ + * + * @param tableName 表åç§° + */ + public void synchDb(String tableName); + + /** + * 批é‡ç”Ÿæˆä»£ç ï¼ˆä¸‹è½½æ–¹å¼ï¼‰ + * + * @param tableNames 表数组 + * @return æ•°æ® + */ + public byte[] downloadCode(String[] tableNames); + + /** + * 修改ä¿å­˜å‚数校验 + * + * @param genTable ä¸šåŠ¡ä¿¡æ¯ + */ + public void validateEdit(GenTable genTable); +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java new file mode 100644 index 0000000..e28c0bb --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -0,0 +1,257 @@ +package com.ruoyi.generator.util; + +import java.util.Arrays; +import org.apache.commons.lang3.RegExUtils; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.config.GenConfig; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 代ç ç”Ÿæˆå™¨ 工具类 + * + * @author ruoyi + */ +public class GenUtils +{ + /** + * åˆå§‹åŒ–è¡¨ä¿¡æ¯ + */ + public static void initTable(GenTable genTable, String operName) + { + genTable.setClassName(convertClassName(genTable.getTableName())); + genTable.setPackageName(GenConfig.getPackageName()); + genTable.setModuleName(getModuleName(GenConfig.getPackageName())); + genTable.setBusinessName(getBusinessName(genTable.getTableName())); + genTable.setFunctionName(replaceText(genTable.getTableComment())); + genTable.setFunctionAuthor(GenConfig.getAuthor()); + genTable.setCreateBy(operName); + } + + /** + * åˆå§‹åŒ–列属性字段 + */ + public static void initColumnField(GenTableColumn column, GenTable table) + { + String dataType = getDbType(column.getColumnType()); + String columnName = column.getColumnName(); + column.setTableId(table.getTableId()); + column.setCreateBy(table.getCreateBy()); + // 设置java字段å + column.setJavaField(StringUtils.toCamelCase(columnName)); + // 设置默认类型 + column.setJavaType(GenConstants.TYPE_STRING); + column.setQueryType(GenConstants.QUERY_EQ); + + if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) + { + // 字符串长度超过500设置为文本域 + Integer columnLength = getColumnLength(column.getColumnType()); + String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; + column.setHtmlType(htmlType); + } + else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) + { + column.setJavaType(GenConstants.TYPE_DATE); + column.setHtmlType(GenConstants.HTML_DATETIME); + } + else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) + { + column.setHtmlType(GenConstants.HTML_INPUT); + + // 如果是浮点型 统一用BigDecimal + String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); + if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) + { + column.setJavaType(GenConstants.TYPE_BIGDECIMAL); + } + // 如果是整形 + else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) + { + column.setJavaType(GenConstants.TYPE_INTEGER); + } + // é•¿æ•´å½¢ + else + { + column.setJavaType(GenConstants.TYPE_LONG); + } + } + + // æ’å…¥å­—æ®µï¼ˆé»˜è®¤æ‰€æœ‰å­—æ®µéƒ½éœ€è¦æ’入) + column.setIsInsert(GenConstants.REQUIRE); + + // 编辑字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) + { + column.setIsEdit(GenConstants.REQUIRE); + } + // 列表字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) + { + column.setIsList(GenConstants.REQUIRE); + } + // 查询字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) + { + column.setIsQuery(GenConstants.REQUIRE); + } + + // 查询字段类型 + if (StringUtils.endsWithIgnoreCase(columnName, "name")) + { + column.setQueryType(GenConstants.QUERY_LIKE); + } + // 状æ€å­—段设置å•选框 + if (StringUtils.endsWithIgnoreCase(columnName, "status")) + { + column.setHtmlType(GenConstants.HTML_RADIO); + } + // 类型&性别字段设置下拉框 + else if (StringUtils.endsWithIgnoreCase(columnName, "type") + || StringUtils.endsWithIgnoreCase(columnName, "sex")) + { + column.setHtmlType(GenConstants.HTML_SELECT); + } + // 图片字段设置图片上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "image")) + { + column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD); + } + // 文件字段设置文件上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "file")) + { + column.setHtmlType(GenConstants.HTML_FILE_UPLOAD); + } + // 内容字段设置富文本控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "content")) + { + column.setHtmlType(GenConstants.HTML_EDITOR); + } + } + + /** + * 校验数组是å¦åŒ…嫿Œ‡å®šå€¼ + * + * @param arr 数组 + * @param targetValue 值 + * @return 是å¦åŒ…å« + */ + public static boolean arraysContains(String[] arr, String targetValue) + { + return Arrays.asList(arr).contains(targetValue); + } + + /** + * èŽ·å–æ¨¡å—å + * + * @param packageName 包å + * @return 模å—å + */ + public static String getModuleName(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + int nameLength = packageName.length(); + return StringUtils.substring(packageName, lastIndex + 1, nameLength); + } + + /** + * 获å–业务å + * + * @param tableName 表å + * @return 业务å + */ + public static String getBusinessName(String tableName) + { + int lastIndex = tableName.lastIndexOf("_"); + int nameLength = tableName.length(); + return StringUtils.substring(tableName, lastIndex + 1, nameLength); + } + + /** + * 表åè½¬æ¢æˆJavaç±»å + * + * @param tableName 表åç§° + * @return ç±»å + */ + public static String convertClassName(String tableName) + { + boolean autoRemovePre = GenConfig.getAutoRemovePre(); + String tablePrefix = GenConfig.getTablePrefix(); + if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) + { + String[] searchList = StringUtils.split(tablePrefix, ","); + tableName = replaceFirst(tableName, searchList); + } + return StringUtils.convertToCamelCase(tableName); + } + + /** + * æ‰¹é‡æ›¿æ¢å‰ç¼€ + * + * @param replacementm 替æ¢å€¼ + * @param searchList 替æ¢åˆ—表 + * @return + */ + public static String replaceFirst(String replacementm, String[] searchList) + { + String text = replacementm; + for (String searchString : searchList) + { + if (replacementm.startsWith(searchString)) + { + text = replacementm.replaceFirst(searchString, ""); + break; + } + } + return text; + } + + /** + * å…³é”®å­—æ›¿æ¢ + * + * @param text 需è¦è¢«æ›¿æ¢çš„åå­— + * @return 替æ¢åŽçš„åå­— + */ + public static String replaceText(String text) + { + return RegExUtils.replaceAll(text, "(?:表|è‹¥ä¾)", ""); + } + + /** + * èŽ·å–æ•°æ®åº“类型字段 + * + * @param columnType 列类型 + * @return 截å–åŽçš„列类型 + */ + public static String getDbType(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + return StringUtils.substringBefore(columnType, "("); + } + else + { + return columnType; + } + } + + /** + * 获å–字段长度 + * + * @param columnType 列类型 + * @return 截å–åŽçš„列类型 + */ + public static Integer getColumnLength(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + String length = StringUtils.substringBetween(columnType, "(", ")"); + return Integer.valueOf(length); + } + else + { + return 0; + } + } +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java new file mode 100644 index 0000000..2645633 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java @@ -0,0 +1,34 @@ +package com.ruoyi.generator.util; + +import java.util.Properties; +import org.apache.velocity.app.Velocity; +import com.ruoyi.common.constant.Constants; + +/** + * VelocityEngine工厂 + * + * @author ruoyi + */ +public class VelocityInitializer +{ + /** + * åˆå§‹åŒ–vm方法 + */ + public static void initVelocity() + { + Properties p = new Properties(); + try + { + // 加载classpath目录下的vm文件 + p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + // 定义字符集 + p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); + // åˆå§‹åŒ–Velocity引擎,指定é…ç½®Properties + Velocity.init(p); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } +} diff --git a/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java new file mode 100644 index 0000000..733c714 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -0,0 +1,402 @@ +package com.ruoyi.generator.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.velocity.VelocityContext; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 模æ¿å¤„ç†å·¥å…·ç±» + * + * @author ruoyi + */ +public class VelocityUtils +{ + /** 项目空间路径 */ + private static final String PROJECT_PATH = "main/java"; + + /** mybatis空间路径 */ + private static final String MYBATIS_PATH = "main/resources/mapper"; + + /** 默认上级èœå•,系统工具 */ + private static final String DEFAULT_PARENT_MENU_ID = "3"; + + /** + * 设置模æ¿å˜é‡ä¿¡æ¯ + * + * @return 模æ¿åˆ—表 + */ + public static VelocityContext prepareContext(GenTable genTable) + { + String moduleName = genTable.getModuleName(); + String businessName = genTable.getBusinessName(); + String packageName = genTable.getPackageName(); + String tplCategory = genTable.getTplCategory(); + String functionName = genTable.getFunctionName(); + + VelocityContext velocityContext = new VelocityContext(); + velocityContext.put("tplCategory", genTable.getTplCategory()); + velocityContext.put("tableName", genTable.getTableName()); + velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "ã€è¯·å¡«å†™åŠŸèƒ½å称】"); + velocityContext.put("ClassName", genTable.getClassName()); + velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName())); + velocityContext.put("moduleName", genTable.getModuleName()); + velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName())); + velocityContext.put("businessName", genTable.getBusinessName()); + velocityContext.put("basePackage", getPackagePrefix(packageName)); + velocityContext.put("packageName", packageName); + velocityContext.put("author", genTable.getFunctionAuthor()); + velocityContext.put("datetime", DateUtils.getDate()); + velocityContext.put("pkColumn", genTable.getPkColumn()); + velocityContext.put("importList", getImportList(genTable)); + velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); + velocityContext.put("columns", genTable.getColumns()); + velocityContext.put("table", genTable); + velocityContext.put("dicts", getDicts(genTable)); + setMenuVelocityContext(velocityContext, genTable); + if (GenConstants.TPL_TREE.equals(tplCategory)) + { + setTreeVelocityContext(velocityContext, genTable); + } + if (GenConstants.TPL_SUB.equals(tplCategory)) + { + setSubVelocityContext(velocityContext, genTable); + } + return velocityContext; + } + + public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String parentMenuId = getParentMenuId(paramsObj); + context.put("parentMenuId", parentMenuId); + } + + public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeCode = getTreecode(paramsObj); + String treeParentCode = getTreeParentCode(paramsObj); + String treeName = getTreeName(paramsObj); + + context.put("treeCode", treeCode); + context.put("treeParentCode", treeParentCode); + context.put("treeName", treeName); + context.put("expandColumn", getExpandColumn(genTable)); + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME)); + } + } + + public static void setSubVelocityContext(VelocityContext context, GenTable genTable) + { + GenTable subTable = genTable.getSubTable(); + String subTableName = genTable.getSubTableName(); + String subTableFkName = genTable.getSubTableFkName(); + String subClassName = genTable.getSubTable().getClassName(); + String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName); + + context.put("subTable", subTable); + context.put("subTableName", subTableName); + context.put("subTableFkName", subTableFkName); + context.put("subTableFkClassName", subTableFkClassName); + context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName)); + context.put("subClassName", subClassName); + context.put("subclassName", StringUtils.uncapitalize(subClassName)); + context.put("subImportList", getImportList(genTable.getSubTable())); + } + + /** + * èŽ·å–æ¨¡æ¿ä¿¡æ¯ + * + * @return 模æ¿åˆ—表 + */ + public static List getTemplateList(String tplCategory) + { + List templates = new ArrayList(); + templates.add("vm/java/domain.java.vm"); + templates.add("vm/java/mapper.java.vm"); + templates.add("vm/java/service.java.vm"); + templates.add("vm/java/serviceImpl.java.vm"); + templates.add("vm/java/controller.java.vm"); + templates.add("vm/xml/mapper.xml.vm"); + templates.add("vm/sql/sql.vm"); + templates.add("vm/js/api.js.vm"); + if (GenConstants.TPL_CRUD.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + } + else if (GenConstants.TPL_TREE.equals(tplCategory)) + { + templates.add("vm/vue/index-tree.vue.vm"); + } + else if (GenConstants.TPL_SUB.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + templates.add("vm/java/sub-domain.java.vm"); + } + return templates; + } + + /** + * èŽ·å–æ–‡ä»¶å + */ + public static String getFileName(String template, GenTable genTable) + { + // 文件åç§° + String fileName = ""; + // 包路径 + String packageName = genTable.getPackageName(); + // 模å—å + String moduleName = genTable.getModuleName(); + // 大写类å + String className = genTable.getClassName(); + // 业务åç§° + String businessName = genTable.getBusinessName(); + + String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/"); + String mybatisPath = MYBATIS_PATH + "/" + moduleName; + String vuePath = "vue"; + + if (template.contains("domain.java.vm")) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, className); + } + if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory())) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName()); + } + else if (template.contains("mapper.java.vm")) + { + fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); + } + else if (template.contains("service.java.vm")) + { + fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className); + } + else if (template.contains("serviceImpl.java.vm")) + { + fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); + } + else if (template.contains("controller.java.vm")) + { + fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); + } + else if (template.contains("mapper.xml.vm")) + { + fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); + } + else if (template.contains("sql.vm")) + { + fileName = businessName + "Menu.sql"; + } + else if (template.contains("api.js.vm")) + { + fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName); + } + else if (template.contains("index.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + else if (template.contains("index-tree.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + return fileName; + } + + /** + * 获å–包å‰ç¼€ + * + * @param packageName 包åç§° + * @return 包å‰ç¼€åç§° + */ + public static String getPackagePrefix(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + return StringUtils.substring(packageName, 0, lastIndex); + } + + /** + * æ ¹æ®åˆ—类型获å–导入包 + * + * @param genTable 业务表对象 + * @return 返回需è¦å¯¼å…¥çš„包列表 + */ + public static HashSet getImportList(GenTable genTable) + { + List columns = genTable.getColumns(); + GenTable subGenTable = genTable.getSubTable(); + HashSet importList = new HashSet(); + if (StringUtils.isNotNull(subGenTable)) + { + importList.add("java.util.List"); + } + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) + { + importList.add("java.util.Date"); + importList.add("com.fasterxml.jackson.annotation.JsonFormat"); + } + else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) + { + importList.add("java.math.BigDecimal"); + } + } + return importList; + } + + /** + * æ ¹æ®åˆ—类型获å–字典组 + * + * @param genTable 业务表对象 + * @return 返回字典组 + */ + public static String getDicts(GenTable genTable) + { + List columns = genTable.getColumns(); + Set dicts = new HashSet(); + addDicts(dicts, columns); + if (StringUtils.isNotNull(genTable.getSubTable())) + { + List subColumns = genTable.getSubTable().getColumns(); + addDicts(dicts, subColumns); + } + return StringUtils.join(dicts, ", "); + } + + /** + * 添加字典列表 + * + * @param dicts 字典列表 + * @param columns åˆ—é›†åˆ + */ + public static void addDicts(Set dicts, List columns) + { + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny( + column.getHtmlType(), + new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) + { + dicts.add("'" + column.getDictType() + "'"); + } + } + } + + /** + * èŽ·å–æƒé™å‰ç¼€ + * + * @param moduleName 模å—åç§° + * @param businessName 业务åç§° + * @return 返回æƒé™å‰ç¼€ + */ + public static String getPermissionPrefix(String moduleName, String businessName) + { + return StringUtils.format("{}:{}", moduleName, businessName); + } + + /** + * 获å–上级èœå•ID字段 + * + * @param paramsObj 生æˆå…¶ä»–选项 + * @return 上级èœå•ID字段 + */ + public static String getParentMenuId(JSONObject paramsObj) + { + if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID) + && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) + { + return paramsObj.getString(GenConstants.PARENT_MENU_ID); + } + return DEFAULT_PARENT_MENU_ID; + } + + /** + * èŽ·å–æ ‘ç¼–ç  + * + * @param paramsObj 生æˆå…¶ä»–选项 + * @return æ ‘ç¼–ç  + */ + public static String getTreecode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * èŽ·å–æ ‘çˆ¶ç¼–ç  + * + * @param paramsObj 生æˆå…¶ä»–选项 + * @return æ ‘çˆ¶ç¼–ç  + */ + public static String getTreeParentCode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * èŽ·å–æ ‘åç§° + * + * @param paramsObj 生æˆå…¶ä»–选项 + * @return æ ‘åç§° + */ + public static String getTreeName(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); + } + return StringUtils.EMPTY; + } + + /** + * 获å–需è¦åœ¨å“ªä¸€åˆ—ä¸Šé¢æ˜¾ç¤ºå±•开按钮 + * + * @param genTable 业务表对象 + * @return 展开按钮列åºå· + */ + public static int getExpandColumn(GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + int num = 0; + for (GenTableColumn column : genTable.getColumns()) + { + if (column.isList()) + { + num++; + String columnName = column.getColumnName(); + if (columnName.equals(treeName)) + { + break; + } + } + } + return num; + } +} diff --git a/examapi/ruoyi-generator/src/main/resources/generator.yml b/examapi/ruoyi-generator/src/main/resources/generator.yml new file mode 100644 index 0000000..1aeec14 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/generator.yml @@ -0,0 +1,10 @@ +# 代ç ç”Ÿæˆ +gen: + # 作者 + author: ruoyi + # 默认生æˆåŒ…路径 system 需改æˆè‡ªå·±çš„æ¨¡å—åç§° 如 system monitor tool + packageName: com.ruoyi.system + # 自动去除表å‰ç¼€ï¼Œé»˜è®¤æ˜¯false + autoRemovePre: false + # 表å‰ç¼€ï¼ˆç”Ÿæˆç±»åä¸ä¼šåŒ…å«è¡¨å‰ç¼€ï¼Œå¤šä¸ªç”¨é€—å·åˆ†éš”) + tablePrefix: sys_ \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml new file mode 100644 index 0000000..c7bd42b --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column + + + + + + + + insert into gen_table_column ( + table_id, + column_name, + column_comment, + column_type, + java_type, + java_field, + is_pk, + is_increment, + is_required, + is_insert, + is_edit, + is_list, + is_query, + query_type, + html_type, + dict_type, + sort, + create_by, + create_time + )values( + #{tableId}, + #{columnName}, + #{columnComment}, + #{columnType}, + #{javaType}, + #{javaField}, + #{isPk}, + #{isIncrement}, + #{isRequired}, + #{isInsert}, + #{isEdit}, + #{isList}, + #{isQuery}, + #{queryType}, + #{htmlType}, + #{dictType}, + #{sort}, + #{createBy}, + sysdate() + ) + + + + update gen_table_column + + column_comment = #{columnComment}, + java_type = #{javaType}, + java_field = #{javaField}, + is_insert = #{isInsert}, + is_edit = #{isEdit}, + is_list = #{isList}, + is_query = #{isQuery}, + is_required = #{isRequired}, + query_type = #{queryType}, + html_type = #{htmlType}, + dict_type = #{dictType}, + sort = #{sort}, + update_by = #{updateBy}, + update_time = sysdate() + + where column_id = #{columnId} + + + + delete from gen_table_column where table_id in + + #{tableId} + + + + + delete from gen_table_column where column_id in + + #{item.columnId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml new file mode 100644 index 0000000..a4b5bbe --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table + + + + + + + + + + + + + + + + + + insert into gen_table ( + table_name, + table_comment, + class_name, + tpl_category, + package_name, + module_name, + business_name, + function_name, + function_author, + gen_type, + gen_path, + remark, + create_by, + create_time + )values( + #{tableName}, + #{tableComment}, + #{className}, + #{tplCategory}, + #{packageName}, + #{moduleName}, + #{businessName}, + #{functionName}, + #{functionAuthor}, + #{genType}, + #{genPath}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update gen_table + + table_name = #{tableName}, + table_comment = #{tableComment}, + sub_table_name = #{subTableName}, + sub_table_fk_name = #{subTableFkName}, + class_name = #{className}, + function_author = #{functionAuthor}, + gen_type = #{genType}, + gen_path = #{genPath}, + tpl_category = #{tplCategory}, + package_name = #{packageName}, + module_name = #{moduleName}, + business_name = #{businessName}, + function_name = #{functionName}, + options = #{options}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where table_id = #{tableId} + + + + delete from gen_table where table_id in + + #{tableId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/controller.java.vm new file mode 100644 index 0000000..bf88988 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -0,0 +1,115 @@ +package ${packageName}.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; +import com.ruoyi.common.utils.poi.ExcelUtil; +#if($table.crud || $table.sub) +import com.ruoyi.common.core.page.TableDataInfo; +#elseif($table.tree) +#end + +/** + * ${functionName}Controller + * + * @author ${author} + * @date ${datetime} + */ +@RestController +@RequestMapping("/${moduleName}/${businessName}") +public class ${ClassName}Controller extends BaseController +{ + @Autowired + private I${ClassName}Service ${className}Service; + + /** + * 查询${functionName}列表 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')") + @GetMapping("/list") +#if($table.crud || $table.sub) + public TableDataInfo list(${ClassName} ${className}) + { + startPage(); + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + return getDataTable(list); + } +#elseif($table.tree) + public AjaxResult list(${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + return success(list); + } +#end + + /** + * 导出${functionName}列表 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')") + @Log(title = "${functionName}", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, ${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); + util.exportExcel(response, list, "${functionName}æ•°æ®"); + } + + /** + * 获å–${functionName}è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')") + @GetMapping(value = "/{${pkColumn.javaField}}") + public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) + { + return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField})); + } + + /** + * 新增${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')") + @Log(title = "${functionName}", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.insert${ClassName}(${className})); + } + + /** + * 修改${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')") + @Log(title = "${functionName}", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.update${ClassName}(${className})); + } + + /** + * 删除${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')") + @Log(title = "${functionName}", businessType = BusinessType.DELETE) + @DeleteMapping("/{${pkColumn.javaField}s}") + public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) + { + return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s)); + } +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/domain.java.vm new file mode 100644 index 0000000..94a40a9 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/domain.java.vm @@ -0,0 +1,105 @@ +package ${packageName}.domain; + +#foreach ($import in $importList) +import ${import}; +#end +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +#if($table.crud || $table.sub) +import com.ruoyi.common.core.domain.BaseEntity; +#elseif($table.tree) +import com.ruoyi.common.core.domain.TreeEntity; +#end + +/** + * ${functionName}对象 ${tableName} + * + * @author ${author} + * @date ${datetime} + */ +#if($table.crud || $table.sub) +#set($Entity="BaseEntity") +#elseif($table.tree) +#set($Entity="TreeEntity") +#end +public class ${ClassName} extends ${Entity} +{ + private static final long serialVersionUID = 1L; + +#foreach ($column in $columns) +#if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ +#if($column.list) +#set($parentheseIndex=$column.columnComment.indexOf("(")) +#if($parentheseIndex != -1) +#set($comment=$column.columnComment.substring(0, $parentheseIndex)) +#else +#set($comment=$column.columnComment) +#end +#if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") +#elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") +#else + @Excel(name = "${comment}") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#if($table.sub) + /** $table.subTable.functionNameä¿¡æ¯ */ + private List<${subClassName}> ${subclassName}List; + +#end +#foreach ($column in $columns) +#if(!$table.isSuperColumn($column.javaField)) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + public void set${AttrName}($column.javaType $column.javaField) + { + this.$column.javaField = $column.javaField; + } + + public $column.javaType get${AttrName}() + { + return $column.javaField; + } +#end +#end + +#if($table.sub) + public List<${subClassName}> get${subClassName}List() + { + return ${subclassName}List; + } + + public void set${subClassName}List(List<${subClassName}> ${subclassName}List) + { + this.${subclassName}List = ${subclassName}List; + } + +#end + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) +#foreach ($column in $columns) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + .append("${column.javaField}", get${AttrName}()) +#end +#if($table.sub) + .append("${subclassName}List", get${subClassName}List()) +#end + .toString(); + } +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm new file mode 100644 index 0000000..7e7d7c2 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm @@ -0,0 +1,91 @@ +package ${packageName}.mapper; + +import java.util.List; +import ${packageName}.domain.${ClassName}; +#if($table.sub) +import ${packageName}.domain.${subClassName}; +#end + +/** + * ${functionName}MapperæŽ¥å£ + * + * @author ${author} + * @date ${datetime} + */ +public interface ${ClassName}Mapper +{ + /** + * 查询${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 查询${functionName}列表 + * + * @param ${className} ${functionName} + * @return ${functionName}é›†åˆ + */ + public List<${ClassName}> select${ClassName}List(${ClassName} ${className}); + + /** + * 新增${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int insert${ClassName}(${ClassName} ${className}); + + /** + * 修改${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int update${ClassName}(${ClassName} ${className}); + + /** + * 删除${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 批é‡åˆ é™¤${functionName} + * + * @param ${pkColumn.javaField}s 需è¦åˆ é™¤çš„æ•°æ®ä¸»é”®é›†åˆ + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); +#if($table.sub) + + /** + * 批é‡åˆ é™¤${subTable.functionName} + * + * @param ${pkColumn.javaField}s 需è¦åˆ é™¤çš„æ•°æ®ä¸»é”®é›†åˆ + * @return 结果 + */ + public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); + + /** + * æ‰¹é‡æ–°å¢ž${subTable.functionName} + * + * @param ${subclassName}List ${subTable.functionName}列表 + * @return 结果 + */ + public int batch${subClassName}(List<${subClassName}> ${subclassName}List); + + + /** + * 通过${functionName}主键删除${subTable.functionName}ä¿¡æ¯ + * + * @param ${pkColumn.javaField} ${functionName}ID + * @return 结果 + */ + public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField}); +#end +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/service.java.vm new file mode 100644 index 0000000..250f68c --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/service.java.vm @@ -0,0 +1,61 @@ +package ${packageName}.service; + +import java.util.List; +import ${packageName}.domain.${ClassName}; + +/** + * ${functionName}ServiceæŽ¥å£ + * + * @author ${author} + * @date ${datetime} + */ +public interface I${ClassName}Service +{ + /** + * 查询${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 查询${functionName}列表 + * + * @param ${className} ${functionName} + * @return ${functionName}é›†åˆ + */ + public List<${ClassName}> select${ClassName}List(${ClassName} ${className}); + + /** + * 新增${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int insert${ClassName}(${ClassName} ${className}); + + /** + * 修改${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int update${ClassName}(${ClassName} ${className}); + + /** + * 批é‡åˆ é™¤${functionName} + * + * @param ${pkColumn.javaField}s 需è¦åˆ é™¤çš„${functionName}ä¸»é”®é›†åˆ + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); + + /** + * 删除${functionName}ä¿¡æ¯ + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm new file mode 100644 index 0000000..116f6c5 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -0,0 +1,169 @@ +package ${packageName}.service.impl; + +import java.util.List; +#foreach ($column in $columns) +#if($column.javaField == 'createTime' || $column.javaField == 'updateTime') +import com.ruoyi.common.utils.DateUtils; +#break +#end +#end +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +#if($table.sub) +import java.util.ArrayList; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.transaction.annotation.Transactional; +import ${packageName}.domain.${subClassName}; +#end +import ${packageName}.mapper.${ClassName}Mapper; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; + +/** + * ${functionName}Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author ${author} + * @date ${datetime} + */ +@Service +public class ${ClassName}ServiceImpl implements I${ClassName}Service +{ + @Autowired + private ${ClassName}Mapper ${className}Mapper; + + /** + * 查询${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + @Override + public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) + { + return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}); + } + + /** + * 查询${functionName}列表 + * + * @param ${className} ${functionName} + * @return ${functionName} + */ + @Override + public List<${ClassName}> select${ClassName}List(${ClassName} ${className}) + { + return ${className}Mapper.select${ClassName}List(${className}); + } + + /** + * 新增${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int insert${ClassName}(${ClassName} ${className}) + { +#foreach ($column in $columns) +#if($column.javaField == 'createTime') + ${className}.setCreateTime(DateUtils.getNowDate()); +#end +#end +#if($table.sub) + int rows = ${className}Mapper.insert${ClassName}(${className}); + insert${subClassName}(${className}); + return rows; +#else + return ${className}Mapper.insert${ClassName}(${className}); +#end + } + + /** + * 修改${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int update${ClassName}(${ClassName} ${className}) + { +#foreach ($column in $columns) +#if($column.javaField == 'updateTime') + ${className}.setUpdateTime(DateUtils.getNowDate()); +#end +#end +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}()); + insert${subClassName}(${className}); +#end + return ${className}Mapper.update${ClassName}(${className}); + } + + /** + * 批é‡åˆ é™¤${functionName} + * + * @param ${pkColumn.javaField}s 需è¦åˆ é™¤çš„${functionName}主键 + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s) + { +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s); +#end + return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s); + } + + /** + * 删除${functionName}ä¿¡æ¯ + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) + { +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField}); +#end + return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}); + } +#if($table.sub) + + /** + * 新增${subTable.functionName}ä¿¡æ¯ + * + * @param ${className} ${functionName}对象 + */ + public void insert${subClassName}(${ClassName} ${className}) + { + List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List(); + ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}(); + if (StringUtils.isNotNull(${subclassName}List)) + { + List<${subClassName}> list = new ArrayList<${subClassName}>(); + for (${subClassName} ${subclassName} : ${subclassName}List) + { + ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField}); + list.add(${subclassName}); + } + if (list.size() > 0) + { + ${className}Mapper.batch${subClassName}(list); + } + } + } +#end +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm b/examapi/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm new file mode 100644 index 0000000..b5e308c --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm @@ -0,0 +1,76 @@ +package ${packageName}.domain; + +#foreach ($import in $subImportList) +import ${import}; +#end +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * ${subTable.functionName}对象 ${subTableName} + * + * @author ${author} + * @date ${datetime} + */ +public class ${subClassName} extends BaseEntity +{ + private static final long serialVersionUID = 1L; + +#foreach ($column in $subTable.columns) +#if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ +#if($column.list) +#set($parentheseIndex=$column.columnComment.indexOf("(")) +#if($parentheseIndex != -1) +#set($comment=$column.columnComment.substring(0, $parentheseIndex)) +#else +#set($comment=$column.columnComment) +#end +#if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") +#elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") +#else + @Excel(name = "${comment}") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#foreach ($column in $subTable.columns) +#if(!$table.isSuperColumn($column.javaField)) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + public void set${AttrName}($column.javaType $column.javaField) + { + this.$column.javaField = $column.javaField; + } + + public $column.javaType get${AttrName}() + { + return $column.javaField; + } +#end +#end + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) +#foreach ($column in $subTable.columns) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + .append("${column.javaField}", get${AttrName}()) +#end + .toString(); + } +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/js/api.js.vm b/examapi/ruoyi-generator/src/main/resources/vm/js/api.js.vm new file mode 100644 index 0000000..d78cd2f --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/js/api.js.vm @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询${functionName}列表 +export function list${BusinessName}(query) { + return request({ + url: '/${moduleName}/${businessName}/list', + method: 'get', + params: query + }) +} + +// 查询${functionName}详细 +export function get${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'get' + }) +} + +// 新增${functionName} +export function add${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'post', + data: data + }) +} + +// 修改${functionName} +export function update${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'put', + data: data + }) +} + +// 删除${functionName} +export function del${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'delete' + }) +} diff --git a/examapi/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/examapi/ruoyi-generator/src/main/resources/vm/sql/sql.vm new file mode 100644 index 0000000..b50ef21 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/sql/sql.vm @@ -0,0 +1,22 @@ +-- èœå• SQL +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}èœå•'); + +-- 按钮父èœå•ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, ''); \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/examapi/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm new file mode 100644 index 0000000..b7fdb62 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -0,0 +1,505 @@ + + + diff --git a/examapi/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/examapi/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm new file mode 100644 index 0000000..70ff30d --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -0,0 +1,602 @@ + + + diff --git a/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm new file mode 100644 index 0000000..7bbd2fc --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -0,0 +1,474 @@ + + + diff --git a/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm new file mode 100644 index 0000000..8b25665 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm @@ -0,0 +1,590 @@ + + + diff --git a/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt new file mode 100644 index 0000000..99239bb --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt @@ -0,0 +1 @@ +Èç¹ûʹÓõÄÊÇRuoYi-Vue3ǰ¶Ë£¬ÄÇôÐèÒª¸²¸ÇһϴËĿ¼µÄÄ£°åindex.vue.vm¡¢index-tree.vue.vmÎļþµ½Éϼ¶vueĿ¼¡£ \ No newline at end of file diff --git a/examapi/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/examapi/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm new file mode 100644 index 0000000..5b704e7 --- /dev/null +++ b/examapi/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm @@ -0,0 +1,135 @@ + + + + + +#foreach ($column in $columns) + +#end + +#if($table.sub) + + + + + + +#foreach ($column in $subTable.columns) + +#end + +#end + + + select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName} + + + + + + + + insert into ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + $column.columnName, +#end +#end + + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + #{$column.javaField}, +#end +#end + + + + + update ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName) + $column.columnName = #{$column.javaField}, +#end +#end + + where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} in + + #{${pkColumn.javaField}} + + +#if($table.sub) + + + delete from ${subTableName} where ${subTableFkName} in + + #{${subTableFkclassName}} + + + + + delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}} + + + + insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values + + (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end) + + +#end + \ No newline at end of file diff --git a/examapi/ruoyi-quartz/pom.xml b/examapi/ruoyi-quartz/pom.xml new file mode 100644 index 0000000..b1c7b3e --- /dev/null +++ b/examapi/ruoyi-quartz/pom.xml @@ -0,0 +1,40 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-quartz + + + quartz定时任务 + + + + + + + org.quartz-scheduler + quartz + + + com.mchange + c3p0 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java new file mode 100644 index 0000000..bd315d2 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java @@ -0,0 +1,57 @@ +//package com.ruoyi.quartz.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.scheduling.quartz.SchedulerFactoryBean; +//import javax.sql.DataSource; +//import java.util.Properties; +// +///** +// * 定时任务é…ç½®ï¼ˆå•æœºéƒ¨ç½²å»ºè®®åˆ é™¤æ­¤ç±»å’Œqrtzæ•°æ®åº“表,默认走内存会最高效) +// * +// * @author ruoyi +// */ +//@Configuration +//public class ScheduleConfig +//{ +// @Bean +// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) +// { +// SchedulerFactoryBean factory = new SchedulerFactoryBean(); +// factory.setDataSource(dataSource); +// +// // quartz傿•° +// Properties prop = new Properties(); +// prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); +// prop.put("org.quartz.scheduler.instanceId", "AUTO"); +// // 线程池é…ç½® +// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); +// prop.put("org.quartz.threadPool.threadCount", "20"); +// prop.put("org.quartz.threadPool.threadPriority", "5"); +// // JobStoreé…ç½® +// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); +// // 集群é…ç½® +// prop.put("org.quartz.jobStore.isClustered", "true"); +// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); +// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); +// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); +// +// // sqlserver å¯ç”¨ +// // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); +// prop.put("org.quartz.jobStore.misfireThreshold", "12000"); +// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); +// factory.setQuartzProperties(prop); +// +// factory.setSchedulerName("RuoyiScheduler"); +// // å»¶æ—¶å¯åЍ +// factory.setStartupDelay(1); +// factory.setApplicationContextSchedulerContextKey("applicationContextKey"); +// // å¯é€‰ï¼ŒQuartzScheduler +// // å¯åŠ¨æ—¶æ›´æ–°å·±å­˜åœ¨çš„Job,这样就ä¸ç”¨æ¯æ¬¡ä¿®æ”¹targetObjectåŽåˆ é™¤qrtz_job_details表对应记录了 +// factory.setOverwriteExistingJobs(true); +// // 设置自动å¯åŠ¨ï¼Œé»˜è®¤ä¸ºtrue +// factory.setAutoStartup(true); +// +// return factory; +// } +//} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java new file mode 100644 index 0000000..f8189ba --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java @@ -0,0 +1,185 @@ +package com.ruoyi.quartz.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; +import com.ruoyi.quartz.util.ScheduleUtils; + +/** + * è°ƒåº¦ä»»åŠ¡ä¿¡æ¯æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/job") +public class SysJobController extends BaseController +{ + @Autowired + private ISysJobService jobService; + + /** + * 查询定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJob sysJob) + { + startPage(); + List list = jobService.selectJobList(sysJob); + return getDataTable(list); + } + + /** + * 导出定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "定时任务", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJob sysJob) + { + List list = jobService.selectJobList(sysJob); + ExcelUtil util = new ExcelUtil(SysJob.class); + util.exportExcel(response, list, "定时任务"); + } + + /** + * 获å–å®šæ—¶ä»»åŠ¡è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobId}") + public AjaxResult getInfo(@PathVariable("jobId") Long jobId) + { + return success(jobService.selectJobById(jobId)); + } + + /** + * 新增定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:add')") + @Log(title = "定时任务", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("新增任务'" + job.getJobName() + "'失败,Cron表达å¼ä¸æ­£ç¡®"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在è¿è§„"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串ä¸åœ¨ç™½åå•内"); + } + job.setCreateBy(getUsername()); + return toAjax(jobService.insertJob(job)); + } + + /** + * 修改定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:edit')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("修改任务'" + job.getJobName() + "'失败,Cron表达å¼ä¸æ­£ç¡®"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串ä¸å…许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在è¿è§„"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串ä¸åœ¨ç™½åå•内"); + } + job.setUpdateBy(getUsername()); + return toAjax(jobService.updateJob(job)); + } + + /** + * 定时任务状æ€ä¿®æ”¹ + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException + { + SysJob newJob = jobService.selectJobById(job.getJobId()); + newJob.setStatus(job.getStatus()); + return toAjax(jobService.changeStatus(newJob)); + } + + /** + * å®šæ—¶ä»»åŠ¡ç«‹å³æ‰§è¡Œä¸€æ¬¡ + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/run") + public AjaxResult run(@RequestBody SysJob job) throws SchedulerException + { + boolean result = jobService.run(job); + return result ? success() : error("任务ä¸å­˜åœ¨æˆ–已过期ï¼"); + } + + /** + * 删除定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobIds}") + public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException + { + jobService.deleteJobByIds(jobIds); + return success(); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java new file mode 100644 index 0000000..67f44ab --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java @@ -0,0 +1,92 @@ +package com.ruoyi.quartz.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 调度日志æ“ä½œå¤„ç† + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/jobLog") +public class SysJobLogController extends BaseController +{ + @Autowired + private ISysJobLogService jobLogService; + + /** + * 查询定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJobLog sysJobLog) + { + startPage(); + List list = jobLogService.selectJobLogList(sysJobLog); + return getDataTable(list); + } + + /** + * 导出定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJobLog sysJobLog) + { + List list = jobLogService.selectJobLogList(sysJobLog); + ExcelUtil util = new ExcelUtil(SysJobLog.class); + util.exportExcel(response, list, "调度日志"); + } + + /** + * æ ¹æ®è°ƒåº¦ç¼–å·èŽ·å–è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobLogId}") + public AjaxResult getInfo(@PathVariable Long jobLogId) + { + return success(jobLogService.selectJobLogById(jobLogId)); + } + + + /** + * 删除定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobLogIds}") + public AjaxResult remove(@PathVariable Long[] jobLogIds) + { + return toAjax(jobLogService.deleteJobLogByIds(jobLogIds)); + } + + /** + * 清空定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "调度日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + jobLogService.cleanJobLog(); + return success(); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java new file mode 100644 index 0000000..4776e5f --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java @@ -0,0 +1,171 @@ +package com.ruoyi.quartz.domain; + +import java.util.Date; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.quartz.util.CronUtils; + +/** + * 定时任务调度表 sys_job + * + * @author ruoyi + */ +public class SysJob extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 任务ID */ + @Excel(name = "任务åºå·", cellType = ColumnType.NUMERIC) + private Long jobId; + + /** 任务åç§° */ + @Excel(name = "任务åç§°") + private String jobName; + + /** 任务组å */ + @Excel(name = "任务组å") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** cronæ‰§è¡Œè¡¨è¾¾å¼ */ + @Excel(name = "æ‰§è¡Œè¡¨è¾¾å¼ ") + private String cronExpression; + + /** cron计划策略 */ + @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=ç«‹å³è§¦å‘执行,2=触å‘一次执行,3=ä¸è§¦å‘ç«‹å³æ‰§è¡Œ") + private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; + + /** 是å¦å¹¶å‘执行(0å…许 1ç¦æ­¢ï¼‰ */ + @Excel(name = "并呿‰§è¡Œ", readConverterExp = "0=å…许,1=ç¦æ­¢") + private String concurrent; + + /** 任务状æ€ï¼ˆ0正常 1æš‚åœï¼‰ */ + @Excel(name = "任务状æ€", readConverterExp = "0=正常,1=æš‚åœ") + private String status; + + public Long getJobId() + { + return jobId; + } + + public void setJobId(Long jobId) + { + this.jobId = jobId; + } + + @NotBlank(message = "任务åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 64, message = "任务åç§°ä¸èƒ½è¶…过64个字符") + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + @NotBlank(message = "调用目标字符串ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 500, message = "调用目标字符串长度ä¸èƒ½è¶…过500个字符") + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + @NotBlank(message = "Cron执行表达å¼ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 255, message = "Cron执行表达å¼ä¸èƒ½è¶…过255个字符") + public String getCronExpression() + { + return cronExpression; + } + + public void setCronExpression(String cronExpression) + { + this.cronExpression = cronExpression; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getNextValidTime() + { + if (StringUtils.isNotEmpty(cronExpression)) + { + return CronUtils.getNextExecution(cronExpression); + } + return null; + } + + public String getMisfirePolicy() + { + return misfirePolicy; + } + + public void setMisfirePolicy(String misfirePolicy) + { + this.misfirePolicy = misfirePolicy; + } + + public String getConcurrent() + { + return concurrent; + } + + public void setConcurrent(String concurrent) + { + this.concurrent = concurrent; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobId", getJobId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("cronExpression", getCronExpression()) + .append("nextValidTime", getNextValidTime()) + .append("misfirePolicy", getMisfirePolicy()) + .append("concurrent", getConcurrent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java new file mode 100644 index 0000000..63c4cd6 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java @@ -0,0 +1,155 @@ +package com.ruoyi.quartz.domain; + +import java.util.Date; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 定时任务调度日志表 sys_job_log + * + * @author ruoyi + */ +public class SysJobLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "日志åºå·") + private Long jobLogId; + + /** 任务åç§° */ + @Excel(name = "任务åç§°") + private String jobName; + + /** 任务组å */ + @Excel(name = "任务组å") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** æ—¥å¿—ä¿¡æ¯ */ + @Excel(name = "日志信æ¯") + private String jobMessage; + + /** 执行状æ€ï¼ˆ0正常 1失败) */ + @Excel(name = "执行状æ€", readConverterExp = "0=正常,1=失败") + private String status; + + /** å¼‚å¸¸ä¿¡æ¯ */ + @Excel(name = "异常信æ¯") + private String exceptionInfo; + + /** 开始时间 */ + private Date startTime; + + /** åœæ­¢æ—¶é—´ */ + private Date stopTime; + + public Long getJobLogId() + { + return jobLogId; + } + + public void setJobLogId(Long jobLogId) + { + this.jobLogId = jobLogId; + } + + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + public String getJobMessage() + { + return jobMessage; + } + + public void setJobMessage(String jobMessage) + { + this.jobMessage = jobMessage; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getExceptionInfo() + { + return exceptionInfo; + } + + public void setExceptionInfo(String exceptionInfo) + { + this.exceptionInfo = exceptionInfo; + } + + public Date getStartTime() + { + return startTime; + } + + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStopTime() + { + return stopTime; + } + + public void setStopTime(Date stopTime) + { + this.stopTime = stopTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobLogId", getJobLogId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("jobMessage", getJobMessage()) + .append("status", getStatus()) + .append("exceptionInfo", getExceptionInfo()) + .append("startTime", getStartTime()) + .append("stopTime", getStopTime()) + .toString(); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java new file mode 100644 index 0000000..ed01ef7 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java @@ -0,0 +1,64 @@ +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * è°ƒåº¦ä»»åŠ¡æ—¥å¿—ä¿¡æ¯ æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysJobLogMapper +{ + /** + * 获å–quartz调度器日志的计划任务 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—é›†åˆ + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 查询所有调度任务日志 + * + * @return 调度任务日志列表 + */ + public List selectJobLogAll(); + + /** + * 通过调度任务日志IDæŸ¥è¯¢è°ƒåº¦ä¿¡æ¯ + * + * @param jobLogId 调度任务日志ID + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—å¯¹è±¡ä¿¡æ¯ + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * @return 结果 + */ + public int insertJobLog(SysJobLog jobLog); + + /** + * 批é‡åˆ é™¤è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * + * @param logIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java new file mode 100644 index 0000000..f481ea1 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java @@ -0,0 +1,67 @@ +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJob; + +/** + * è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysJobMapper +{ + /** + * æŸ¥è¯¢è°ƒåº¦ä»»åŠ¡æ—¥å¿—é›†åˆ + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return æ“ä½œæ—¥å¿—é›†åˆ + */ + public List selectJobList(SysJob job); + + /** + * 查询所有调度任务 + * + * @return 调度任务列表 + */ + public List selectJobAll(); + + /** + * 通过调度IDæŸ¥è¯¢è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * + * @param jobId 调度ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + public SysJob selectJobById(Long jobId); + + /** + * 通过调度IDåˆ é™¤è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * + * @param jobId 调度ID + * @return 结果 + */ + public int deleteJobById(Long jobId); + + /** + * 批é‡åˆ é™¤è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteJobByIds(Long[] ids); + + /** + * ä¿®æ”¹è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * + * @param job è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * @return 结果 + */ + public int updateJob(SysJob job); + + /** + * æ–°å¢žè°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * + * @param job è°ƒåº¦ä»»åŠ¡ä¿¡æ¯ + * @return 结果 + */ + public int insertJob(SysJob job); +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java new file mode 100644 index 0000000..5291a63 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java @@ -0,0 +1,56 @@ +package com.ruoyi.quartz.service; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * 定时任务调度日志信æ¯ä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +public interface ISysJobLogService +{ + /** + * 获å–quartz调度器日志的计划任务 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—é›†åˆ + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 通过调度任务日志IDæŸ¥è¯¢è°ƒåº¦ä¿¡æ¯ + * + * @param jobLogId 调度任务日志ID + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—å¯¹è±¡ä¿¡æ¯ + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + */ + public void addJobLog(SysJobLog jobLog); + + /** + * 批é‡åˆ é™¤è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * + * @param logIds 需è¦åˆ é™¤çš„æ—¥å¿—ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java new file mode 100644 index 0000000..afdb707 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java @@ -0,0 +1,102 @@ +package com.ruoyi.quartz.service; + +import java.util.List; +import org.quartz.SchedulerException; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务调度信æ¯ä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +public interface ISysJobService +{ + /** + * 获å–quartz调度器的计划任务 + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return è°ƒåº¦ä»»åŠ¡é›†åˆ + */ + public List selectJobList(SysJob job); + + /** + * 通过调度任务IDæŸ¥è¯¢è°ƒåº¦ä¿¡æ¯ + * + * @param jobId 调度任务ID + * @return è°ƒåº¦ä»»åŠ¡å¯¹è±¡ä¿¡æ¯ + */ + public SysJob selectJobById(Long jobId); + + /** + * æš‚åœä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int pauseJob(SysJob job) throws SchedulerException; + + /** + * æ¢å¤ä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int resumeJob(SysJob job) throws SchedulerException; + + /** + * 删除任务åŽï¼Œæ‰€å¯¹åº”çš„trigger也将被删除 + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int deleteJob(SysJob job) throws SchedulerException; + + /** + * 批é‡åˆ é™¤è°ƒåº¦ä¿¡æ¯ + * + * @param jobIds 需è¦åˆ é™¤çš„任务ID + * @return 结果 + */ + public void deleteJobByIds(Long[] jobIds) throws SchedulerException; + + /** + * 任务调度状æ€ä¿®æ”¹ + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int changeStatus(SysJob job) throws SchedulerException; + + /** + * ç«‹å³è¿è¡Œä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public boolean run(SysJob job) throws SchedulerException; + + /** + * 新增任务 + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int insertJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 更新任务 + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return 结果 + */ + public int updateJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 校验cronè¡¨è¾¾å¼æ˜¯å¦æœ‰æ•ˆ + * + * @param cronExpression è¡¨è¾¾å¼ + * @return 结果 + */ + public boolean checkCronExpressionIsValid(String cronExpression); +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java new file mode 100644 index 0000000..f68a548 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java @@ -0,0 +1,87 @@ +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.mapper.SysJobLogMapper; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * å®šæ—¶ä»»åŠ¡è°ƒåº¦æ—¥å¿—ä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +@Service +public class SysJobLogServiceImpl implements ISysJobLogService +{ + @Autowired + private SysJobLogMapper jobLogMapper; + + /** + * 获å–quartz调度器日志的计划任务 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—é›†åˆ + */ + @Override + public List selectJobLogList(SysJobLog jobLog) + { + return jobLogMapper.selectJobLogList(jobLog); + } + + /** + * 通过调度任务日志IDæŸ¥è¯¢è°ƒåº¦ä¿¡æ¯ + * + * @param jobLogId 调度任务日志ID + * @return è°ƒåº¦ä»»åŠ¡æ—¥å¿—å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysJobLog selectJobLogById(Long jobLogId) + { + return jobLogMapper.selectJobLogById(jobLogId); + } + + /** + * 新增任务日志 + * + * @param jobLog è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + */ + @Override + public void addJobLog(SysJobLog jobLog) + { + jobLogMapper.insertJobLog(jobLog); + } + + /** + * 批é‡åˆ é™¤è°ƒåº¦æ—¥å¿—ä¿¡æ¯ + * + * @param logIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + @Override + public int deleteJobLogByIds(Long[] logIds) + { + return jobLogMapper.deleteJobLogByIds(logIds); + } + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + */ + @Override + public int deleteJobLogById(Long jobId) + { + return jobLogMapper.deleteJobLogById(jobId); + } + + /** + * 清空任务日志 + */ + @Override + public void cleanJobLog() + { + jobLogMapper.cleanJobLog(); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java new file mode 100644 index 0000000..71540b3 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java @@ -0,0 +1,261 @@ +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import javax.annotation.PostConstruct; +import org.quartz.JobDataMap; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.mapper.SysJobMapper; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; +import com.ruoyi.quartz.util.ScheduleUtils; + +/** + * å®šæ—¶ä»»åŠ¡è°ƒåº¦ä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +@Service +public class SysJobServiceImpl implements ISysJobService +{ + @Autowired + private Scheduler scheduler; + + @Autowired + private SysJobMapper jobMapper; + + /** + * 项目å¯åŠ¨æ—¶ï¼Œåˆå§‹åŒ–定时器 ä¸»è¦æ˜¯é˜²æ­¢æ‰‹åŠ¨ä¿®æ”¹æ•°æ®åº“å¯¼è‡´æœªåŒæ­¥åˆ°å®šæ—¶ä»»åС处ç†ï¼ˆæ³¨ï¼šä¸èƒ½æ‰‹åŠ¨ä¿®æ”¹æ•°æ®åº“ID和任务组å,å¦åˆ™ä¼šå¯¼è‡´è„æ•°æ®ï¼‰ + */ + @PostConstruct + public void init() throws SchedulerException, TaskException + { + scheduler.clear(); + List jobList = jobMapper.selectJobAll(); + for (SysJob job : jobList) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + } + + /** + * 获å–quartz调度器的计划任务列表 + * + * @param job è°ƒåº¦ä¿¡æ¯ + * @return + */ + @Override + public List selectJobList(SysJob job) + { + return jobMapper.selectJobList(job); + } + + /** + * 通过调度任务IDæŸ¥è¯¢è°ƒåº¦ä¿¡æ¯ + * + * @param jobId 调度任务ID + * @return è°ƒåº¦ä»»åŠ¡å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysJob selectJobById(Long jobId) + { + return jobMapper.selectJobById(jobId); + } + + /** + * æš‚åœä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int pauseJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * æ¢å¤ä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int resumeJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 删除任务åŽï¼Œæ‰€å¯¹åº”çš„trigger也将被删除 + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + int rows = jobMapper.deleteJobById(jobId); + if (rows > 0) + { + scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 批é‡åˆ é™¤è°ƒåº¦ä¿¡æ¯ + * + * @param jobIds 需è¦åˆ é™¤çš„任务ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteJobByIds(Long[] jobIds) throws SchedulerException + { + for (Long jobId : jobIds) + { + SysJob job = jobMapper.selectJobById(jobId); + deleteJob(job); + } + } + + /** + * 任务调度状æ€ä¿®æ”¹ + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int changeStatus(SysJob job) throws SchedulerException + { + int rows = 0; + String status = job.getStatus(); + if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) + { + rows = resumeJob(job); + } + else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) + { + rows = pauseJob(job); + } + return rows; + } + + /** + * ç«‹å³è¿è¡Œä»»åŠ¡ + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean run(SysJob job) throws SchedulerException + { + boolean result = false; + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + SysJob properties = selectJobById(job.getJobId()); + // 傿•° + JobDataMap dataMap = new JobDataMap(); + dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + result = true; + scheduler.triggerJob(jobKey, dataMap); + } + return result; + } + + /** + * 新增任务 + * + * @param job è°ƒåº¦ä¿¡æ¯ è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertJob(SysJob job) throws SchedulerException, TaskException + { + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.insertJob(job); + if (rows > 0) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + return rows; + } + + /** + * æ›´æ–°ä»»åŠ¡çš„æ—¶é—´è¡¨è¾¾å¼ + * + * @param job è°ƒåº¦ä¿¡æ¯ + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateJob(SysJob job) throws SchedulerException, TaskException + { + SysJob properties = selectJobById(job.getJobId()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + updateSchedulerJob(job, properties.getJobGroup()); + } + return rows; + } + + /** + * 更新任务 + * + * @param job 任务对象 + * @param jobGroup 任务组å + */ + public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException + { + Long jobId = job.getJobId(); + // 判断是å¦å­˜åœ¨ + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + // 防止创建时存在数æ®é—®é¢˜ 先移除,然åŽåœ¨æ‰§è¡Œåˆ›å»ºæ“作 + scheduler.deleteJob(jobKey); + } + ScheduleUtils.createScheduleJob(scheduler, job); + } + + /** + * 校验cronè¡¨è¾¾å¼æ˜¯å¦æœ‰æ•ˆ + * + * @param cronExpression è¡¨è¾¾å¼ + * @return 结果 + */ + @Override + public boolean checkCronExpressionIsValid(String cronExpression) + { + return CronUtils.isValid(cronExpression); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java new file mode 100644 index 0000000..25d1ddd --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java @@ -0,0 +1,28 @@ +package com.ruoyi.quartz.task; + +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.StringUtils; + +/** + * 定时任务调度测试 + * + * @author ruoyi + */ +@Component("ryTask") +public class RyTask +{ + public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) + { + System.out.println(StringUtils.format("æ‰§è¡Œå¤šå‚æ–¹æ³•: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); + } + + public void ryParams(String params) + { + System.out.println("æ‰§è¡Œæœ‰å‚æ–¹æ³•:" + params); + } + + public void ryNoParams() + { + System.out.println("æ‰§è¡Œæ— å‚æ–¹æ³•"); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java new file mode 100644 index 0000000..fd652d6 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java @@ -0,0 +1,107 @@ +package com.ruoyi.quartz.util; + +import java.util.Date; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.utils.ExceptionUtil; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 抽象quartz调用 + * + * @author ruoyi + */ +public abstract class AbstractQuartzJob implements Job +{ + private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class); + + /** + * 线程本地å˜é‡ + */ + private static ThreadLocal threadLocal = new ThreadLocal<>(); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException + { + SysJob sysJob = new SysJob(); + BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); + try + { + before(context, sysJob); + if (sysJob != null) + { + doExecute(context, sysJob); + } + after(context, sysJob, null); + } + catch (Exception e) + { + log.error("任务执行异常 - :", e); + after(context, sysJob, e); + } + } + + /** + * æ‰§è¡Œå‰ + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + */ + protected void before(JobExecutionContext context, SysJob sysJob) + { + threadLocal.set(new Date()); + } + + /** + * æ‰§è¡ŒåŽ + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + */ + protected void after(JobExecutionContext context, SysJob sysJob, Exception e) + { + Date startTime = threadLocal.get(); + threadLocal.remove(); + + final SysJobLog sysJobLog = new SysJobLog(); + sysJobLog.setJobName(sysJob.getJobName()); + sysJobLog.setJobGroup(sysJob.getJobGroup()); + sysJobLog.setInvokeTarget(sysJob.getInvokeTarget()); + sysJobLog.setStartTime(startTime); + sysJobLog.setStopTime(new Date()); + long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime(); + sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒"); + if (e != null) + { + sysJobLog.setStatus(Constants.FAIL); + String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); + sysJobLog.setExceptionInfo(errorMsg); + } + else + { + sysJobLog.setStatus(Constants.SUCCESS); + } + + // 写入数æ®åº“当中 + SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog); + } + + /** + * 执行方法,由å­ç±»é‡è½½ + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + * @throws Exception 执行过程中的异常 + */ + protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception; +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java new file mode 100644 index 0000000..6826787 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java @@ -0,0 +1,63 @@ +package com.ruoyi.quartz.util; + +import java.text.ParseException; +import java.util.Date; +import org.quartz.CronExpression; + +/** + * cron表达å¼å·¥å…·ç±» + * + * @author ruoyi + * + */ +public class CronUtils +{ + /** + * 返回一个布尔值代表一个给定的Cron表达å¼çš„æœ‰æ•ˆæ€§ + * + * @param cronExpression Cronè¡¨è¾¾å¼ + * @return boolean è¡¨è¾¾å¼æ˜¯å¦æœ‰æ•ˆ + */ + public static boolean isValid(String cronExpression) + { + return CronExpression.isValidExpression(cronExpression); + } + + /** + * 返回一个字符串值,è¡¨ç¤ºè¯¥æ¶ˆæ¯æ— æ•ˆCron表达å¼ç»™å‡ºæœ‰æ•ˆæ€§ + * + * @param cronExpression Cronè¡¨è¾¾å¼ + * @return String 无效时返回表达å¼é”™è¯¯æè¿°,如果有效返回null + */ + public static String getInvalidMessage(String cronExpression) + { + try + { + new CronExpression(cronExpression); + return null; + } + catch (ParseException pe) + { + return pe.getMessage(); + } + } + + /** + * 返回下一个执行时间根æ®ç»™å®šçš„Cronè¡¨è¾¾å¼ + * + * @param cronExpression Cronè¡¨è¾¾å¼ + * @return Date 下次Cronè¡¨è¾¾å¼æ‰§è¡Œæ—¶é—´ + */ + public static Date getNextExecution(String cronExpression) + { + try + { + CronExpression cron = new CronExpression(cronExpression); + return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis())); + } + catch (ParseException e) + { + throw new IllegalArgumentException(e.getMessage()); + } + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java new file mode 100644 index 0000000..9a90d7b --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java @@ -0,0 +1,182 @@ +package com.ruoyi.quartz.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 任务执行工具 + * + * @author ruoyi + */ +public class JobInvokeUtil +{ + /** + * 执行方法 + * + * @param sysJob 系统任务 + */ + public static void invokeMethod(SysJob sysJob) throws Exception + { + String invokeTarget = sysJob.getInvokeTarget(); + String beanName = getBeanName(invokeTarget); + String methodName = getMethodName(invokeTarget); + List methodParams = getMethodParams(invokeTarget); + + if (!isValidClassName(beanName)) + { + Object bean = SpringUtils.getBean(beanName); + invokeMethod(bean, methodName, methodParams); + } + else + { + Object bean = Class.forName(beanName).getDeclaredConstructor().newInstance(); + invokeMethod(bean, methodName, methodParams); + } + } + + /** + * 调用任务方法 + * + * @param bean 目标对象 + * @param methodName 方法åç§° + * @param methodParams æ–¹æ³•å‚æ•° + */ + private static void invokeMethod(Object bean, String methodName, List methodParams) + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) + { + Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams)); + method.invoke(bean, getMethodParamsValue(methodParams)); + } + else + { + Method method = bean.getClass().getMethod(methodName); + method.invoke(bean); + } + } + + /** + * 校验是å¦ä¸ºä¸ºclass包å + * + * @param invokeTarget åç§° + * @return true是 falseå¦ + */ + public static boolean isValidClassName(String invokeTarget) + { + return StringUtils.countMatches(invokeTarget, ".") > 1; + } + + /** + * 获å–beanåç§° + * + * @param invokeTarget 目标字符串 + * @return beanåç§° + */ + public static String getBeanName(String invokeTarget) + { + String beanName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringBeforeLast(beanName, "."); + } + + /** + * 获å–bean方法 + * + * @param invokeTarget 目标字符串 + * @return method方法 + */ + public static String getMethodName(String invokeTarget) + { + String methodName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringAfterLast(methodName, "."); + } + + /** + * 获å–methodæ–¹æ³•å‚æ•°ç›¸å…³åˆ—表 + * + * @param invokeTarget 目标字符串 + * @return methodæ–¹æ³•ç›¸å…³å‚æ•°åˆ—表 + */ + public static List getMethodParams(String invokeTarget) + { + String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); + if (StringUtils.isEmpty(methodStr)) + { + return null; + } + String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); + List classs = new LinkedList<>(); + for (int i = 0; i < methodParams.length; i++) + { + String str = StringUtils.trimToEmpty(methodParams[i]); + // String字符串类型,以'或"开头 + if (StringUtils.startsWithAny(str, "'", "\"")) + { + classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class }); + } + // boolean布尔类型,等于true或者false + else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) + { + classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + } + // long长整形,以L结尾 + else if (StringUtils.endsWith(str, "L")) + { + classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class }); + } + // double浮点类型,以D结尾 + else if (StringUtils.endsWith(str, "D")) + { + classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class }); + } + // 其他类型归类为整形 + else + { + classs.add(new Object[] { Integer.valueOf(str), Integer.class }); + } + } + return classs; + } + + /** + * 获å–傿•°ç±»åž‹ + * + * @param methodParams 傿•°ç›¸å…³åˆ—表 + * @return 傿•°ç±»åž‹åˆ—表 + */ + public static Class[] getMethodParamsType(List methodParams) + { + Class[] classs = new Class[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Class) os[1]; + index++; + } + return classs; + } + + /** + * 获å–傿•°å€¼ + * + * @param methodParams 傿•°ç›¸å…³åˆ—表 + * @return 傿•°å€¼åˆ—表 + */ + public static Object[] getMethodParamsValue(List methodParams) + { + Object[] classs = new Object[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Object) os[0]; + index++; + } + return classs; + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java new file mode 100644 index 0000000..96a6dcf --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java @@ -0,0 +1,21 @@ +package com.ruoyi.quartz.util; + +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处ç†ï¼ˆç¦æ­¢å¹¶å‘执行) + * + * @author ruoyi + * + */ +@DisallowConcurrentExecution +public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java new file mode 100644 index 0000000..87a06bc --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java @@ -0,0 +1,19 @@ +package com.ruoyi.quartz.util; + +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处ç†ï¼ˆå…è®¸å¹¶å‘æ‰§è¡Œï¼‰ + * + * @author ruoyi + * + */ +public class QuartzJobExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java new file mode 100644 index 0000000..ab829e6 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java @@ -0,0 +1,141 @@ +package com.ruoyi.quartz.util; + +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.Job; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.exception.job.TaskException.Code; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务工具类 + * + * @author ruoyi + * + */ +public class ScheduleUtils +{ + /** + * 得到quartz任务类 + * + * @param sysJob 执行计划 + * @return 具体执行任务类 + */ + private static Class getQuartzJobClass(SysJob sysJob) + { + boolean isConcurrent = "0".equals(sysJob.getConcurrent()); + return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; + } + + /** + * 构建任务触å‘对象 + */ + public static TriggerKey getTriggerKey(Long jobId, String jobGroup) + { + return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 构建任务键对象 + */ + public static JobKey getJobKey(Long jobId, String jobGroup) + { + return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException + { + Class jobClass = getQuartzJobClass(job); + // 构建jobä¿¡æ¯ + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); + + // 表达å¼è°ƒåº¦æž„建器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); + cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); + + // 按新的cronExpressionè¡¨è¾¾å¼æž„建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) + .withSchedule(cronScheduleBuilder).build(); + + // æ”¾å…¥å‚æ•°ï¼Œè¿è¡Œæ—¶çš„æ–¹æ³•å¯ä»¥èŽ·å– + jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); + + // 判断是å¦å­˜åœ¨ + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) + { + // 防止创建时存在数æ®é—®é¢˜ 先移除,然åŽåœ¨æ‰§è¡Œåˆ›å»ºæ“作 + scheduler.deleteJob(getJobKey(jobId, jobGroup)); + } + + // 判断任务是å¦è¿‡æœŸ + if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) + { + // 执行调度任务 + scheduler.scheduleJob(jobDetail, trigger); + } + + // æš‚åœä»»åŠ¡ + if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + } + + /** + * 设置定时任务策略 + */ + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb) + throws TaskException + { + switch (job.getMisfirePolicy()) + { + case ScheduleConstants.MISFIRE_DEFAULT: + return cb; + case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: + return cb.withMisfireHandlingInstructionIgnoreMisfires(); + case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: + return cb.withMisfireHandlingInstructionFireAndProceed(); + case ScheduleConstants.MISFIRE_DO_NOTHING: + return cb.withMisfireHandlingInstructionDoNothing(); + default: + throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + } + } + + /** + * æ£€æŸ¥åŒ…åæ˜¯å¦ä¸ºç™½åå•é…ç½® + * + * @param invokeTarget 目标字符串 + * @return 结果 + */ + public static boolean whiteList(String invokeTarget) + { + String packageName = StringUtils.substringBefore(invokeTarget, "("); + int count = StringUtils.countMatches(packageName, "."); + if (count > 1) + { + return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); + } + Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); + String beanPackageName = obj.getClass().getPackage().getName(); + return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR) + && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR); + } +} diff --git a/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml new file mode 100644 index 0000000..f9cf50a --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time + from sys_job_log + + + + + + + + + + delete from sys_job_log where job_log_id = #{jobLogId} + + + + delete from sys_job_log where job_log_id in + + #{jobLogId} + + + + + delete from sys_job_log + + + + insert into sys_job_log( + job_log_id, + job_name, + job_group, + invoke_target, + job_message, + status, + exception_info, + create_time + )values( + #{jobLogId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{jobMessage}, + #{status}, + #{exceptionInfo}, + sysdate() + ) + + + \ No newline at end of file diff --git a/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml new file mode 100644 index 0000000..f9c8d78 --- /dev/null +++ b/examapi/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark + from sys_job + + + + + + + + + + delete from sys_job where job_id = #{jobId} + + + + delete from sys_job where job_id in + + #{jobId} + + + + + update sys_job + + job_name = #{jobName}, + job_group = #{jobGroup}, + invoke_target = #{invokeTarget}, + cron_expression = #{cronExpression}, + misfire_policy = #{misfirePolicy}, + concurrent = #{concurrent}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where job_id = #{jobId} + + + + insert into sys_job( + job_id, + job_name, + job_group, + invoke_target, + cron_expression, + misfire_policy, + concurrent, + status, + remark, + create_by, + create_time + )values( + #{jobId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{cronExpression}, + #{misfirePolicy}, + #{concurrent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/pom.xml b/examapi/ruoyi-system/pom.xml new file mode 100644 index 0000000..c5940f7 --- /dev/null +++ b/examapi/ruoyi-system/pom.xml @@ -0,0 +1,28 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-system + + + systemç³»ç»Ÿæ¨¡å— + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java new file mode 100644 index 0000000..2ee8212 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java @@ -0,0 +1,81 @@ +package com.ruoyi.system.domain; + +import com.ruoyi.common.utils.StringUtils; + +/** + * ç¼“å­˜ä¿¡æ¯ + * + * @author ruoyi + */ +public class SysCache +{ + /** 缓存åç§° */ + private String cacheName = ""; + + /** 缓存键å */ + private String cacheKey = ""; + + /** 缓存内容 */ + private String cacheValue = ""; + + /** 备注 */ + private String remark = ""; + + public SysCache() + { + + } + + public SysCache(String cacheName, String remark) + { + this.cacheName = cacheName; + this.remark = remark; + } + + public SysCache(String cacheName, String cacheKey, String cacheValue) + { + this.cacheName = StringUtils.replace(cacheName, ":", ""); + this.cacheKey = StringUtils.replace(cacheKey, cacheName, ""); + this.cacheValue = cacheValue; + } + + public String getCacheName() + { + return cacheName; + } + + public void setCacheName(String cacheName) + { + this.cacheName = cacheName; + } + + public String getCacheKey() + { + return cacheKey; + } + + public void setCacheKey(String cacheKey) + { + this.cacheKey = cacheKey; + } + + public String getCacheValue() + { + return cacheValue; + } + + public void setCacheValue(String cacheValue) + { + this.cacheValue = cacheValue; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java new file mode 100644 index 0000000..676a891 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java @@ -0,0 +1,111 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 傿•°é…置表 sys_config + * + * @author ruoyi + */ +public class SysConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 傿•°ä¸»é”® */ + @Excel(name = "傿•°ä¸»é”®", cellType = ColumnType.NUMERIC) + private Long configId; + + /** 傿•°åç§° */ + @Excel(name = "傿•°åç§°") + private String configName; + + /** 傿•°é”®å */ + @Excel(name = "傿•°é”®å") + private String configKey; + + /** 傿•°é”®å€¼ */ + @Excel(name = "傿•°é”®å€¼") + private String configValue; + + /** 系统内置(Y是 Nå¦ï¼‰ */ + @Excel(name = "系统内置", readConverterExp = "Y=是,N=å¦") + private String configType; + + public Long getConfigId() + { + return configId; + } + + public void setConfigId(Long configId) + { + this.configId = configId; + } + + @NotBlank(message = "傿•°åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "傿•°åç§°ä¸èƒ½è¶…过100个字符") + public String getConfigName() + { + return configName; + } + + public void setConfigName(String configName) + { + this.configName = configName; + } + + @NotBlank(message = "傿•°é”®å长度ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 100, message = "傿•°é”®å长度ä¸èƒ½è¶…过100个字符") + public String getConfigKey() + { + return configKey; + } + + public void setConfigKey(String configKey) + { + this.configKey = configKey; + } + + @NotBlank(message = "傿•°é”®å€¼ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 500, message = "傿•°é”®å€¼é•¿åº¦ä¸èƒ½è¶…过500个字符") + public String getConfigValue() + { + return configValue; + } + + public void setConfigValue(String configValue) + { + this.configValue = configValue; + } + + public String getConfigType() + { + return configType; + } + + public void setConfigType(String configType) + { + this.configType = configType; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("configId", getConfigId()) + .append("configName", getConfigName()) + .append("configKey", getConfigKey()) + .append("configValue", getConfigValue()) + .append("configType", getConfigType()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java new file mode 100644 index 0000000..02a7fb5 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java @@ -0,0 +1,144 @@ +package com.ruoyi.system.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 系统访问记录表 sys_logininfor + * + * @author ruoyi + */ +public class SysLogininfor extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "åºå·", cellType = ColumnType.NUMERIC) + private Long infoId; + + /** ç”¨æˆ·è´¦å· */ + @Excel(name = "用户账å·") + private String userName; + + /** ç™»å½•çŠ¶æ€ 0æˆåŠŸ 1失败 */ + @Excel(name = "登录状æ€", readConverterExp = "0=æˆåŠŸ,1=失败") + private String status; + + /** 登录IPåœ°å€ */ + @Excel(name = "登录地å€") + private String ipaddr; + + /** 登录地点 */ + @Excel(name = "登录地点") + private String loginLocation; + + /** æµè§ˆå™¨ç±»åž‹ */ + @Excel(name = "æµè§ˆå™¨") + private String browser; + + /** æ“作系统 */ + @Excel(name = "æ“作系统") + private String os; + + /** æç¤ºæ¶ˆæ¯ */ + @Excel(name = "æç¤ºæ¶ˆæ¯") + private String msg; + + /** 访问时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date loginTime; + + public Long getInfoId() + { + return infoId; + } + + public void setInfoId(Long infoId) + { + this.infoId = infoId; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public Date getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Date loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java new file mode 100644 index 0000000..b5c6187 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java @@ -0,0 +1,102 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.xss.Xss; + +/** + * 通知公告表 sys_notice + * + * @author ruoyi + */ +public class SysNotice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 公告ID */ + private Long noticeId; + + /** 公告标题 */ + private String noticeTitle; + + /** 公告类型(1通知 2公告) */ + private String noticeType; + + /** 公告内容 */ + private String noticeContent; + + /** 公告状æ€ï¼ˆ0正常 1关闭) */ + private String status; + + public Long getNoticeId() + { + return noticeId; + } + + public void setNoticeId(Long noticeId) + { + this.noticeId = noticeId; + } + + public void setNoticeTitle(String noticeTitle) + { + this.noticeTitle = noticeTitle; + } + + @Xss(message = "公告标题ä¸èƒ½åŒ…å«è„šæœ¬å­—ç¬¦") + @NotBlank(message = "公告标题ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 50, message = "公告标题ä¸èƒ½è¶…过50个字符") + public String getNoticeTitle() + { + return noticeTitle; + } + + public void setNoticeType(String noticeType) + { + this.noticeType = noticeType; + } + + public String getNoticeType() + { + return noticeType; + } + + public void setNoticeContent(String noticeContent) + { + this.noticeContent = noticeContent; + } + + public String getNoticeContent() + { + return noticeContent; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("noticeId", getNoticeId()) + .append("noticeTitle", getNoticeTitle()) + .append("noticeType", getNoticeType()) + .append("noticeContent", getNoticeContent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java new file mode 100644 index 0000000..7286573 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java @@ -0,0 +1,269 @@ +package com.ruoyi.system.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * æ“作日志记录表 oper_log + * + * @author ruoyi + */ +public class SysOperLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 日志主键 */ + @Excel(name = "æ“作åºå·", cellType = ColumnType.NUMERIC) + private Long operId; + + /** æ“ä½œæ¨¡å— */ + @Excel(name = "æ“作模å—") + private String title; + + /** 业务类型(0其它 1新增 2修改 3删除) */ + @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授æƒ,5=导出,6=导入,7=强退,8=生æˆä»£ç ,9=清空数æ®") + private Integer businessType; + + /** 业务类型数组 */ + private Integer[] businessTypes; + + /** 请求方法 */ + @Excel(name = "请求方法") + private String method; + + /** è¯·æ±‚æ–¹å¼ */ + @Excel(name = "请求方å¼") + private String requestMethod; + + /** æ“作类别(0其它 1åŽå°ç”¨æˆ· 2手机端用户) */ + @Excel(name = "æ“作类别", readConverterExp = "0=其它,1=åŽå°ç”¨æˆ·,2=手机端用户") + private Integer operatorType; + + /** æ“作人员 */ + @Excel(name = "æ“作人员") + private String operName; + + /** 部门åç§° */ + @Excel(name = "部门åç§°") + private String deptName; + + /** 请求url */ + @Excel(name = "请求地å€") + private String operUrl; + + /** æ“ä½œåœ°å€ */ + @Excel(name = "æ“作地å€") + private String operIp; + + /** æ“作地点 */ + @Excel(name = "æ“作地点") + private String operLocation; + + /** è¯·æ±‚å‚æ•° */ + @Excel(name = "è¯·æ±‚å‚æ•°") + private String operParam; + + /** è¿”å›žå‚æ•° */ + @Excel(name = "è¿”å›žå‚æ•°") + private String jsonResult; + + /** æ“作状æ€ï¼ˆ0正常 1异常) */ + @Excel(name = "状æ€", readConverterExp = "0=正常,1=异常") + private Integer status; + + /** é”™è¯¯æ¶ˆæ¯ */ + @Excel(name = "错误消æ¯") + private String errorMsg; + + /** æ“作时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "æ“作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date operTime; + + /** 消耗时间 */ + @Excel(name = "消耗时间", suffix = "毫秒") + private Long costTime; + + public Long getOperId() + { + return operId; + } + + public void setOperId(Long operId) + { + this.operId = operId; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public Integer getBusinessType() + { + return businessType; + } + + public void setBusinessType(Integer businessType) + { + this.businessType = businessType; + } + + public Integer[] getBusinessTypes() + { + return businessTypes; + } + + public void setBusinessTypes(Integer[] businessTypes) + { + this.businessTypes = businessTypes; + } + + public String getMethod() + { + return method; + } + + public void setMethod(String method) + { + this.method = method; + } + + public String getRequestMethod() + { + return requestMethod; + } + + public void setRequestMethod(String requestMethod) + { + this.requestMethod = requestMethod; + } + + public Integer getOperatorType() + { + return operatorType; + } + + public void setOperatorType(Integer operatorType) + { + this.operatorType = operatorType; + } + + public String getOperName() + { + return operName; + } + + public void setOperName(String operName) + { + this.operName = operName; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getOperUrl() + { + return operUrl; + } + + public void setOperUrl(String operUrl) + { + this.operUrl = operUrl; + } + + public String getOperIp() + { + return operIp; + } + + public void setOperIp(String operIp) + { + this.operIp = operIp; + } + + public String getOperLocation() + { + return operLocation; + } + + public void setOperLocation(String operLocation) + { + this.operLocation = operLocation; + } + + public String getOperParam() + { + return operParam; + } + + public void setOperParam(String operParam) + { + this.operParam = operParam; + } + + public String getJsonResult() + { + return jsonResult; + } + + public void setJsonResult(String jsonResult) + { + this.jsonResult = jsonResult; + } + + public Integer getStatus() + { + return status; + } + + public void setStatus(Integer status) + { + this.status = status; + } + + public String getErrorMsg() + { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) + { + this.errorMsg = errorMsg; + } + + public Date getOperTime() + { + return operTime; + } + + public void setOperTime(Date operTime) + { + this.operTime = operTime; + } + + public Long getCostTime() + { + return costTime; + } + + public void setCostTime(Long costTime) + { + this.costTime = costTime; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java new file mode 100644 index 0000000..a36ed79 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java @@ -0,0 +1,124 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * å²—ä½è¡¨ sys_post + * + * @author ruoyi + */ +public class SysPost extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** å²—ä½åºå· */ + @Excel(name = "å²—ä½åºå·", cellType = ColumnType.NUMERIC) + private Long postId; + + /** å²—ä½ç¼–ç  */ + @Excel(name = "å²—ä½ç¼–ç ") + private String postCode; + + /** å²—ä½åç§° */ + @Excel(name = "å²—ä½åç§°") + private String postName; + + /** å²—ä½æŽ’åº */ + @Excel(name = "岗使ޒåº") + private Integer postSort; + + /** 状æ€ï¼ˆ0正常 1åœç”¨ï¼‰ */ + @Excel(name = "状æ€", readConverterExp = "0=正常,1=åœç”¨") + private String status; + + /** 用户是å¦å­˜åœ¨æ­¤å²—使 ‡è¯† 默认ä¸å­˜åœ¨ */ + private boolean flag = false; + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @NotBlank(message = "å²—ä½ç¼–ç ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 64, message = "å²—ä½ç¼–ç é•¿åº¦ä¸èƒ½è¶…过64个字符") + public String getPostCode() + { + return postCode; + } + + public void setPostCode(String postCode) + { + this.postCode = postCode; + } + + @NotBlank(message = "å²—ä½åç§°ä¸èƒ½ä¸ºç©º") + @Size(min = 0, max = 50, message = "å²—ä½å称长度ä¸èƒ½è¶…过50个字符") + public String getPostName() + { + return postName; + } + + public void setPostName(String postName) + { + this.postName = postName; + } + + @NotNull(message = "显示顺åºä¸èƒ½ä¸ºç©º") + public Integer getPostSort() + { + return postSort; + } + + public void setPostSort(Integer postSort) + { + this.postSort = postSort; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("postId", getPostId()) + .append("postCode", getPostCode()) + .append("postName", getPostName()) + .append("postSort", getPostSort()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java new file mode 100644 index 0000000..8ed8e47 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * è§’è‰²å’Œéƒ¨é—¨å…³è” sys_role_dept + * + * @author ruoyi + */ +public class SysRoleDept +{ + /** 角色ID */ + private Long roleId; + + /** 部门ID */ + private Long deptId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("deptId", getDeptId()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java new file mode 100644 index 0000000..59d2869 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和èœå•å…³è” sys_role_menu + * + * @author ruoyi + */ +public class SysRoleMenu +{ + /** 角色ID */ + private Long roleId; + + /** èœå•ID */ + private Long menuId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("menuId", getMenuId()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java new file mode 100644 index 0000000..e1495aa --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java @@ -0,0 +1,113 @@ +package com.ruoyi.system.domain; + +/** + * 当å‰åœ¨çº¿ä¼šè¯ + * + * @author ruoyi + */ +public class SysUserOnline +{ + /** 会è¯ç¼–å· */ + private String tokenId; + + /** 部门åç§° */ + private String deptName; + + /** 用户åç§° */ + private String userName; + + /** 登录IPåœ°å€ */ + private String ipaddr; + + /** ç™»å½•åœ°å€ */ + private String loginLocation; + + /** æµè§ˆå™¨ç±»åž‹ */ + private String browser; + + /** æ“作系统 */ + private String os; + + /** 登录时间 */ + private Long loginTime; + + public String getTokenId() + { + return tokenId; + } + + public void setTokenId(String tokenId) + { + this.tokenId = tokenId; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java new file mode 100644 index 0000000..07ceb85 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和岗ä½å…³è” sys_user_post + * + * @author ruoyi + */ +public class SysUserPost +{ + /** 用户ID */ + private Long userId; + + /** å²—ä½ID */ + private Long postId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("postId", getPostId()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java new file mode 100644 index 0000000..ce2af2b --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * ç”¨æˆ·å’Œè§’è‰²å…³è” sys_user_role + * + * @author ruoyi + */ +public class SysUserRole +{ + /** 用户ID */ + private Long userId; + + /** 角色ID */ + private Long roleId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("roleId", getRoleId()) + .toString(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java new file mode 100644 index 0000000..6826326 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java @@ -0,0 +1,106 @@ +package com.ruoyi.system.domain.vo; + +import com.ruoyi.common.utils.StringUtils; + +/** + * è·¯ç”±æ˜¾ç¤ºä¿¡æ¯ + * + * @author ruoyi + */ +public class MetaVo +{ + /** + * 设置该路由在侧边æ å’Œé¢åŒ…屑中展示的åå­— + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则ä¸ä¼šè¢« 缓存 + */ + private boolean noCache; + + /** + * 内链地å€ï¼ˆhttp(s)://开头) + */ + private String link; + + public MetaVo() + { + } + + public MetaVo(String title, String icon) + { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) + { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtils.ishttp(link)) + { + this.link = link; + } + } + + public boolean isNoCache() + { + return noCache; + } + + public void setNoCache(boolean noCache) + { + this.noCache = noCache; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public String getLink() + { + return link; + } + + public void setLink(String link) + { + this.link = link; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java new file mode 100644 index 0000000..2d4a2b8 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java @@ -0,0 +1,148 @@ +package com.ruoyi.system.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; + +/** + * 路由é…ç½®ä¿¡æ¯ + * + * @author ruoyi + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouterVo +{ + /** + * 路由åå­— + */ + private String name; + + /** + * è·¯ç”±åœ°å€ + */ + private String path; + + /** + * 是å¦éšè—路由,当设置 true 的时候该路由ä¸ä¼šå†ä¾§è¾¹æ å‡ºçް + */ + private boolean hidden; + + /** + * é‡å®šå‘地å€ï¼Œå½“设置 noRedirect 的时候该路由在é¢åŒ…屑导航中ä¸å¯è¢«ç‚¹å‡» + */ + private String redirect; + + /** + * ç»„ä»¶åœ°å€ + */ + private String component; + + /** + * è·¯ç”±å‚æ•°ï¼šå¦‚ {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下é¢çš„ children 声明的路由大于1ä¸ªæ—¶ï¼Œè‡ªåŠ¨ä¼šå˜æˆåµŒå¥—的模å¼--å¦‚ç»„ä»¶é¡µé¢ + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * å­è·¯ç”± + */ + private List children; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public boolean getHidden() + { + return hidden; + } + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public String getRedirect() + { + return redirect; + } + + public void setRedirect(String redirect) + { + this.redirect = redirect; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public Boolean getAlwaysShow() + { + return alwaysShow; + } + + public void setAlwaysShow(Boolean alwaysShow) + { + this.alwaysShow = alwaysShow; + } + + public MetaVo getMeta() + { + return meta; + } + + public void setMeta(MetaVo meta) + { + this.meta = meta; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java new file mode 100644 index 0000000..999995d --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java @@ -0,0 +1,76 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysConfig; + +/** + * 傿•°é…ç½® æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysConfigMapper +{ + /** + * æŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 傿•°é…ç½®ä¿¡æ¯ + */ + public SysConfig selectConfig(SysConfig config); + + /** + * 通过ID查询é…ç½® + * + * @param configId 傿•°ID + * @return 傿•°é…ç½®ä¿¡æ¯ + */ + public SysConfig selectConfigById(Long configId); + + /** + * æŸ¥è¯¢å‚æ•°é…置列表 + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 傿•°é…ç½®é›†åˆ + */ + public List selectConfigList(SysConfig config); + + /** + * æ ¹æ®é”®åæŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param configKey 傿•°é”®å + * @return 傿•°é…ç½®ä¿¡æ¯ + */ + public SysConfig checkConfigKeyUnique(String configKey); + + /** + * æ–°å¢žå‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * ä¿®æ”¹å‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * åˆ é™¤å‚æ•°é…ç½® + * + * @param configId 傿•°ID + * @return 结果 + */ + public int deleteConfigById(Long configId); + + /** + * 批é‡åˆ é™¤å‚æ•°ä¿¡æ¯ + * + * @param configIds 需è¦åˆ é™¤çš„傿•°ID + * @return 结果 + */ + public int deleteConfigByIds(Long[] configIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java new file mode 100644 index 0000000..f3b5847 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java @@ -0,0 +1,118 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * éƒ¨é—¨ç®¡ç† æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysDeptMapper +{ + /** + * æŸ¥è¯¢éƒ¨é—¨ç®¡ç†æ•°æ® + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 部门信æ¯é›†åˆ + */ + public List selectDeptList(SysDept dept); + + /** + * æ ¹æ®è§’色IDæŸ¥è¯¢éƒ¨é—¨æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是å¦å…³è”显示 + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + + /** + * æ ¹æ®éƒ¨é—¨IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param deptId 部门ID + * @return éƒ¨é—¨ä¿¡æ¯ + */ + public SysDept selectDeptById(Long deptId); + + /** + * æ ¹æ®ID查询所有å­éƒ¨é—¨ + * + * @param deptId 部门ID + * @return 部门列表 + */ + public List selectChildrenDeptById(Long deptId); + + /** + * æ ¹æ®ID查询所有å­éƒ¨é—¨ï¼ˆæ­£å¸¸çжæ€ï¼‰ + * + * @param deptId 部门ID + * @return å­éƒ¨é—¨æ•° + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是å¦å­˜åœ¨å­èŠ‚ç‚¹ + * + * @param deptId 部门ID + * @return 结果 + */ + public int hasChildByDeptId(Long deptId); + + /** + * 查询部门是å¦å­˜åœ¨ç”¨æˆ· + * + * @param deptId 部门ID + * @return 结果 + */ + public int checkDeptExistUser(Long deptId); + + /** + * 校验部门å称是å¦å”¯ä¸€ + * + * @param deptName 部门åç§° + * @param parentId 父部门ID + * @return 结果 + */ + public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId); + + /** + * æ–°å¢žéƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * ä¿®æ”¹éƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * ä¿®æ”¹æ‰€åœ¨éƒ¨é—¨æ­£å¸¸çŠ¶æ€ + * + * @param deptIds 部门ID组 + */ + public void updateDeptStatusNormal(Long[] deptIds); + + /** + * 修改å­å…ƒç´ å…³ç³» + * + * @param depts å­å…ƒç´  + * @return 结果 + */ + public int updateDeptChildren(@Param("depts") List depts); + + /** + * 删除部门管ç†ä¿¡æ¯ + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..92f799e --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java @@ -0,0 +1,95 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysDictData; + +/** + * 字典表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysDictDataMapper +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + public List selectDictDataList(SysDictData dictData); + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictType 字典类型 + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + public List selectDictDataByType(String dictType); + + /** + * æ ¹æ®å­—典类型和字典键值查询字典数æ®ä¿¡æ¯ + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue); + + /** + * æ ¹æ®å­—典数æ®IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictCode 字典数æ®ID + * @return å­—å…¸æ•°æ® + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * æŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictType 字典类型 + * @return å­—å…¸æ•°æ® + */ + public int countDictDataByType(String dictType); + + /** + * 通过字典ID删除字典数æ®ä¿¡æ¯ + * + * @param dictCode 字典数æ®ID + * @return 结果 + */ + public int deleteDictDataById(Long dictCode); + + /** + * 批é‡åˆ é™¤å­—典数æ®ä¿¡æ¯ + * + * @param dictCodes 需è¦åˆ é™¤çš„字典数æ®ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增字典数æ®ä¿¡æ¯ + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改字典数æ®ä¿¡æ¯ + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + public int updateDictData(SysDictData dictData); + + /** + * åŒæ­¥ä¿®æ”¹å­—典类型 + * + * @param oldDictType 旧字典类型 + * @param newDictType 新旧字典类型 + * @return 结果 + */ + public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java new file mode 100644 index 0000000..132a72e --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java @@ -0,0 +1,83 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + * 字典表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysDictTypeMapper +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—典类型 + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 字典类型集åˆä¿¡æ¯ + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * æ ¹æ®æ‰€æœ‰å­—典类型 + * + * @return 字典类型集åˆä¿¡æ¯ + */ + public List selectDictTypeAll(); + + /** + * æ ¹æ®å­—典类型IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢ä¿¡æ¯ + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 通过字典IDåˆ é™¤å­—å…¸ä¿¡æ¯ + * + * @param dictId å­—å…¸ID + * @return 结果 + */ + public int deleteDictTypeById(Long dictId); + + /** + * 批é‡åˆ é™¤å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictIds 需è¦åˆ é™¤çš„å­—å…¸ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * æ–°å¢žå­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * ä¿®æ”¹å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是å¦å”¯ä¸€ + * + * @param dictType 字典类型 + * @return 结果 + */ + public SysDictType checkDictTypeUnique(String dictType); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java new file mode 100644 index 0000000..480dd9f --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java @@ -0,0 +1,42 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysLogininfor; + +/** + * ç³»ç»Ÿè®¿é—®æ—¥å¿—æƒ…å†µä¿¡æ¯ æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysLogininforMapper +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * æŸ¥è¯¢ç³»ç»Ÿç™»å½•æ—¥å¿—é›†åˆ + * + * @param logininfor 访问日志对象 + * @return ç™»å½•è®°å½•é›†åˆ + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿç™»å½•日志 + * + * @param infoIds 需è¦åˆ é™¤çš„登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + * + * @return 结果 + */ + public int cleanLogininfor(); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java new file mode 100644 index 0000000..f3e2eb9 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java @@ -0,0 +1,125 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * èœå•表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysMenuMapper +{ + /** + * 查询系统èœå•列表 + * + * @param menu èœå•ä¿¡æ¯ + * @return èœå•列表 + */ + public List selectMenuList(SysMenu menu); + + /** + * æ ¹æ®ç”¨æˆ·æ‰€æœ‰æƒé™ + * + * @return æƒé™åˆ—表 + */ + public List selectMenuPerms(); + + /** + * æ ¹æ®ç”¨æˆ·æŸ¥è¯¢ç³»ç»Ÿèœå•列表 + * + * @param menu èœå•ä¿¡æ¯ + * @return èœå•列表 + */ + public List selectMenuListByUserId(SysMenu menu); + + /** + * æ ¹æ®è§’色ID查询æƒé™ + * + * @param roleId 角色ID + * @return æƒé™åˆ—表 + */ + public List selectMenuPermsByRoleId(Long roleId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询æƒé™ + * + * @param userId 用户ID + * @return æƒé™åˆ—表 + */ + public List selectMenuPermsByUserId(Long userId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询èœå• + * + * @return èœå•列表 + */ + public List selectMenuTreeAll(); + + /** + * æ ¹æ®ç”¨æˆ·ID查询èœå• + * + * @param userId 用户ID + * @return èœå•列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * æ ¹æ®è§’色ID查询èœå•æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @param menuCheckStrictly èœå•树选择项是å¦å…³è”显示 + * @return 选中èœå•列表 + */ + public List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * æ ¹æ®èœå•IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return èœå•ä¿¡æ¯ + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是å¦å­˜åœ¨èœå•å­èŠ‚ç‚¹ + * + * @param menuId èœå•ID + * @return 结果 + */ + public int hasChildByMenuId(Long menuId); + + /** + * 新增èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除èœå•管ç†ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验èœå•å称是å¦å”¯ä¸€ + * + * @param menuName èœå•åç§° + * @param parentId 父èœå•ID + * @return 结果 + */ + public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..cc267ac --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysNotice; + +/** + * 通知公告表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysNoticeMapper +{ + /** + * æŸ¥è¯¢å…¬å‘Šä¿¡æ¯ + * + * @param noticeId 公告ID + * @return å…¬å‘Šä¿¡æ¯ + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return å…¬å‘Šé›†åˆ + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 批é‡åˆ é™¤å…¬å‘Š + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批é‡åˆ é™¤å…¬å‘Šä¿¡æ¯ + * + * @param noticeIds 需è¦åˆ é™¤çš„公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java new file mode 100644 index 0000000..3bf69bb --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysOperLog; + +/** + * æ“作日志 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysOperLogMapper +{ + /** + * 新增æ“作日志 + * + * @param operLog æ“作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统æ“ä½œæ—¥å¿—é›†åˆ + * + * @param operLog æ“作日志对象 + * @return æ“ä½œæ—¥å¿—é›†åˆ + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿæ“作日志 + * + * @param operIds 需è¦åˆ é™¤çš„æ“ä½œæ—¥å¿—ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询æ“作日志详细 + * + * @param operId æ“作ID + * @return æ“作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空æ“作日志 + */ + public void cleanOperLog(); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java new file mode 100644 index 0000000..8603d9a --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java @@ -0,0 +1,99 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysPost; + +/** + * å²—ä½ä¿¡æ¯ æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysPostMapper +{ + /** + * æŸ¥è¯¢å²—ä½æ•°æ®é›†åˆ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 岗使•°æ®é›†åˆ + */ + public List selectPostList(SysPost post); + + /** + * æŸ¥è¯¢æ‰€æœ‰å²—ä½ + * + * @return å²—ä½åˆ—表 + */ + public List selectPostAll(); + + /** + * 通过岗ä½ID查询岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + public SysPost selectPostById(Long postId); + + /** + * æ ¹æ®ç”¨æˆ·ID获å–å²—ä½é€‰æ‹©æ¡†åˆ—表 + * + * @param userId 用户ID + * @return 选中岗ä½ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗ä½ç»„ + * + * @param userName 用户å + * @return 结果 + */ + public List selectPostsByUserName(String userName); + + /** + * 删除岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批é‡åˆ é™¤å²—ä½ä¿¡æ¯ + * + * @param postIds 需è¦åˆ é™¤çš„å²—ä½ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 修改岗ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public int updatePost(SysPost post); + + /** + * 新增岗ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 校验岗ä½åç§° + * + * @param postName å²—ä½åç§° + * @return 结果 + */ + public SysPost checkPostNameUnique(String postName); + + /** + * 校验岗ä½ç¼–ç  + * + * @param postCode å²—ä½ç¼–ç  + * @return 结果 + */ + public SysPost checkPostCodeUnique(String postCode); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java new file mode 100644 index 0000000..a4ad4de --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysRoleDept; + +/** + * 角色与部门关è”表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysRoleDeptMapper +{ + /** + * 通过角色IDåˆ é™¤è§’è‰²å’Œéƒ¨é—¨å…³è” + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批é‡åˆ é™¤è§’色部门关è”ä¿¡æ¯ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteRoleDept(Long[] ids); + + /** + * æŸ¥è¯¢éƒ¨é—¨ä½¿ç”¨æ•°é‡ + * + * @param deptId 部门ID + * @return 结果 + */ + public int selectCountRoleDeptByDeptId(Long deptId); + + /** + * æ‰¹é‡æ–°å¢žè§’è‰²éƒ¨é—¨ä¿¡æ¯ + * + * @param roleDeptList 角色部门列表 + * @return 结果 + */ + public int batchRoleDept(List roleDeptList); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..58ede18 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -0,0 +1,107 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysRole; + +/** + * 角色表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysRoleMapper +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢è§’è‰²æ•°æ® + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 角色数æ®é›†åˆä¿¡æ¯ + */ + public List selectRoleList(SysRole role); + + /** + * æ ¹æ®ç”¨æˆ·ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * æ ¹æ®ç”¨æˆ·ID获å–角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + public SysRole selectRoleById(Long roleId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询角色 + * + * @param userName 用户å + * @return 角色列表 + */ + public List selectRolesByUserName(String userName); + + /** + * 校验角色å称是å¦å”¯ä¸€ + * + * @param roleName 角色åç§° + * @return è§’è‰²ä¿¡æ¯ + */ + public SysRole checkRoleNameUnique(String roleName); + + /** + * 校验角色æƒé™æ˜¯å¦å”¯ä¸€ + * + * @param roleKey 角色æƒé™ + * @return è§’è‰²ä¿¡æ¯ + */ + public SysRole checkRoleKeyUnique(String roleKey); + + /** + * ä¿®æ”¹è§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * æ–°å¢žè§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批é‡åˆ é™¤è§’è‰²ä¿¡æ¯ + * + * @param roleIds 需è¦åˆ é™¤çš„角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..2339155 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysRoleMenu; + +/** + * 角色与èœå•å…³è”表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysRoleMenuMapper +{ + /** + * 查询èœå•ä½¿ç”¨æ•°é‡ + * + * @param menuId èœå•ID + * @return 结果 + */ + public int checkMenuExistRole(Long menuId); + + /** + * 通过角色ID删除角色和èœå•å…³è” + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleMenuByRoleId(Long roleId); + + /** + * 批é‡åˆ é™¤è§’色èœå•å…³è”ä¿¡æ¯ + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteRoleMenu(Long[] ids); + + /** + * æ‰¹é‡æ–°å¢žè§’色èœå•ä¿¡æ¯ + * + * @param roleMenuList 角色èœå•列表 + * @return 结果 + */ + public int batchRoleMenu(List roleMenuList); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..c86acea --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -0,0 +1,127 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 用户表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysUserMapper +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢ç”¨æˆ·åˆ—表 + * + * @param sysUser ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectUserList(SysUser sysUser); + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å·²é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectAllocatedList(SysUser user); + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢æœªåˆ†é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectUnallocatedList(SysUser user); + + /** + * é€šè¿‡ç”¨æˆ·åæŸ¥è¯¢ç”¨æˆ· + * + * @param userName 用户å + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + public SysUser selectUserById(Long userId); + + /** + * æ–°å¢žç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * ä¿®æ”¹ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * ä¿®æ”¹ç”¨æˆ·å¤´åƒ + * + * @param userName 用户å + * @param avatar 头åƒåœ°å€ + * @return 结果 + */ + public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); + + /** + * é‡ç½®ç”¨æˆ·å¯†ç  + * + * @param userName 用户å + * @param password å¯†ç  + * @return 结果 + */ + public int resetUserPwd(@Param("userName") String userName, @Param("password") String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·ä¿¡æ¯ + * + * @param userIds 需è¦åˆ é™¤çš„用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 校验用户å称是å¦å”¯ä¸€ + * + * @param userName 用户åç§° + * @return 结果 + */ + public SysUser checkUserNameUnique(String userName); + + /** + * 校验手机å·ç æ˜¯å¦å”¯ä¸€ + * + * @param phonenumber 手机å·ç  + * @return 结果 + */ + public SysUser checkPhoneUnique(String phonenumber); + + /** + * 校验email是å¦å”¯ä¸€ + * + * @param email 用户邮箱 + * @return 结果 + */ + public SysUser checkEmailUnique(String email); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java new file mode 100644 index 0000000..9c33e54 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysUserPost; + +/** + * 用户与岗ä½å…³è”表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysUserPostMapper +{ + /** + * 通过用户ID删除用户和岗ä½å…³è” + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserPostByUserId(Long userId); + + /** + * 通过岗ä½ID查询岗ä½ä½¿ç”¨æ•°é‡ + * + * @param postId å²—ä½ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·å’Œå²—ä½å…³è” + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteUserPost(Long[] ids); + + /** + * æ‰¹é‡æ–°å¢žç”¨æˆ·å²—ä½ä¿¡æ¯ + * + * @param userPostList 用户角色列表 + * @return 结果 + */ + public int batchUserPost(List userPostList); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..ad3fe62 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,62 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.system.domain.SysUserRole; + +/** + * 用户与角色关è”表 æ•°æ®å±‚ + * + * @author ruoyi + */ +public interface SysUserRoleMapper +{ + /** + * 通过用户IDåˆ é™¤ç”¨æˆ·å’Œè§’è‰²å…³è” + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserRoleByUserId(Long userId); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·å’Œè§’è‰²å…³è” + * + * @param ids 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteUserRole(Long[] ids); + + /** + * 通过角色IDæŸ¥è¯¢è§’è‰²ä½¿ç”¨æ•°é‡ + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * æ‰¹é‡æ–°å¢žç”¨æˆ·è§’è‰²ä¿¡æ¯ + * + * @param userRoleList 用户角色列表 + * @return 结果 + */ + public int batchUserRole(List userRoleList); + + /** + * 删除用户和角色关è”ä¿¡æ¯ + * + * @param userRole 用户和角色关è”ä¿¡æ¯ + * @return 结果 + */ + public int deleteUserRoleInfo(SysUserRole userRole); + + /** + * 批é‡å–消授æƒç”¨æˆ·è§’色 + * + * @param roleId 角色ID + * @param userIds 需è¦åˆ é™¤çš„用户数æ®ID + * @return 结果 + */ + public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java new file mode 100644 index 0000000..2096137 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java @@ -0,0 +1,89 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysConfig; + +/** + * 傿•°é…ç½® æœåС层 + * + * @author ruoyi + */ +public interface ISysConfigService +{ + /** + * æŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param configId 傿•°é…ç½®ID + * @return 傿•°é…ç½®ä¿¡æ¯ + */ + public SysConfig selectConfigById(Long configId); + + /** + * æ ¹æ®é”®åæŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param configKey 傿•°é”®å + * @return 傿•°é”®å€¼ + */ + public String selectConfigByKey(String configKey); + + /** + * 获å–验è¯ç å¼€å…³ + * + * @return trueå¼€å¯ï¼Œfalse关闭 + */ + public boolean selectCaptchaEnabled(); + + /** + * æŸ¥è¯¢å‚æ•°é…置列表 + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 傿•°é…ç½®é›†åˆ + */ + public List selectConfigList(SysConfig config); + + /** + * æ–°å¢žå‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * ä¿®æ”¹å‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 批é‡åˆ é™¤å‚æ•°ä¿¡æ¯ + * + * @param configIds 需è¦åˆ é™¤çš„傿•°ID + */ + public void deleteConfigByIds(Long[] configIds); + + /** + * åŠ è½½å‚æ•°ç¼“å­˜æ•°æ® + */ + public void loadingConfigCache(); + + /** + * æ¸…ç©ºå‚æ•°ç¼“å­˜æ•°æ® + */ + public void clearConfigCache(); + + /** + * é‡ç½®å‚æ•°ç¼“å­˜æ•°æ® + */ + public void resetConfigCache(); + + /** + * æ ¡éªŒå‚æ•°é”®å是å¦å”¯ä¸€ + * + * @param config 傿•°ä¿¡æ¯ + * @return 结果 + */ + public boolean checkConfigKeyUnique(SysConfig config); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java new file mode 100644 index 0000000..302d7a1 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java @@ -0,0 +1,124 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * éƒ¨é—¨ç®¡ç† æœåС层 + * + * @author ruoyi + */ +public interface ISysDeptService +{ + /** + * æŸ¥è¯¢éƒ¨é—¨ç®¡ç†æ•°æ® + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 部门信æ¯é›†åˆ + */ + public List selectDeptList(SysDept dept); + + /** + * æŸ¥è¯¢éƒ¨é—¨æ ‘ç»“æž„ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 部门树信æ¯é›†åˆ + */ + public List selectDeptTreeList(SysDept dept); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦æ ‘结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + public List buildDeptTree(List depts); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦ä¸‹æ‹‰æ ‘结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + public List buildDeptTreeSelect(List depts); + + /** + * æ ¹æ®è§’色IDæŸ¥è¯¢éƒ¨é—¨æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(Long roleId); + + /** + * æ ¹æ®éƒ¨é—¨IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param deptId 部门ID + * @return éƒ¨é—¨ä¿¡æ¯ + */ + public SysDept selectDeptById(Long deptId); + + /** + * æ ¹æ®ID查询所有å­éƒ¨é—¨ï¼ˆæ­£å¸¸çжæ€ï¼‰ + * + * @param deptId 部门ID + * @return å­éƒ¨é—¨æ•° + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是å¦å­˜åœ¨éƒ¨é—¨å­èŠ‚ç‚¹ + * + * @param deptId 部门ID + * @return 结果 + */ + public boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是å¦å­˜åœ¨ç”¨æˆ· + * + * @param deptId 部门ID + * @return 结果 true 存在 false ä¸å­˜åœ¨ + */ + public boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门å称是å¦å”¯ä¸€ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + public boolean checkDeptNameUnique(SysDept dept); + + /** + * æ ¡éªŒéƒ¨é—¨æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param deptId 部门id + */ + public void checkDeptDataScope(Long deptId); + + /** + * 新增ä¿å­˜éƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改ä¿å­˜éƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 删除部门管ç†ä¿¡æ¯ + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java new file mode 100644 index 0000000..9a5cf19 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictData; + +/** + * å­—å…¸ 业务层 + * + * @author ruoyi + */ +public interface ISysDictDataService +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + public List selectDictDataList(SysDictData dictData); + + /** + * æ ¹æ®å­—典类型和字典键值查询字典数æ®ä¿¡æ¯ + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(String dictType, String dictValue); + + /** + * æ ¹æ®å­—典数æ®IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictCode 字典数æ®ID + * @return å­—å…¸æ•°æ® + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 批é‡åˆ é™¤å­—典数æ®ä¿¡æ¯ + * + * @param dictCodes 需è¦åˆ é™¤çš„字典数æ®ID + */ + public void deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增ä¿å­˜å­—典数æ®ä¿¡æ¯ + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改ä¿å­˜å­—典数æ®ä¿¡æ¯ + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + public int updateDictData(SysDictData dictData); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java new file mode 100644 index 0000000..f01a358 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java @@ -0,0 +1,98 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + * å­—å…¸ 业务层 + * + * @author ruoyi + */ +public interface ISysDictTypeService +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—典类型 + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 字典类型集åˆä¿¡æ¯ + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * æ ¹æ®æ‰€æœ‰å­—典类型 + * + * @return 字典类型集åˆä¿¡æ¯ + */ + public List selectDictTypeAll(); + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictType 字典类型 + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + public List selectDictDataByType(String dictType); + + /** + * æ ¹æ®å­—典类型IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢ä¿¡æ¯ + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 批é‡åˆ é™¤å­—å…¸ä¿¡æ¯ + * + * @param dictIds 需è¦åˆ é™¤çš„å­—å…¸ID + */ + public void deleteDictTypeByIds(Long[] dictIds); + + /** + * åŠ è½½å­—å…¸ç¼“å­˜æ•°æ® + */ + public void loadingDictCache(); + + /** + * æ¸…ç©ºå­—å…¸ç¼“å­˜æ•°æ® + */ + public void clearDictCache(); + + /** + * é‡ç½®å­—å…¸ç¼“å­˜æ•°æ® + */ + public void resetDictCache(); + + /** + * 新增ä¿å­˜å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改ä¿å­˜å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是å¦å”¯ä¸€ + * + * @param dictType 字典类型 + * @return 结果 + */ + public boolean checkDictTypeUnique(SysDictType dictType); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java new file mode 100644 index 0000000..0a83208 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java @@ -0,0 +1,40 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysLogininfor; + +/** + * ç³»ç»Ÿè®¿é—®æ—¥å¿—æƒ…å†µä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +public interface ISysLogininforService +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * æŸ¥è¯¢ç³»ç»Ÿç™»å½•æ—¥å¿—é›†åˆ + * + * @param logininfor 访问日志对象 + * @return ç™»å½•è®°å½•é›†åˆ + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿç™»å½•日志 + * + * @param infoIds 需è¦åˆ é™¤çš„登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + */ + public void cleanLogininfor(); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java new file mode 100644 index 0000000..134b9eb --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -0,0 +1,144 @@ +package com.ruoyi.system.service; + +import java.util.List; +import java.util.Set; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.system.domain.vo.RouterVo; + +/** + * èœå• 业务层 + * + * @author ruoyi + */ +public interface ISysMenuService +{ + /** + * æ ¹æ®ç”¨æˆ·æŸ¥è¯¢ç³»ç»Ÿèœå•列表 + * + * @param userId 用户ID + * @return èœå•列表 + */ + public List selectMenuList(Long userId); + + /** + * æ ¹æ®ç”¨æˆ·æŸ¥è¯¢ç³»ç»Ÿèœå•列表 + * + * @param menu èœå•ä¿¡æ¯ + * @param userId 用户ID + * @return èœå•列表 + */ + public List selectMenuList(SysMenu menu, Long userId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询æƒé™ + * + * @param userId 用户ID + * @return æƒé™åˆ—表 + */ + public Set selectMenuPermsByUserId(Long userId); + + /** + * æ ¹æ®è§’色ID查询æƒé™ + * + * @param roleId 角色ID + * @return æƒé™åˆ—表 + */ + public Set selectMenuPermsByRoleId(Long roleId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询èœå•æ ‘ä¿¡æ¯ + * + * @param userId 用户ID + * @return èœå•列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * æ ¹æ®è§’色ID查询èœå•æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @return 选中èœå•列表 + */ + public List selectMenuListByRoleId(Long roleId); + + /** + * 构建å‰ç«¯è·¯ç”±æ‰€éœ€è¦çš„èœå• + * + * @param menus èœå•列表 + * @return 路由列表 + */ + public List buildMenus(List menus); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦æ ‘结构 + * + * @param menus èœå•列表 + * @return 树结构列表 + */ + public List buildMenuTree(List menus); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦ä¸‹æ‹‰æ ‘结构 + * + * @param menus èœå•列表 + * @return 下拉树结构列表 + */ + public List buildMenuTreeSelect(List menus); + + /** + * æ ¹æ®èœå•IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return èœå•ä¿¡æ¯ + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是å¦å­˜åœ¨èœå•å­èŠ‚ç‚¹ + * + * @param menuId èœå•ID + * @return 结果 true 存在 false ä¸å­˜åœ¨ + */ + public boolean hasChildByMenuId(Long menuId); + + /** + * 查询èœå•是å¦å­˜åœ¨è§’色 + * + * @param menuId èœå•ID + * @return 结果 true 存在 false ä¸å­˜åœ¨ + */ + public boolean checkMenuExistRole(Long menuId); + + /** + * 新增ä¿å­˜èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改ä¿å­˜èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除èœå•管ç†ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验èœå•å称是å¦å”¯ä¸€ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public boolean checkMenuNameUnique(SysMenu menu); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java new file mode 100644 index 0000000..fb1e420 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysNotice; + +/** + * 公告 æœåС层 + * + * @author ruoyi + */ +public interface ISysNoticeService +{ + /** + * æŸ¥è¯¢å…¬å‘Šä¿¡æ¯ + * + * @param noticeId 公告ID + * @return å…¬å‘Šä¿¡æ¯ + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return å…¬å‘Šé›†åˆ + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * åˆ é™¤å…¬å‘Šä¿¡æ¯ + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批é‡åˆ é™¤å…¬å‘Šä¿¡æ¯ + * + * @param noticeIds 需è¦åˆ é™¤çš„公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java new file mode 100644 index 0000000..241f121 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysOperLog; + +/** + * æ“作日志 æœåС层 + * + * @author ruoyi + */ +public interface ISysOperLogService +{ + /** + * 新增æ“作日志 + * + * @param operLog æ“作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统æ“ä½œæ—¥å¿—é›†åˆ + * + * @param operLog æ“作日志对象 + * @return æ“ä½œæ—¥å¿—é›†åˆ + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿæ“作日志 + * + * @param operIds 需è¦åˆ é™¤çš„æ“ä½œæ—¥å¿—ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询æ“作日志详细 + * + * @param operId æ“作ID + * @return æ“作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空æ“作日志 + */ + public void cleanOperLog(); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java new file mode 100644 index 0000000..590634b --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java @@ -0,0 +1,99 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysPost; + +/** + * å²—ä½ä¿¡æ¯ æœåС层 + * + * @author ruoyi + */ +public interface ISysPostService +{ + /** + * 查询岗ä½ä¿¡æ¯é›†åˆ + * + * @param post å²—ä½ä¿¡æ¯ + * @return å²—ä½åˆ—表 + */ + public List selectPostList(SysPost post); + + /** + * æŸ¥è¯¢æ‰€æœ‰å²—ä½ + * + * @return å²—ä½åˆ—表 + */ + public List selectPostAll(); + + /** + * 通过岗ä½ID查询岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + public SysPost selectPostById(Long postId); + + /** + * æ ¹æ®ç”¨æˆ·ID获å–å²—ä½é€‰æ‹©æ¡†åˆ—表 + * + * @param userId 用户ID + * @return 选中岗ä½ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 校验岗ä½åç§° + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public boolean checkPostNameUnique(SysPost post); + + /** + * 校验岗ä½ç¼–ç  + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public boolean checkPostCodeUnique(SysPost post); + + /** + * 通过岗ä½ID查询岗ä½ä½¿ç”¨æ•°é‡ + * + * @param postId å²—ä½ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 删除岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批é‡åˆ é™¤å²—ä½ä¿¡æ¯ + * + * @param postIds 需è¦åˆ é™¤çš„å²—ä½ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 新增ä¿å­˜å²—ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 修改ä¿å­˜å²—ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + public int updatePost(SysPost post); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java new file mode 100644 index 0000000..ba79ed5 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -0,0 +1,173 @@ +package com.ruoyi.system.service; + +import java.util.List; +import java.util.Set; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.system.domain.SysUserRole; + +/** + * 角色业务层 + * + * @author ruoyi + */ +public interface ISysRoleService +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢è§’è‰²æ•°æ® + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 角色数æ®é›†åˆä¿¡æ¯ + */ + public List selectRoleList(SysRole role); + + /** + * æ ¹æ®ç”¨æˆ·ID查询角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolesByUserId(Long userId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询角色æƒé™ + * + * @param userId 用户ID + * @return æƒé™åˆ—表 + */ + public Set selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * æ ¹æ®ç”¨æˆ·ID获å–角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + public SysRole selectRoleById(Long roleId); + + /** + * 校验角色å称是å¦å”¯ä¸€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public boolean checkRoleNameUnique(SysRole role); + + /** + * 校验角色æƒé™æ˜¯å¦å”¯ä¸€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public boolean checkRoleKeyUnique(SysRole role); + + /** + * 校验角色是å¦å…许æ“作 + * + * @param role è§’è‰²ä¿¡æ¯ + */ + public void checkRoleAllowed(SysRole role); + + /** + * æ ¡éªŒè§’è‰²æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param roleId 角色id + */ + public void checkRoleDataScope(Long roleId); + + /** + * 通过角色IDæŸ¥è¯¢è§’è‰²ä½¿ç”¨æ•°é‡ + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 新增ä¿å­˜è§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 修改ä¿å­˜è§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * ä¿®æ”¹è§’è‰²çŠ¶æ€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int updateRoleStatus(SysRole role); + + /** + * ä¿®æ”¹æ•°æ®æƒé™ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + public int authDataScope(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批é‡åˆ é™¤è§’è‰²ä¿¡æ¯ + * + * @param roleIds 需è¦åˆ é™¤çš„角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); + + /** + * å–æ¶ˆæŽˆæƒç”¨æˆ·è§’色 + * + * @param userRole 用户和角色关è”ä¿¡æ¯ + * @return 结果 + */ + public int deleteAuthUser(SysUserRole userRole); + + /** + * 批é‡å–消授æƒç”¨æˆ·è§’色 + * + * @param roleId 角色ID + * @param userIds 需è¦å–消授æƒçš„用户数æ®ID + * @return 结果 + */ + public int deleteAuthUsers(Long roleId, Long[] userIds); + + /** + * 批é‡é€‰æ‹©æŽˆæƒç”¨æˆ·è§’色 + * + * @param roleId 角色ID + * @param userIds 需è¦åˆ é™¤çš„用户数æ®ID + * @return 结果 + */ + public int insertAuthUsers(Long roleId, Long[] userIds); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java new file mode 100644 index 0000000..12095ff --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.service; + +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.system.domain.SysUserOnline; + +/** + * 在线用户 æœåС层 + * + * @author ruoyi + */ +public interface ISysUserOnlineService +{ + /** + * é€šè¿‡ç™»å½•åœ°å€æŸ¥è¯¢ä¿¡æ¯ + * + * @param ipaddr ç™»å½•åœ°å€ + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user); + + /** + * 通过用户åç§°æŸ¥è¯¢ä¿¡æ¯ + * + * @param userName 用户åç§° + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user); + + /** + * 通过登录地å€/用户åç§°æŸ¥è¯¢ä¿¡æ¯ + * + * @param ipaddr ç™»å½•åœ°å€ + * @param userName 用户åç§° + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user); + + /** + * è®¾ç½®åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 在线用户 + */ + public SysUserOnline loginUserToUserOnline(LoginUser user); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java new file mode 100644 index 0000000..e438b57 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -0,0 +1,206 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 用户 业务层 + * + * @author ruoyi + */ +public interface ISysUserService +{ + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢ç”¨æˆ·åˆ—表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectUserList(SysUser user); + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å·²åˆ†é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectAllocatedList(SysUser user); + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢æœªåˆ†é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + public List selectUnallocatedList(SysUser user); + + /** + * é€šè¿‡ç”¨æˆ·åæŸ¥è¯¢ç”¨æˆ· + * + * @param userName 用户å + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + public SysUser selectUserById(Long userId); + + /** + * æ ¹æ®ç”¨æˆ·ID查询用户所属角色组 + * + * @param userName 用户å + * @return 结果 + */ + public String selectUserRoleGroup(String userName); + + /** + * æ ¹æ®ç”¨æˆ·ID查询用户所属岗ä½ç»„ + * + * @param userName 用户å + * @return 结果 + */ + public String selectUserPostGroup(String userName); + + /** + * 校验用户å称是å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public boolean checkUserNameUnique(SysUser user); + + /** + * 校验手机å·ç æ˜¯å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public boolean checkPhoneUnique(SysUser user); + + /** + * 校验email是å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public boolean checkEmailUnique(SysUser user); + + /** + * 校验用户是å¦å…许æ“作 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + */ + public void checkUserAllowed(SysUser user); + + /** + * æ ¡éªŒç”¨æˆ·æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param userId 用户id + */ + public void checkUserDataScope(Long userId); + + /** + * æ–°å¢žç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * æ³¨å†Œç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public boolean registerUser(SysUser user); + + /** + * ä¿®æ”¹ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 用户授æƒè§’色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserAuth(Long userId, Long[] roleIds); + + /** + * ä¿®æ”¹ç”¨æˆ·çŠ¶æ€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int updateUserStatus(SysUser user); + + /** + * ä¿®æ”¹ç”¨æˆ·åŸºæœ¬ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int updateUserProfile(SysUser user); + + /** + * ä¿®æ”¹ç”¨æˆ·å¤´åƒ + * + * @param userName 用户å + * @param avatar 头åƒåœ°å€ + * @return 结果 + */ + public boolean updateUserAvatar(String userName, String avatar); + + /** + * é‡ç½®ç”¨æˆ·å¯†ç  + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + public int resetPwd(SysUser user); + + /** + * é‡ç½®ç”¨æˆ·å¯†ç  + * + * @param userName 用户å + * @param password å¯†ç  + * @return 结果 + */ + public int resetUserPwd(String userName, String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·ä¿¡æ¯ + * + * @param userIds 需è¦åˆ é™¤çš„用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * å¯¼å…¥ç”¨æˆ·æ•°æ® + * + * @param userList 用户数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + public String importUser(List userList, Boolean isUpdateSupport, String operName); +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..3615b88 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,232 @@ +package com.ruoyi.system.service.impl; + +import java.util.Collection; +import java.util.List; +import javax.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataSource; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.enums.DataSourceType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.mapper.SysConfigMapper; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 傿•°é…ç½® æœåŠ¡å±‚å®žçŽ° + * + * @author ruoyi + */ +@Service +public class SysConfigServiceImpl implements ISysConfigService +{ + @Autowired + private SysConfigMapper configMapper; + + @Autowired + private RedisCache redisCache; + + /** + * 项目å¯åŠ¨æ—¶ï¼Œåˆå§‹åŒ–傿•°åˆ°ç¼“å­˜ + */ + @PostConstruct + public void init() + { + loadingConfigCache(); + } + + /** + * æŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param configId 傿•°é…ç½®ID + * @return 傿•°é…ç½®ä¿¡æ¯ + */ + @Override + @DataSource(DataSourceType.MASTER) + public SysConfig selectConfigById(Long configId) + { + SysConfig config = new SysConfig(); + config.setConfigId(configId); + return configMapper.selectConfig(config); + } + + /** + * æ ¹æ®é”®åæŸ¥è¯¢å‚æ•°é…ç½®ä¿¡æ¯ + * + * @param configKey 傿•°key + * @return 傿•°é”®å€¼ + */ + @Override + public String selectConfigByKey(String configKey) + { + String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))); + if (StringUtils.isNotEmpty(configValue)) + { + return configValue; + } + SysConfig config = new SysConfig(); + config.setConfigKey(configKey); + SysConfig retConfig = configMapper.selectConfig(config); + if (StringUtils.isNotNull(retConfig)) + { + redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); + return retConfig.getConfigValue(); + } + return StringUtils.EMPTY; + } + + /** + * 获å–验è¯ç å¼€å…³ + * + * @return trueå¼€å¯ï¼Œfalse关闭 + */ + @Override + public boolean selectCaptchaEnabled() + { + String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled"); + if (StringUtils.isEmpty(captchaEnabled)) + { + return true; + } + return Convert.toBool(captchaEnabled); + } + + /** + * æŸ¥è¯¢å‚æ•°é…置列表 + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 傿•°é…ç½®é›†åˆ + */ + @Override + public List selectConfigList(SysConfig config) + { + return configMapper.selectConfigList(config); + } + + /** + * æ–°å¢žå‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertConfig(SysConfig config) + { + int row = configMapper.insertConfig(config); + if (row > 0) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * ä¿®æ”¹å‚æ•°é…ç½® + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateConfig(SysConfig config) + { + SysConfig temp = configMapper.selectConfigById(config.getConfigId()); + if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) + { + redisCache.deleteObject(getCacheKey(temp.getConfigKey())); + } + + int row = configMapper.updateConfig(config); + if (row > 0) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 批é‡åˆ é™¤å‚æ•°ä¿¡æ¯ + * + * @param configIds 需è¦åˆ é™¤çš„傿•°ID + */ + @Override + public void deleteConfigByIds(Long[] configIds) + { + for (Long configId : configIds) + { + SysConfig config = selectConfigById(configId); + if (StringUtils.equals(UserConstants.YES, config.getConfigType())) + { + throw new ServiceException(String.format("å†…ç½®å‚æ•°ã€%1$s】ä¸èƒ½åˆ é™¤ ", config.getConfigKey())); + } + configMapper.deleteConfigById(configId); + redisCache.deleteObject(getCacheKey(config.getConfigKey())); + } + } + + /** + * åŠ è½½å‚æ•°ç¼“å­˜æ•°æ® + */ + @Override + public void loadingConfigCache() + { + List configsList = configMapper.selectConfigList(new SysConfig()); + for (SysConfig config : configsList) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + } + + /** + * æ¸…ç©ºå‚æ•°ç¼“å­˜æ•°æ® + */ + @Override + public void clearConfigCache() + { + Collection keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*"); + redisCache.deleteObject(keys); + } + + /** + * é‡ç½®å‚æ•°ç¼“å­˜æ•°æ® + */ + @Override + public void resetConfigCache() + { + clearConfigCache(); + loadingConfigCache(); + } + + /** + * æ ¡éªŒå‚æ•°é”®å是å¦å”¯ä¸€ + * + * @param config 傿•°é…ç½®ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkConfigKeyUnique(SysConfig config) + { + Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()); + if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 设置cache key + * + * @param configKey 傿•°é”® + * @return 缓存键key + */ + private String getCacheKey(String configKey) + { + return CacheConstants.SYS_CONFIG_KEY + configKey; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..c5f3ce6 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,338 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.service.ISysDeptService; + +/** + * éƒ¨é—¨ç®¡ç† æœåŠ¡å®žçŽ° + * + * @author ruoyi + */ +@Service +public class SysDeptServiceImpl implements ISysDeptService +{ + @Autowired + private SysDeptMapper deptMapper; + + @Autowired + private SysRoleMapper roleMapper; + + /** + * æŸ¥è¯¢éƒ¨é—¨ç®¡ç†æ•°æ® + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 部门信æ¯é›†åˆ + */ + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDept dept) + { + return deptMapper.selectDeptList(dept); + } + + /** + * æŸ¥è¯¢éƒ¨é—¨æ ‘ç»“æž„ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 部门树信æ¯é›†åˆ + */ + @Override + public List selectDeptTreeList(SysDept dept) + { + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + return buildDeptTreeSelect(depts); + } + + /** + * 构建å‰ç«¯æ‰€éœ€è¦æ ‘结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + @Override + public List buildDeptTree(List depts) + { + List returnList = new ArrayList(); + List tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList()); + for (SysDept dept : depts) + { + // 如果是顶级节点, é历该父节点的所有å­èŠ‚ç‚¹ + if (!tempList.contains(dept.getParentId())) + { + recursionFn(depts, dept); + returnList.add(dept); + } + } + if (returnList.isEmpty()) + { + returnList = depts; + } + return returnList; + } + + /** + * 构建å‰ç«¯æ‰€éœ€è¦ä¸‹æ‹‰æ ‘结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List buildDeptTreeSelect(List depts) + { + List deptTrees = buildDeptTree(depts); + return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * æ ¹æ®è§’色IDæŸ¥è¯¢éƒ¨é—¨æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * æ ¹æ®éƒ¨é—¨IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param deptId 部门ID + * @return éƒ¨é—¨ä¿¡æ¯ + */ + @Override + public SysDept selectDeptById(Long deptId) + { + return deptMapper.selectDeptById(deptId); + } + + /** + * æ ¹æ®ID查询所有å­éƒ¨é—¨ï¼ˆæ­£å¸¸çжæ€ï¼‰ + * + * @param deptId 部门ID + * @return å­éƒ¨é—¨æ•° + */ + @Override + public int selectNormalChildrenDeptById(Long deptId) + { + return deptMapper.selectNormalChildrenDeptById(deptId); + } + + /** + * 是å¦å­˜åœ¨å­èŠ‚ç‚¹ + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) + { + int result = deptMapper.hasChildByDeptId(deptId); + return result > 0; + } + + /** + * 查询部门是å¦å­˜åœ¨ç”¨æˆ· + * + * @param deptId 部门ID + * @return 结果 true 存在 false ä¸å­˜åœ¨ + */ + @Override + public boolean checkDeptExistUser(Long deptId) + { + int result = deptMapper.checkDeptExistUser(deptId); + return result > 0; + } + + /** + * 校验部门å称是å¦å”¯ä¸€ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkDeptNameUnique(SysDept dept) + { + Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId(); + SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId()); + if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * æ ¡éªŒéƒ¨é—¨æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param deptId 部门id + */ + @Override + public void checkDeptDataScope(Long deptId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysDept dept = new SysDept(); + dept.setDeptId(deptId); + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + if (StringUtils.isEmpty(depts)) + { + throw new ServiceException("没有æƒé™è®¿é—®éƒ¨é—¨æ•°æ®ï¼"); + } + } + } + + /** + * 新增ä¿å­˜éƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertDept(SysDept dept) + { + SysDept info = deptMapper.selectDeptById(dept.getParentId()); + // 如果父节点ä¸ä¸ºæ­£å¸¸çжæ€,则ä¸å…许新增å­èŠ‚ç‚¹ + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) + { + throw new ServiceException("部门åœç”¨ï¼Œä¸å…许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + return deptMapper.insertDept(dept); + } + + /** + * 修改ä¿å­˜éƒ¨é—¨ä¿¡æ¯ + * + * @param dept éƒ¨é—¨ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateDept(SysDept dept) + { + SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId()); + SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId()); + if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) + { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + int result = deptMapper.updateDept(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals("0", dept.getAncestors())) + { + // 如果该部门是å¯ç”¨çжæ€ï¼Œåˆ™å¯ç”¨è¯¥éƒ¨é—¨çš„æ‰€æœ‰ä¸Šçº§éƒ¨é—¨ + updateParentDeptStatusNormal(dept); + } + return result; + } + + /** + * ä¿®æ”¹è¯¥éƒ¨é—¨çš„çˆ¶çº§éƒ¨é—¨çŠ¶æ€ + * + * @param dept 当å‰éƒ¨é—¨ + */ + private void updateParentDeptStatusNormal(SysDept dept) + { + String ancestors = dept.getAncestors(); + Long[] deptIds = Convert.toLongArray(ancestors); + deptMapper.updateDeptStatusNormal(deptIds); + } + + /** + * 修改å­å…ƒç´ å…³ç³» + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父IDé›†åˆ + * @param oldAncestors 旧的父IDé›†åˆ + */ + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) + { + List children = deptMapper.selectChildrenDeptById(deptId); + for (SysDept child : children) + { + child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + } + if (children.size() > 0) + { + deptMapper.updateDeptChildren(children); + } + } + + /** + * 删除部门管ç†ä¿¡æ¯ + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public int deleteDeptById(Long deptId) + { + return deptMapper.deleteDeptById(deptId); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDept t) + { + // 得到å­èŠ‚ç‚¹åˆ—è¡¨ + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDept tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到å­èŠ‚ç‚¹åˆ—è¡¨ + */ + private List getChildList(List list, SysDept t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysDept n = (SysDept) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * åˆ¤æ–­æ˜¯å¦æœ‰å­èŠ‚ç‚¹ + */ + private boolean hasChild(List list, SysDept t) + { + return getChildList(list, t).size() > 0; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..de244f8 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,111 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.service.ISysDictDataService; + +/** + * å­—å…¸ ä¸šåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysDictDataServiceImpl implements ISysDictDataService +{ + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictData 字典数æ®ä¿¡æ¯ + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + @Override + public List selectDictDataList(SysDictData dictData) + { + return dictDataMapper.selectDictDataList(dictData); + } + + /** + * æ ¹æ®å­—典类型和字典键值查询字典数æ®ä¿¡æ¯ + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + @Override + public String selectDictLabel(String dictType, String dictValue) + { + return dictDataMapper.selectDictLabel(dictType, dictValue); + } + + /** + * æ ¹æ®å­—典数æ®IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictCode 字典数æ®ID + * @return å­—å…¸æ•°æ® + */ + @Override + public SysDictData selectDictDataById(Long dictCode) + { + return dictDataMapper.selectDictDataById(dictCode); + } + + /** + * 批é‡åˆ é™¤å­—典数æ®ä¿¡æ¯ + * + * @param dictCodes 需è¦åˆ é™¤çš„字典数æ®ID + */ + @Override + public void deleteDictDataByIds(Long[] dictCodes) + { + for (Long dictCode : dictCodes) + { + SysDictData data = selectDictDataById(dictCode); + dictDataMapper.deleteDictDataById(dictCode); + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + } + + /** + * 新增ä¿å­˜å­—典数æ®ä¿¡æ¯ + * + * @param data 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertDictData(SysDictData data) + { + int row = dictDataMapper.insertDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } + + /** + * 修改ä¿å­˜å­—典数æ®ä¿¡æ¯ + * + * @param data 字典数æ®ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateDictData(SysDictData data) + { + int row = dictDataMapper.updateDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..b6c4c56 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,223 @@ +package com.ruoyi.system.service.impl; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.mapper.SysDictTypeMapper; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * å­—å…¸ ä¸šåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService +{ + @Autowired + private SysDictTypeMapper dictTypeMapper; + + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 项目å¯åŠ¨æ—¶ï¼Œåˆå§‹åŒ–字典到缓存 + */ + @PostConstruct + public void init() + { + loadingDictCache(); + } + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å­—典类型 + * + * @param dictType å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 字典类型集åˆä¿¡æ¯ + */ + @Override + public List selectDictTypeList(SysDictType dictType) + { + return dictTypeMapper.selectDictTypeList(dictType); + } + + /** + * æ ¹æ®æ‰€æœ‰å­—典类型 + * + * @return 字典类型集åˆä¿¡æ¯ + */ + @Override + public List selectDictTypeAll() + { + return dictTypeMapper.selectDictTypeAll(); + } + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢å­—å…¸æ•°æ® + * + * @param dictType 字典类型 + * @return 字典数æ®é›†åˆä¿¡æ¯ + */ + @Override + public List selectDictDataByType(String dictType) + { + List dictDatas = DictUtils.getDictCache(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + return dictDatas; + } + dictDatas = dictDataMapper.selectDictDataByType(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + DictUtils.setDictCache(dictType, dictDatas); + return dictDatas; + } + return null; + } + + /** + * æ ¹æ®å­—典类型IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeById(Long dictId) + { + return dictTypeMapper.selectDictTypeById(dictId); + } + + /** + * æ ¹æ®å­—å…¸ç±»åž‹æŸ¥è¯¢ä¿¡æ¯ + * + * @param dictType 字典类型 + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeByType(String dictType) + { + return dictTypeMapper.selectDictTypeByType(dictType); + } + + /** + * 批é‡åˆ é™¤å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dictIds 需è¦åˆ é™¤çš„å­—å…¸ID + */ + @Override + public void deleteDictTypeByIds(Long[] dictIds) + { + for (Long dictId : dictIds) + { + SysDictType dictType = selectDictTypeById(dictId); + if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) + { + throw new ServiceException(String.format("%1$s已分é…,ä¸èƒ½åˆ é™¤", dictType.getDictName())); + } + dictTypeMapper.deleteDictTypeById(dictId); + DictUtils.removeDictCache(dictType.getDictType()); + } + } + + /** + * åŠ è½½å­—å…¸ç¼“å­˜æ•°æ® + */ + @Override + public void loadingDictCache() + { + SysDictData dictData = new SysDictData(); + dictData.setStatus("0"); + Map> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getDictType)); + for (Map.Entry> entry : dictDataMap.entrySet()) + { + DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList())); + } + } + + /** + * æ¸…ç©ºå­—å…¸ç¼“å­˜æ•°æ® + */ + @Override + public void clearDictCache() + { + DictUtils.clearDictCache(); + } + + /** + * é‡ç½®å­—å…¸ç¼“å­˜æ•°æ® + */ + @Override + public void resetDictCache() + { + clearDictCache(); + loadingDictCache(); + } + + /** + * 新增ä¿å­˜å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dict å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertDictType(SysDictType dict) + { + int row = dictTypeMapper.insertDictType(dict); + if (row > 0) + { + DictUtils.setDictCache(dict.getDictType(), null); + } + return row; + } + + /** + * 修改ä¿å­˜å­—å…¸ç±»åž‹ä¿¡æ¯ + * + * @param dict å­—å…¸ç±»åž‹ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int updateDictType(SysDictType dict) + { + SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId()); + dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType()); + int row = dictTypeMapper.updateDictType(dict); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType()); + DictUtils.setDictCache(dict.getDictType(), dictDatas); + } + return row; + } + + /** + * 校验字典类型称是å¦å”¯ä¸€ + * + * @param dict 字典类型 + * @return 结果 + */ + @Override + public boolean checkDictTypeUnique(SysDictType dict) + { + Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId(); + SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType()); + if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 0000000..a5637ae --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java @@ -0,0 +1,65 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.mapper.SysLogininforMapper; +import com.ruoyi.system.service.ISysLogininforService; + +/** + * ç³»ç»Ÿè®¿é—®æ—¥å¿—æƒ…å†µä¿¡æ¯ æœåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysLogininforServiceImpl implements ISysLogininforService +{ + + @Autowired + private SysLogininforMapper logininforMapper; + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + @Override + public void insertLogininfor(SysLogininfor logininfor) + { + logininforMapper.insertLogininfor(logininfor); + } + + /** + * æŸ¥è¯¢ç³»ç»Ÿç™»å½•æ—¥å¿—é›†åˆ + * + * @param logininfor 访问日志对象 + * @return ç™»å½•è®°å½•é›†åˆ + */ + @Override + public List selectLogininforList(SysLogininfor logininfor) + { + return logininforMapper.selectLogininforList(logininfor); + } + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿç™»å½•日志 + * + * @param infoIds 需è¦åˆ é™¤çš„登录日志ID + * @return 结果 + */ + @Override + public int deleteLogininforByIds(Long[] infoIds) + { + return logininforMapper.deleteLogininforByIds(infoIds); + } + + /** + * 清空系统登录日志 + */ + @Override + public void cleanLogininfor() + { + logininforMapper.cleanLogininfor(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..225c280 --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,531 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.vo.MetaVo; +import com.ruoyi.system.domain.vo.RouterVo; +import com.ruoyi.system.mapper.SysMenuMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.service.ISysMenuService; + +/** + * èœå• ä¸šåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysMenuServiceImpl implements ISysMenuService +{ + public static final String PREMISSION_STRING = "perms[\"{0}\"]"; + + @Autowired + private SysMenuMapper menuMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + /** + * æ ¹æ®ç”¨æˆ·æŸ¥è¯¢ç³»ç»Ÿèœå•列表 + * + * @param userId 用户ID + * @return èœå•列表 + */ + @Override + public List selectMenuList(Long userId) + { + return selectMenuList(new SysMenu(), userId); + } + + /** + * 查询系统èœå•列表 + * + * @param menu èœå•ä¿¡æ¯ + * @return èœå•列表 + */ + @Override + public List selectMenuList(SysMenu menu, Long userId) + { + List menuList = null; + // 管ç†å‘˜æ˜¾ç¤ºæ‰€æœ‰èœå•ä¿¡æ¯ + if (SysUser.isAdmin(userId)) + { + menuList = menuMapper.selectMenuList(menu); + } + else + { + menu.getParams().put("userId", userId); + menuList = menuMapper.selectMenuListByUserId(menu); + } + return menuList; + } + + /** + * æ ¹æ®ç”¨æˆ·ID查询æƒé™ + * + * @param userId 用户ID + * @return æƒé™åˆ—表 + */ + @Override + public Set selectMenuPermsByUserId(Long userId) + { + List perms = menuMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * æ ¹æ®è§’色ID查询æƒé™ + * + * @param roleId 角色ID + * @return æƒé™åˆ—表 + */ + @Override + public Set selectMenuPermsByRoleId(Long roleId) + { + List perms = menuMapper.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * æ ¹æ®ç”¨æˆ·ID查询èœå• + * + * @param userId 用户åç§° + * @return èœå•列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) + { + List menus = null; + if (SecurityUtils.isAdmin(userId)) + { + menus = menuMapper.selectMenuTreeAll(); + } + else + { + menus = menuMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + /** + * æ ¹æ®è§’色ID查询èœå•æ ‘ä¿¡æ¯ + * + * @param roleId 角色ID + * @return 选中èœå•列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + /** + * 构建å‰ç«¯è·¯ç”±æ‰€éœ€è¦çš„èœå• + * + * @param menus èœå•列表 + * @return 路由列表 + */ + @Override + public List buildMenus(List menus) + { + List routers = new LinkedList(); + for (SysMenu menu : menus) + { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setQuery(menu.getQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) + { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } + else if (isMenuFrame(menu)) + { + router.setMeta(null); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } + else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) + { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + String routerPath = innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 构建å‰ç«¯æ‰€éœ€è¦æ ‘结构 + * + * @param menus èœå•列表 + * @return 树结构列表 + */ + @Override + public List buildMenuTree(List menus) + { + List returnList = new ArrayList(); + List tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList()); + for (Iterator iterator = menus.iterator(); iterator.hasNext();) + { + SysMenu menu = (SysMenu) iterator.next(); + // 如果是顶级节点, é历该父节点的所有å­èŠ‚ç‚¹ + if (!tempList.contains(menu.getParentId())) + { + recursionFn(menus, menu); + returnList.add(menu); + } + } + if (returnList.isEmpty()) + { + returnList = menus; + } + return returnList; + } + + /** + * 构建å‰ç«¯æ‰€éœ€è¦ä¸‹æ‹‰æ ‘结构 + * + * @param menus èœå•列表 + * @return 下拉树结构列表 + */ + @Override + public List buildMenuTreeSelect(List menus) + { + List menuTrees = buildMenuTree(menus); + return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * æ ¹æ®èœå•IDæŸ¥è¯¢ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return èœå•ä¿¡æ¯ + */ + @Override + public SysMenu selectMenuById(Long menuId) + { + return menuMapper.selectMenuById(menuId); + } + + /** + * 是å¦å­˜åœ¨èœå•å­èŠ‚ç‚¹ + * + * @param menuId èœå•ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) + { + int result = menuMapper.hasChildByMenuId(menuId); + return result > 0; + } + + /** + * 查询èœå•ä½¿ç”¨æ•°é‡ + * + * @param menuId èœå•ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) + { + int result = roleMenuMapper.checkMenuExistRole(menuId); + return result > 0; + } + + /** + * 新增ä¿å­˜èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertMenu(SysMenu menu) + { + return menuMapper.insertMenu(menu); + } + + /** + * 修改ä¿å­˜èœå•ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateMenu(SysMenu menu) + { + return menuMapper.updateMenu(menu); + } + + /** + * 删除èœå•管ç†ä¿¡æ¯ + * + * @param menuId èœå•ID + * @return 结果 + */ + @Override + public int deleteMenuById(Long menuId) + { + return menuMapper.deleteMenuById(menuId); + } + + /** + * 校验èœå•å称是å¦å”¯ä¸€ + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkMenuNameUnique(SysMenu menu) + { + Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); + SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); + if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 获å–路由åç§° + * + * @param menu èœå•ä¿¡æ¯ + * @return 路由åç§° + */ + public String getRouteName(SysMenu menu) + { + String routerName = StringUtils.capitalize(menu.getPath()); + // éžå¤–链并且是一级目录(类型为目录) + if (isMenuFrame(menu)) + { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 获å–è·¯ç”±åœ°å€ + * + * @param menu èœå•ä¿¡æ¯ + * @return è·¯ç”±åœ°å€ + */ + public String getRouterPath(SysMenu menu) + { + String routerPath = menu.getPath(); + // å†…é“¾æ‰“å¼€å¤–ç½‘æ–¹å¼ + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + routerPath = innerLinkReplaceEach(routerPath); + } + // éžå¤–链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) + { + routerPath = "/" + menu.getPath(); + } + // éžå¤–链并且是一级目录(类型为èœå•) + else if (isMenuFrame(menu)) + { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获å–ç»„ä»¶ä¿¡æ¯ + * + * @param menu èœå•ä¿¡æ¯ + * @return ç»„ä»¶ä¿¡æ¯ + */ + public String getComponent(SysMenu menu) + { + String component = UserConstants.LAYOUT; + if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) + { + component = menu.getComponent(); + } + else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + component = UserConstants.INNER_LINK; + } + else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) + { + component = UserConstants.PARENT_VIEW; + } + return component; + } + + /** + * 是å¦ä¸ºèœå•内部跳转 + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public boolean isMenuFrame(SysMenu menu) + { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 是å¦ä¸ºå†…链组件 + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public boolean isInnerLink(SysMenu menu) + { + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); + } + + /** + * 是å¦ä¸ºparent_view组件 + * + * @param menu èœå•ä¿¡æ¯ + * @return 结果 + */ + public boolean isParentView(SysMenu menu) + { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * æ ¹æ®çˆ¶èŠ‚ç‚¹çš„IDèŽ·å–æ‰€æœ‰å­èŠ‚ç‚¹ + * + * @param list 分类表 + * @param parentId 传入的父节点ID + * @return String + */ + public List getChildPerms(List list, int parentId) + { + List returnList = new ArrayList(); + for (Iterator iterator = list.iterator(); iterator.hasNext();) + { + SysMenu t = (SysMenu) iterator.next(); + // ä¸€ã€æ ¹æ®ä¼ å…¥çš„æŸä¸ªçˆ¶èŠ‚ç‚¹ID,é历该父节点的所有å­èŠ‚ç‚¹ + if (t.getParentId() == parentId) + { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } + + /** + * 递归列表 + * + * @param list 分类表 + * @param t å­èŠ‚ç‚¹ + */ + private void recursionFn(List list, SysMenu t) + { + // 得到å­èŠ‚ç‚¹åˆ—è¡¨ + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysMenu tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到å­èŠ‚ç‚¹åˆ—è¡¨ + */ + private List getChildList(List list, SysMenu t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysMenu n = (SysMenu) it.next(); + if (n.getParentId().longValue() == t.getMenuId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * åˆ¤æ–­æ˜¯å¦æœ‰å­èŠ‚ç‚¹ + */ + private boolean hasChild(List list, SysMenu t) + { + return getChildList(list, t).size() > 0; + } + + /** + * 内链域åç‰¹æ®Šå­—ç¬¦æ›¿æ¢ + * + * @return 替æ¢åŽçš„内链域å + */ + public String innerLinkReplaceEach(String path) + { + return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." }, + new String[] { "", "", "", "/" }); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..8bebd9c --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.mapper.SysNoticeMapper; +import com.ruoyi.system.service.ISysNoticeService; + +/** + * 公告 æœåŠ¡å±‚å®žçŽ° + * + * @author ruoyi + */ +@Service +public class SysNoticeServiceImpl implements ISysNoticeService +{ + @Autowired + private SysNoticeMapper noticeMapper; + + /** + * æŸ¥è¯¢å…¬å‘Šä¿¡æ¯ + * + * @param noticeId 公告ID + * @return å…¬å‘Šä¿¡æ¯ + */ + @Override + public SysNotice selectNoticeById(Long noticeId) + { + return noticeMapper.selectNoticeById(noticeId); + } + + /** + * 查询公告列表 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return å…¬å‘Šé›†åˆ + */ + @Override + public List selectNoticeList(SysNotice notice) + { + return noticeMapper.selectNoticeList(notice); + } + + /** + * 新增公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertNotice(SysNotice notice) + { + return noticeMapper.insertNotice(notice); + } + + /** + * 修改公告 + * + * @param notice å…¬å‘Šä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateNotice(SysNotice notice) + { + return noticeMapper.updateNotice(notice); + } + + /** + * 删除公告对象 + * + * @param noticeId 公告ID + * @return 结果 + */ + @Override + public int deleteNoticeById(Long noticeId) + { + return noticeMapper.deleteNoticeById(noticeId); + } + + /** + * 批é‡åˆ é™¤å…¬å‘Šä¿¡æ¯ + * + * @param noticeIds 需è¦åˆ é™¤çš„公告ID + * @return 结果 + */ + @Override + public int deleteNoticeByIds(Long[] noticeIds) + { + return noticeMapper.deleteNoticeByIds(noticeIds); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 0000000..785ee1e --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java @@ -0,0 +1,76 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.mapper.SysOperLogMapper; +import com.ruoyi.system.service.ISysOperLogService; + +/** + * æ“作日志 æœåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysOperLogServiceImpl implements ISysOperLogService +{ + @Autowired + private SysOperLogMapper operLogMapper; + + /** + * 新增æ“作日志 + * + * @param operLog æ“作日志对象 + */ + @Override + public void insertOperlog(SysOperLog operLog) + { + operLogMapper.insertOperlog(operLog); + } + + /** + * 查询系统æ“ä½œæ—¥å¿—é›†åˆ + * + * @param operLog æ“作日志对象 + * @return æ“ä½œæ—¥å¿—é›†åˆ + */ + @Override + public List selectOperLogList(SysOperLog operLog) + { + return operLogMapper.selectOperLogList(operLog); + } + + /** + * 批é‡åˆ é™¤ç³»ç»Ÿæ“作日志 + * + * @param operIds 需è¦åˆ é™¤çš„æ“ä½œæ—¥å¿—ID + * @return 结果 + */ + @Override + public int deleteOperLogByIds(Long[] operIds) + { + return operLogMapper.deleteOperLogByIds(operIds); + } + + /** + * 查询æ“作日志详细 + * + * @param operId æ“作ID + * @return æ“作日志对象 + */ + @Override + public SysOperLog selectOperLogById(Long operId) + { + return operLogMapper.selectOperLogById(operId); + } + + /** + * 清空æ“作日志 + */ + @Override + public void cleanOperLog() + { + operLogMapper.cleanOperLog(); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..57995eb --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java @@ -0,0 +1,178 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.service.ISysPostService; + +/** + * å²—ä½ä¿¡æ¯ æœåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysPostServiceImpl implements ISysPostService +{ + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + /** + * 查询岗ä½ä¿¡æ¯é›†åˆ + * + * @param post å²—ä½ä¿¡æ¯ + * @return å²—ä½ä¿¡æ¯é›†åˆ + */ + @Override + public List selectPostList(SysPost post) + { + return postMapper.selectPostList(post); + } + + /** + * æŸ¥è¯¢æ‰€æœ‰å²—ä½ + * + * @return å²—ä½åˆ—表 + */ + @Override + public List selectPostAll() + { + return postMapper.selectPostAll(); + } + + /** + * 通过岗ä½ID查询岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysPost selectPostById(Long postId) + { + return postMapper.selectPostById(postId); + } + + /** + * æ ¹æ®ç”¨æˆ·ID获å–å²—ä½é€‰æ‹©æ¡†åˆ—表 + * + * @param userId 用户ID + * @return 选中岗ä½ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) + { + return postMapper.selectPostListByUserId(userId); + } + + /** + * 校验岗ä½å称是å¦å”¯ä¸€ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkPostNameUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostNameUnique(post.getPostName()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验岗ä½ç¼–ç æ˜¯å¦å”¯ä¸€ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkPostCodeUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostCodeUnique(post.getPostCode()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 通过岗ä½ID查询岗ä½ä½¿ç”¨æ•°é‡ + * + * @param postId å²—ä½ID + * @return 结果 + */ + @Override + public int countUserPostById(Long postId) + { + return userPostMapper.countUserPostById(postId); + } + + /** + * 删除岗ä½ä¿¡æ¯ + * + * @param postId å²—ä½ID + * @return 结果 + */ + @Override + public int deletePostById(Long postId) + { + return postMapper.deletePostById(postId); + } + + /** + * 批é‡åˆ é™¤å²—ä½ä¿¡æ¯ + * + * @param postIds 需è¦åˆ é™¤çš„å²—ä½ID + * @return 结果 + */ + @Override + public int deletePostByIds(Long[] postIds) + { + for (Long postId : postIds) + { + SysPost post = selectPostById(postId); + if (countUserPostById(postId) > 0) + { + throw new ServiceException(String.format("%1$s已分é…,ä¸èƒ½åˆ é™¤", post.getPostName())); + } + } + return postMapper.deletePostByIds(postIds); + } + + /** + * 新增ä¿å­˜å²—ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + @Override + public int insertPost(SysPost post) + { + return postMapper.insertPost(post); + } + + /** + * 修改ä¿å­˜å²—ä½ä¿¡æ¯ + * + * @param post å²—ä½ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updatePost(SysPost post) + { + return postMapper.updatePost(post); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..5e0a02d --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,424 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysRoleDept; +import com.ruoyi.system.domain.SysRoleMenu; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.SysRoleDeptMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysRoleService; + +/** + * 角色 ä¸šåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysRoleServiceImpl implements ISysRoleService +{ + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysRoleDeptMapper roleDeptMapper; + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢è§’è‰²æ•°æ® + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 角色数æ®é›†åˆä¿¡æ¯ + */ + @Override + @DataScope(deptAlias = "d") + public List selectRoleList(SysRole role) + { + return roleMapper.selectRoleList(role); + } + + /** + * æ ¹æ®ç”¨æˆ·ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) + { + List userRoles = roleMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRole role : roles) + { + for (SysRole userRole : userRoles) + { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) + { + role.setFlag(true); + break; + } + } + } + return roles; + } + + /** + * æ ¹æ®ç”¨æˆ·ID查询æƒé™ + * + * @param userId 用户ID + * @return æƒé™åˆ—表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) + { + List perms = roleMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRole perm : perms) + { + if (StringUtils.isNotNull(perm)) + { + permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + @Override + public List selectRoleAll() + { + return SpringUtils.getAopProxy(this).selectRoleList(new SysRole()); + } + + /** + * æ ¹æ®ç”¨æˆ·ID获å–角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) + { + return roleMapper.selectRoleListByUserId(userId); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return è§’è‰²å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysRole selectRoleById(Long roleId) + { + return roleMapper.selectRoleById(roleId); + } + + /** + * 校验角色å称是å¦å”¯ä¸€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkRoleNameUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色æƒé™æ˜¯å¦å”¯ä¸€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkRoleKeyUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色是å¦å…许æ“作 + * + * @param role è§’è‰²ä¿¡æ¯ + */ + @Override + public void checkRoleAllowed(SysRole role) + { + if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) + { + throw new ServiceException("ä¸å…许æ“作超级管ç†å‘˜è§’色"); + } + } + + /** + * æ ¡éªŒè§’è‰²æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param roleId 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysRole role = new SysRole(); + role.setRoleId(roleId); + List roles = SpringUtils.getAopProxy(this).selectRoleList(role); + if (StringUtils.isEmpty(roles)) + { + throw new ServiceException("没有æƒé™è®¿é—®è§’色数æ®ï¼"); + } + } + } + + /** + * 通过角色IDæŸ¥è¯¢è§’è‰²ä½¿ç”¨æ•°é‡ + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public int countUserRoleByRoleId(Long roleId) + { + return userRoleMapper.countUserRoleByRoleId(roleId); + } + + /** + * 新增ä¿å­˜è§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int insertRole(SysRole role) + { + // æ–°å¢žè§’è‰²ä¿¡æ¯ + roleMapper.insertRole(role); + return insertRoleMenu(role); + } + + /** + * 修改ä¿å­˜è§’è‰²ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int updateRole(SysRole role) + { + // ä¿®æ”¹è§’è‰²ä¿¡æ¯ + roleMapper.updateRole(role); + // 删除角色与èœå•å…³è” + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + return insertRoleMenu(role); + } + + /** + * ä¿®æ”¹è§’è‰²çŠ¶æ€ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateRoleStatus(SysRole role) + { + return roleMapper.updateRole(role); + } + + /** + * ä¿®æ”¹æ•°æ®æƒé™ä¿¡æ¯ + * + * @param role è§’è‰²ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int authDataScope(SysRole role) + { + // ä¿®æ”¹è§’è‰²ä¿¡æ¯ + roleMapper.updateRole(role); + // åˆ é™¤è§’è‰²ä¸Žéƒ¨é—¨å…³è” + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信æ¯ï¼ˆæ•°æ®æƒé™ï¼‰ + return insertRoleDept(role); + } + + /** + * 新增角色èœå•ä¿¡æ¯ + * + * @param role 角色对象 + */ + public int insertRoleMenu(SysRole role) + { + int rows = 1; + // æ–°å¢žç”¨æˆ·ä¸Žè§’è‰²ç®¡ç† + List list = new ArrayList(); + for (Long menuId : role.getMenuIds()) + { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) + { + rows = roleMenuMapper.batchRoleMenu(list); + } + return rows; + } + + /** + * 新增角色部门信æ¯(æ•°æ®æƒé™) + * + * @param role 角色对象 + */ + public int insertRoleDept(SysRole role) + { + int rows = 1; + // æ–°å¢žè§’è‰²ä¸Žéƒ¨é—¨ï¼ˆæ•°æ®æƒé™ï¼‰ç®¡ç† + List list = new ArrayList(); + for (Long deptId : role.getDeptIds()) + { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) + { + rows = roleDeptMapper.batchRoleDept(list); + } + return rows; + } + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleById(Long roleId) + { + // 删除角色与èœå•å…³è” + roleMenuMapper.deleteRoleMenuByRoleId(roleId); + // åˆ é™¤è§’è‰²ä¸Žéƒ¨é—¨å…³è” + roleDeptMapper.deleteRoleDeptByRoleId(roleId); + return roleMapper.deleteRoleById(roleId); + } + + /** + * 批é‡åˆ é™¤è§’è‰²ä¿¡æ¯ + * + * @param roleIds 需è¦åˆ é™¤çš„角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleByIds(Long[] roleIds) + { + for (Long roleId : roleIds) + { + checkRoleAllowed(new SysRole(roleId)); + checkRoleDataScope(roleId); + SysRole role = selectRoleById(roleId); + if (countUserRoleByRoleId(roleId) > 0) + { + throw new ServiceException(String.format("%1$s已分é…,ä¸èƒ½åˆ é™¤", role.getRoleName())); + } + } + // 删除角色与èœå•å…³è” + roleMenuMapper.deleteRoleMenu(roleIds); + // åˆ é™¤è§’è‰²ä¸Žéƒ¨é—¨å…³è” + roleDeptMapper.deleteRoleDept(roleIds); + return roleMapper.deleteRoleByIds(roleIds); + } + + /** + * å–æ¶ˆæŽˆæƒç”¨æˆ·è§’色 + * + * @param userRole 用户和角色关è”ä¿¡æ¯ + * @return 结果 + */ + @Override + public int deleteAuthUser(SysUserRole userRole) + { + return userRoleMapper.deleteUserRoleInfo(userRole); + } + + /** + * 批é‡å–消授æƒç”¨æˆ·è§’色 + * + * @param roleId 角色ID + * @param userIds 需è¦å–消授æƒçš„用户数æ®ID + * @return 结果 + */ + @Override + public int deleteAuthUsers(Long roleId, Long[] userIds) + { + return userRoleMapper.deleteUserRoleInfos(roleId, userIds); + } + + /** + * 批é‡é€‰æ‹©æŽˆæƒç”¨æˆ·è§’色 + * + * @param roleId 角色ID + * @param userIds éœ€è¦æŽˆæƒçš„用户数æ®ID + * @return 结果 + */ + @Override + public int insertAuthUsers(Long roleId, Long[] userIds) + { + // æ–°å¢žç”¨æˆ·ä¸Žè§’è‰²ç®¡ç† + List list = new ArrayList(); + for (Long userId : userIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + return userRoleMapper.batchUserRole(list); + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java new file mode 100644 index 0000000..347837b --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; + +/** + * 在线用户 æœåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +public class SysUserOnlineServiceImpl implements ISysUserOnlineService +{ + /** + * é€šè¿‡ç™»å½•åœ°å€æŸ¥è¯¢ä¿¡æ¯ + * + * @param ipaddr ç™»å½•åœ°å€ + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + @Override + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过用户åç§°æŸ¥è¯¢ä¿¡æ¯ + * + * @param userName 用户åç§° + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + @Override + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user) + { + if (StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过登录地å€/用户åç§°æŸ¥è¯¢ä¿¡æ¯ + * + * @param ipaddr ç™»å½•åœ°å€ + * @param userName 用户åç§° + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + */ + @Override + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * è®¾ç½®åœ¨çº¿ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 在线用户 + */ + @Override + public SysUserOnline loginUserToUserOnline(LoginUser user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) + { + return null; + } + SysUserOnline sysUserOnline = new SysUserOnline(); + sysUserOnline.setTokenId(user.getToken()); + sysUserOnline.setUserName(user.getUsername()); + sysUserOnline.setIpaddr(user.getIpaddr()); + sysUserOnline.setLoginLocation(user.getLoginLocation()); + sysUserOnline.setBrowser(user.getBrowser()); + sysUserOnline.setOs(user.getOs()); + sysUserOnline.setLoginTime(user.getLoginTime()); + if (StringUtils.isNotNull(user.getUser().getDept())) + { + sysUserOnline.setDeptName(user.getUser().getDept().getDeptName()); + } + return sysUserOnline; + } +} diff --git a/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..37e84bf --- /dev/null +++ b/examapi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,558 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Validator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanValidators; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.domain.SysUserPost; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; +import org.springframework.context.annotation.Configuration; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; + +/** + * 用户 ä¸šåŠ¡å±‚å¤„ç† + * + * @author ruoyi + */ +@Service +@Configuration +public class SysUserServiceImpl implements ISysUserService +{ + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); + + @Autowired + private SysUserMapper userMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + @Autowired + private ISysConfigService configService; + + @Autowired + protected Validator validator; + + @Bean + public Validator getValidator() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + return factory.getValidator(); + } + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢ç”¨æˆ·åˆ—表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) + { + return userMapper.selectUserList(user); + } + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢å·²åˆ†é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectAllocatedList(SysUser user) + { + return userMapper.selectAllocatedList(user); + } + + /** + * æ ¹æ®æ¡ä»¶åˆ†é¡µæŸ¥è¯¢æœªåˆ†é…用户角色列表 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 用户信æ¯é›†åˆä¿¡æ¯ + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUnallocatedList(SysUser user) + { + return userMapper.selectUnallocatedList(user); + } + + /** + * é€šè¿‡ç”¨æˆ·åæŸ¥è¯¢ç”¨æˆ· + * + * @param userName 用户å + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysUser selectUserByUserName(String userName) + { + return userMapper.selectUserByUserName(userName); + } + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return ç”¨æˆ·å¯¹è±¡ä¿¡æ¯ + */ + @Override + public SysUser selectUserById(Long userId) + { + return userMapper.selectUserById(userId); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户å + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) + { + List list = roleMapper.selectRolesByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); + } + + /** + * 查询用户所属岗ä½ç»„ + * + * @param userName 用户å + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) + { + List list = postMapper.selectPostsByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); + } + + /** + * 校验用户å称是å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean checkUserNameUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkUserNameUnique(user.getUserName()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验手机å·ç æ˜¯å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return + */ + @Override + public boolean checkPhoneUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验email是å¦å”¯ä¸€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return + */ + @Override + public boolean checkEmailUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkEmailUnique(user.getEmail()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验用户是å¦å…许æ“作 + * + * @param user ç”¨æˆ·ä¿¡æ¯ + */ + @Override + public void checkUserAllowed(SysUser user) + { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) + { + throw new ServiceException("ä¸å…许æ“作超级管ç†å‘˜ç”¨æˆ·"); + } + } + + /** + * æ ¡éªŒç”¨æˆ·æ˜¯å¦æœ‰æ•°æ®æƒé™ + * + * @param userId 用户id + */ + @Override + public void checkUserDataScope(Long userId) + { + if (StringUtils.isNotNull(userId)) + { + SysUser user = new SysUser(); + user.setUserId(userId); + List users = SpringUtils.getAopProxy(this).selectUserList(user); + if (StringUtils.isEmpty(users)) + { + throw new ServiceException("没有æƒé™è®¿é—®ç”¨æˆ·æ•°æ®ï¼"); + } + } + } + + /** + * 新增ä¿å­˜ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int insertUser(SysUser user) + { + // æ–°å¢žç”¨æˆ·ä¿¡æ¯ + int rows = userMapper.insertUser(user); + // 新增用户岗ä½å…³è” + insertUserPost(user); + // æ–°å¢žç”¨æˆ·ä¸Žè§’è‰²ç®¡ç† + insertUserRole(user); + return rows; + } + + /** + * æ³¨å†Œç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + public boolean registerUser(SysUser user) + { + return userMapper.insertUser(user) > 0; + } + + /** + * 修改ä¿å­˜ç”¨æˆ·ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + @Transactional + public int updateUser(SysUser user) + { + Long userId = user.getUserId(); + // åˆ é™¤ç”¨æˆ·ä¸Žè§’è‰²å…³è” + userRoleMapper.deleteUserRoleByUserId(userId); + // æ–°å¢žç”¨æˆ·ä¸Žè§’è‰²ç®¡ç† + insertUserRole(user); + // 删除用户与岗ä½å…³è” + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗ä½ç®¡ç† + insertUserPost(user); + return userMapper.updateUser(user); + } + + /** + * 用户授æƒè§’色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Override + @Transactional + public void insertUserAuth(Long userId, Long[] roleIds) + { + userRoleMapper.deleteUserRoleByUserId(userId); + insertUserRole(userId, roleIds); + } + + /** + * ä¿®æ”¹ç”¨æˆ·çŠ¶æ€ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateUserStatus(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * ä¿®æ”¹ç”¨æˆ·åŸºæœ¬ä¿¡æ¯ + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + public int updateUserProfile(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * ä¿®æ”¹ç”¨æˆ·å¤´åƒ + * + * @param userName 用户å + * @param avatar 头åƒåœ°å€ + * @return 结果 + */ + @Override + public boolean updateUserAvatar(String userName, String avatar) + { + return userMapper.updateUserAvatar(userName, avatar) > 0; + } + + /** + * é‡ç½®ç”¨æˆ·å¯†ç  + * + * @param user ç”¨æˆ·ä¿¡æ¯ + * @return 结果 + */ + @Override + public int resetPwd(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * é‡ç½®ç”¨æˆ·å¯†ç  + * + * @param userName 用户å + * @param password å¯†ç  + * @return 结果 + */ + @Override + public int resetUserPwd(String userName, String password) + { + return userMapper.resetUserPwd(userName, password); + } + + /** + * æ–°å¢žç”¨æˆ·è§’è‰²ä¿¡æ¯ + * + * @param user 用户对象 + */ + public void insertUserRole(SysUser user) + { + this.insertUserRole(user.getUserId(), user.getRoleIds()); + } + + /** + * 新增用户岗ä½ä¿¡æ¯ + * + * @param user 用户对象 + */ + public void insertUserPost(SysUser user) + { + Long[] posts = user.getPostIds(); + if (StringUtils.isNotNull(posts)) + { + // 新增用户与岗ä½ç®¡ç† + List list = new ArrayList(); + for (Long postId : posts) + { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + if (list.size() > 0) + { + userPostMapper.batchUserPost(list); + } + } + } + + /** + * æ–°å¢žç”¨æˆ·è§’è‰²ä¿¡æ¯ + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserRole(Long userId, Long[] roleIds) + { + if (StringUtils.isNotNull(roleIds)) + { + // æ–°å¢žç”¨æˆ·ä¸Žè§’è‰²ç®¡ç† + List list = new ArrayList(roleIds.length); + for (Long roleId : roleIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + userRoleMapper.batchUserRole(list); + } + } + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserById(Long userId) + { + // åˆ é™¤ç”¨æˆ·ä¸Žè§’è‰²å…³è” + userRoleMapper.deleteUserRoleByUserId(userId); + // 删除用户与岗ä½è¡¨ + userPostMapper.deleteUserPostByUserId(userId); + return userMapper.deleteUserById(userId); + } + + /** + * 批é‡åˆ é™¤ç”¨æˆ·ä¿¡æ¯ + * + * @param userIds 需è¦åˆ é™¤çš„用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserByIds(Long[] userIds) + { + for (Long userId : userIds) + { + checkUserAllowed(new SysUser(userId)); + checkUserDataScope(userId); + } + // åˆ é™¤ç”¨æˆ·ä¸Žè§’è‰²å…³è” + userRoleMapper.deleteUserRole(userIds); + // 删除用户与岗ä½å…³è” + userPostMapper.deleteUserPost(userIds); + return userMapper.deleteUserByIds(userIds); + } + + /** + * å¯¼å…¥ç”¨æˆ·æ•°æ® + * + * @param userList 用户数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + @Override + public String importUser(List userList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(userList) || userList.size() == 0) + { + throw new ServiceException("导入用户数æ®ä¸èƒ½ä¸ºç©ºï¼"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + String password = configService.selectConfigByKey("sys.user.initPassword"); + for (SysUser user : userList) + { + try + { + // éªŒè¯æ˜¯å¦å­˜åœ¨è¿™ä¸ªç”¨æˆ· + SysUser u = userMapper.selectUserByUserName(user.getUserName()); + if (StringUtils.isNull(u)) + { + BeanValidators.validateWithException(validator, user); + user.setPassword(SecurityUtils.encryptPassword(password)); + user.setCreateBy(operName); + userMapper.insertUser(user); + successNum++; + successMsg.append("
" + successNum + "ã€è´¦å· " + user.getUserName() + " 导入æˆåŠŸ"); + } + else if (isUpdateSupport) + { + BeanValidators.validateWithException(validator, user); + checkUserAllowed(u); + checkUserDataScope(u.getUserId()); + user.setUserId(u.getUserId()); + user.setUpdateBy(operName); + userMapper.updateUser(user); + successNum++; + successMsg.append("
" + successNum + "ã€è´¦å· " + user.getUserName() + " æ›´æ–°æˆåŠŸ"); + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "ã€è´¦å· " + user.getUserName() + " 已存在"); + } + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "ã€è´¦å· " + user.getUserName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + log.error(msg, e); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败ï¼å…± " + failureNum + " æ¡æ•°æ®æ ¼å¼ä¸æ­£ç¡®ï¼Œé”™è¯¯å¦‚下:"); + throw new ServiceException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "æ­å–œæ‚¨ï¼Œæ•°æ®å·²å…¨éƒ¨å¯¼å…¥æˆåŠŸï¼å…± " + successNum + " æ¡ï¼Œæ•°æ®å¦‚下:"); + } + return successMsg.toString(); + } +} \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml new file mode 100644 index 0000000..e99c732 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark + from sys_config + + + + + + + and config_id = #{configId} + + + and config_key = #{configKey} + + + + + + + + + + + + + + insert into sys_config ( + config_name, + config_key, + config_value, + config_type, + create_by, + remark, + create_time + )values( + #{configName}, + #{configKey}, + #{configValue}, + #{configType}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_config + + config_name = #{configName}, + config_key = #{configKey}, + config_value = #{configValue}, + config_type = #{configType}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where config_id = #{configId} + + + + delete from sys_config where config_id = #{configId} + + + + delete from sys_config where config_id in + + #{configId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml new file mode 100644 index 0000000..16fd511 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time + from sys_dept d + + + + + + + + + + + + + + + + + + + + insert into sys_dept( + dept_id, + parent_id, + dept_name, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values( + #{deptId}, + #{parentId}, + #{deptName}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate() + ) + + + + update sys_dept + + parent_id = #{parentId}, + dept_name = #{deptName}, + ancestors = #{ancestors}, + order_num = #{orderNum}, + leader = #{leader}, + phone = #{phone}, + email = #{email}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where dept_id = #{deptId} + + + + update sys_dept set ancestors = + + when #{item.deptId} then #{item.ancestors} + + where dept_id in + + #{item.deptId} + + + + + update sys_dept set status = '0' where dept_id in + + #{deptId} + + + + + update sys_dept set del_flag = '2' where dept_id = #{deptId} + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml new file mode 100644 index 0000000..15c7d46 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark + from sys_dict_data + + + + + + + + + + + + + + delete from sys_dict_data where dict_code = #{dictCode} + + + + delete from sys_dict_data where dict_code in + + #{dictCode} + + + + + update sys_dict_data + + dict_sort = #{dictSort}, + dict_label = #{dictLabel}, + dict_value = #{dictValue}, + dict_type = #{dictType}, + css_class = #{cssClass}, + list_class = #{listClass}, + is_default = #{isDefault}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_code = #{dictCode} + + + + update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType} + + + + insert into sys_dict_data( + dict_sort, + dict_label, + dict_value, + dict_type, + css_class, + list_class, + is_default, + status, + remark, + create_by, + create_time + )values( + #{dictSort}, + #{dictLabel}, + #{dictValue}, + #{dictType}, + #{cssClass}, + #{listClass}, + #{isDefault}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml new file mode 100644 index 0000000..b625ddd --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + select dict_id, dict_name, dict_type, status, create_by, create_time, remark + from sys_dict_type + + + + + + + + + + + + + + delete from sys_dict_type where dict_id = #{dictId} + + + + delete from sys_dict_type where dict_id in + + #{dictId} + + + + + update sys_dict_type + + dict_name = #{dictName}, + dict_type = #{dictType}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_id = #{dictId} + + + + insert into sys_dict_type( + dict_name, + dict_type, + status, + remark, + create_by, + create_time + )values( + #{dictName}, + #{dictType}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml new file mode 100644 index 0000000..ebd0d97 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time) + values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate()) + + + + + + delete from sys_logininfor where info_id in + + #{infoId} + + + + + truncate table sys_logininfor + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml new file mode 100644 index 0000000..f009519 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select menu_id, menu_name, parent_id, order_num, path, component, `query`, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time + from sys_menu + + + + + + + + + + + + + + + + + + + + + + + + + + update sys_menu + + menu_name = #{menuName}, + parent_id = #{parentId}, + order_num = #{orderNum}, + path = #{path}, + component = #{component}, + `query` = #{query}, + is_frame = #{isFrame}, + is_cache = #{isCache}, + menu_type = #{menuType}, + visible = #{visible}, + status = #{status}, + perms = #{perms}, + icon = #{icon}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where menu_id = #{menuId} + + + + insert into sys_menu( + menu_id, + parent_id, + menu_name, + order_num, + path, + component, + `query`, + is_frame, + is_cache, + menu_type, + visible, + status, + perms, + icon, + remark, + create_by, + create_time + )values( + #{menuId}, + #{parentId}, + #{menuName}, + #{orderNum}, + #{path}, + #{component}, + #{query}, + #{isFrame}, + #{isCache}, + #{menuType}, + #{visible}, + #{status}, + #{perms}, + #{icon}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_menu where menu_id = #{menuId} + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml new file mode 100644 index 0000000..b633cdc --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark + from sys_notice + + + + + + + + insert into sys_notice ( + notice_title, + notice_type, + notice_content, + status, + remark, + create_by, + create_time + )values( + #{noticeTitle}, + #{noticeType}, + #{noticeContent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_notice + + notice_title = #{noticeTitle}, + notice_type = #{noticeType}, + notice_content = #{noticeContent}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id in + + #{noticeId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml new file mode 100644 index 0000000..d0b8719 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time, cost_time + from sys_oper_log + + + + insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time) + values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, #{costTime}, sysdate()) + + + + + + delete from sys_oper_log where oper_id in + + #{operId} + + + + + + + truncate table sys_oper_log + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml new file mode 100644 index 0000000..5f56a88 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark + from sys_post + + + + + + + + + + + + + + + + delete from sys_post where post_id = #{postId} + + + + delete from sys_post where post_id in + + #{postId} + + + + + update sys_post + + post_code = #{postCode}, + post_name = #{postName}, + post_sort = #{postSort}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where post_id = #{postId} + + + + insert into sys_post( + post_id, + post_code, + post_name, + post_sort, + status, + remark, + create_by, + create_time + )values( + #{postId}, + #{postCode}, + #{postName}, + #{postSort}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml new file mode 100644 index 0000000..bcb7174 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_role_dept where role_id=#{roleId} + + + + + + delete from sys_role_dept where role_id in + + #{roleId} + + + + + insert into sys_role_dept(role_id, dept_id) values + + (#{item.roleId},#{item.deptId}) + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml new file mode 100644 index 0000000..d2add06 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly, + r.status, r.del_flag, r.create_time, r.remark + from sys_role r + left join sys_user_role ur on ur.role_id = r.role_id + left join sys_user u on u.user_id = ur.user_id + left join sys_dept d on u.dept_id = d.dept_id + + + + + + + + + + + + + + + + + + + + insert into sys_role( + role_id, + role_name, + role_key, + role_sort, + data_scope, + menu_check_strictly, + dept_check_strictly, + status, + remark, + create_by, + create_time + )values( + #{roleId}, + #{roleName}, + #{roleKey}, + #{roleSort}, + #{dataScope}, + #{menuCheckStrictly}, + #{deptCheckStrictly}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_role + + role_name = #{roleName}, + role_key = #{roleKey}, + role_sort = #{roleSort}, + data_scope = #{dataScope}, + menu_check_strictly = #{menuCheckStrictly}, + dept_check_strictly = #{deptCheckStrictly}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id in + + #{roleId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml new file mode 100644 index 0000000..387dd80 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_role_menu where role_id=#{roleId} + + + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + insert into sys_role_menu(role_id, menu_id) values + + (#{item.roleId},#{item.menuId}) + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml new file mode 100644 index 0000000..ced92c4 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, u.user_code,u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, + d.dept_id, d.parent_id, d.dept_name, d.order_num, d.leader, d.status as dept_status, + r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status + from sys_user u + left join sys_dept d on u.dept_id = d.dept_id + left join sys_user_role ur on u.user_id = ur.user_id + left join sys_role r on r.role_id = ur.role_id + + + + + + + + + + + + update sys_user + + wechat_openid = #{wechatOpenid}, + wechat_unionid = #{wechatUnionid}, + wechat_nickname = #{wechatNickname}, + wechat_avatar = #{wechatAvatar}, + bind_wechat = #{bindWechat}, + update_time = now() + + where user_id = #{userId} + + + + + + + + + + + + + + + + insert into sys_user( + dept_id, + user_name, + user_code, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + del_flag, + create_by, + remark, + create_time + )values( + #{deptId}, + #{userName}, + #{userCode}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + '0', + #{createBy}, + #{remark}, + now() + ) + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = now() + + where user_id = #{userId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + update sys_user set avatar = #{avatar} where user_name = #{userName} + + + + update sys_user set password = #{password} where user_name = #{userName} + + + + delete from sys_user where user_id = #{userId} + + + + delete from sys_user where user_id in + + #{userId} + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml new file mode 100644 index 0000000..989c102 --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_user_post where user_id=#{userId} + + + + + + delete from sys_user_post where user_id in + + #{userId} + + + + + insert into sys_user_post(user_id, post_id) values + + (#{item.userId},#{item.postId}) + + + + \ No newline at end of file diff --git a/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..29f926a --- /dev/null +++ b/examapi/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + delete from sys_user_role where user_id=#{userId} + + + + + + delete from sys_user_role where user_id in + + #{userId} + + + + + insert into sys_user_role(user_id, role_id) values + + (#{item.userId},#{item.roleId}) + + + + + delete from sys_user_role where user_id=#{userId} and role_id=#{roleId} + + + + delete from sys_user_role where role_id=#{roleId} and user_id in + + #{userId} + + + \ No newline at end of file diff --git a/examapi/ry.bat b/examapi/ry.bat new file mode 100644 index 0000000..69abee7 --- /dev/null +++ b/examapi/ry.bat @@ -0,0 +1,67 @@ +@echo off + +rem jarƽ¼¶Ä¿Â¼ +set AppName=ruoyi-admin.jar + +rem JVM²ÎÊý +set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" + + +ECHO. + ECHO. [1] Æô¶¯%AppName% + ECHO. [2] ¹Ø±Õ%AppName% + ECHO. [3] ÖØÆô%AppName% + ECHO. [4] Æô¶¯×´Ì¬ %AppName% + ECHO. [5] ÍË ³ö +ECHO. + +ECHO.ÇëÊäÈëÑ¡ÔñÏîÄ¿µÄÐòºÅ: +set /p ID= + IF "%id%"=="1" GOTO start + IF "%id%"=="2" GOTO stop + IF "%id%"=="3" GOTO restart + IF "%id%"=="4" GOTO status + IF "%id%"=="5" EXIT +PAUSE +:start + for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( + set pid=%%a + set image_name=%%b + ) + if defined pid ( + echo %%is running + PAUSE + ) + +start javaw %JVM_OPTS% -jar %AppName% + +echo starting¡­¡­ +echo Start %AppName% success... +goto:eof + +rem º¯Êýstopͨ¹ýjpsÃüÁî²éÕÒpid²¢½áÊø½ø³Ì +:stop + for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( + set pid=%%a + set image_name=%%b + ) + if not defined pid (echo process %AppName% does not exists) else ( + echo prepare to kill %image_name% + echo start kill %pid% ... + rem ¸ù¾Ý½ø³ÌID£¬kill½ø³Ì + taskkill /f /pid %pid% + ) +goto:eof +:restart + call :stop + call :start +goto:eof +:status + for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( + set pid=%%a + set image_name=%%b + ) + if not defined pid (echo process %AppName% is dead ) else ( + echo %image_name% is running + ) +goto:eof diff --git a/examapi/ry.sh b/examapi/ry.sh new file mode 100755 index 0000000..d6a9cf3 --- /dev/null +++ b/examapi/ry.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# ./ry.sh start å¯åЍ stop åœæ­¢ restart é‡å¯ status çŠ¶æ€ +AppName=ruoyi-admin.jar + +# JVM傿•° +JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" +APP_HOME=`pwd` +LOG_PATH=$APP_HOME/logs/$AppName.log + +if [ "$1" = "" ]; +then + echo -e "\033[0;31m 未输入æ“作å \033[0m \033[0;34m {start|stop|restart|status} \033[0m" + exit 1 +fi + +if [ "$AppName" = "" ]; +then + echo -e "\033[0;31m 未输入应用å \033[0m" + exit 1 +fi + +function start() +{ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` + + if [ x"$PID" != x"" ]; then + echo "$AppName is running..." + else + nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 & + echo "Start $AppName success..." + fi +} + +function stop() +{ + echo "Stop $AppName" + + PID="" + query(){ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` + } + + query + if [ x"$PID" != x"" ]; then + kill -TERM $PID + echo "$AppName (pid:$PID) exiting..." + while [ x"$PID" != x"" ] + do + sleep 1 + query + done + echo "$AppName exited." + else + echo "$AppName already stopped." + fi +} + +function restart() +{ + stop + sleep 2 + start +} + +function status() +{ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l` + if [ $PID != 0 ];then + echo "$AppName is running..." + else + echo "$AppName is not running..." + fi +} + +case $1 in + start) + start;; + stop) + stop;; + restart) + restart;; + status) + status;; + *) + +esac diff --git a/examapi/yanzhu-exam/pom.xml b/examapi/yanzhu-exam/pom.xml new file mode 100644 index 0000000..17ab25e --- /dev/null +++ b/examapi/yanzhu-exam/pom.xml @@ -0,0 +1,198 @@ + + 4.0.0 + + com.ruoyi + ruoyi + 3.8.6 + + yanzhu-exam + yanzhu-exam + 应用扩展包 + + 1.8 + 2.0.34 + 1.18.30 + 12.2.0.1.0 + 1.2.20 + 2.3.2 + 2.10.1 + 3.0.5 + 2.3.2 + 4.5.14 + 4.5.14 + 4.4.16 + 1.15 + 1.2 + 2.11.0 + 3.12.0 + 3.12.0 + 4.5.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson.version} + + + org.projectlombok + lombok + ${lombok.version} + + + com.google.code.gson + gson + ${gson.version} + + + cn.hutool + hutool-all + 5.8.25 + + + com.github.ulisesbocchio + jasypt-spring-boot-starter + ${jasypt.version} + + + + org.springframework + spring-context-support + + + + org.springframework + spring-tx + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.version} + + + + org.quartz-scheduler + quartz + ${quartz.version} + + + slf4j-api + org.slf4j + + + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + org.apache.httpcomponents + httpmime + ${httpmime.version} + + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + + + + com.thoughtworks.xstream + xstream + 1.4.20 + + + + + commons-io + commons-io + ${commons-io.version} + + + commons-lang + commons-lang + 2.6 + + + + + commons-codec + commons-codec + ${commons-codec.version} + + + + commons-logging + commons-logging + ${commons-logging.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + commons-fileupload + commons-fileupload + 1.4 + + + com.github.binarywang + weixin-java-cp + ${weixin-java-cp.version} + + + org.json + json + 20231013 + + + com.ruoyi + ruoyi-framework + + + com.ruoyi + ruoyi-system + + + com.ruoyi + ruoyi-common + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/DigitUtils.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/DigitUtils.java new file mode 100644 index 0000000..de2fe19 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/DigitUtils.java @@ -0,0 +1,31 @@ +package com.yanzhu.exam.cms.utils; + +public class DigitUtils { + + public static String toChinese(String str) { + //数字对应的汉字 + String[] num = {"一", "二", "三", "å››", "五", "å…­", "七", "å…«", "ä¹"}; + //å•ä½ + String[] unit = {"", "å", "百", "åƒ", "万", "å", "百", "åƒ", "亿", "å", "百", "åƒ", "万亿"}; + //将输入数字转æ¢ä¸ºå­—符串 + //将该字符串分割为数组存放 + char[] ch = str.toCharArray(); + //结果 字符串 + String result = ""; + int length = ch.length; + for (int i = 0; i < length; i++) { + int c = (int) ch[i] - 48; + if (c != 0) { + result += num[c - 1] + unit[length - i - 1]; + } + } + return result; + } + + public static void main(String[] args) { + + // 将字符串数字转化为汉字 + + toChinese("30"); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/FileUpload.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/FileUpload.java new file mode 100644 index 0000000..bd7341f --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/FileUpload.java @@ -0,0 +1,63 @@ +package com.yanzhu.exam.cms.utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.springframework.web.multipart.MultipartFile; + +public class FileUpload { + /** + * æ–‡ä»¶ä¸Šä¼ å¤„ç† + * + * @param file + * @return + */ + public static String writeUploadFile(MultipartFile file,String path) { + String filename = file.getOriginalFilename(); + System.out.println("原始文件å:" + filename); + File fileDir = new File(path); + if (!fileDir.exists()) + fileDir.mkdirs(); + + String extname = FilenameUtils.getExtension(filename); + String allowImgFormat = "gif,jpg,jpeg,png"; + if (!allowImgFormat.contains(extname.toLowerCase())) { + return "NOT_IMAGE"; + } + + filename = Math.abs(file.getOriginalFilename().hashCode()) + RandomUtils.createRandomString( 4 ) + "." + extname; + InputStream input = null; + FileOutputStream fos = null; + try { + input = file.getInputStream(); + fos = new FileOutputStream(path + "/" + filename); + IOUtils.copy(input, fos); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + } + return filename; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/RandomUtils.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/RandomUtils.java new file mode 100644 index 0000000..d7f7979 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/cms/utils/RandomUtils.java @@ -0,0 +1,35 @@ +package com.yanzhu.exam.cms.utils; + +public class RandomUtils { + private static final String charlist = "0123456789"; + + public static String createRandomString(int len) { + String str = new String(); + for (int i = 0; i < len; i++) { + str += charlist.charAt(getRandom(charlist.length())); + } + return str; + } + + public static int getRandom(int mod) { + if (mod < 1) { + return 0; + } + int ret = getInt() % mod; + return ret; + } + + private static int getInt() { + int ret = Math.abs(Long.valueOf(getRandomNumString()).intValue()); + return ret; + } + + private static String getRandomNumString() { + double d = Math.random(); + String dStr = String.valueOf(d).replaceAll("[^\\d]", ""); + if (dStr.length() > 1) { + dStr = dStr.substring(0, dStr.length() - 1); + } + return dStr; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskDataController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskDataController.java new file mode 100644 index 0000000..175fac7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskDataController.java @@ -0,0 +1,50 @@ +package com.yanzhu.exam.exam.controller; + +import org.springframework.beans.factory.annotation.Autowired; +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 com.yanzhu.exam.exam.domain.ExamTaskData; +import com.yanzhu.exam.exam.service.IExamTaskDataService; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; + +@RestController +@RequestMapping("/exam/examtask") +public class ExamTaskDataController extends BaseController{ + @Autowired + private IExamTaskDataService examTaskDataService; + + + @PostMapping("/save") + public AjaxResult save(@RequestBody ExamTaskData examTaskData) + { + // æ•°æ®åˆ¤æ–­ + if (examTaskData == null) { + return AjaxResult.error(-1, "传入数æ®ä¸ºç©º!"); + } + + if (examTaskData.getExamTaskManager() == null) { + return AjaxResult.error(-1, "传入任务属性信æ¯ä¸ºç©º!"); + } + + if (examTaskData.getTaskQuestionsList() == null || examTaskData.getTaskQuestionsList().size() == 0) { + return AjaxResult.error(-1, "传入题库信æ¯ä¸ºç©º!"); + } + + if (examTaskData.getTaskGroupList() == null || examTaskData.getTaskGroupList().size() == 0) { + return AjaxResult.error(-1, "传入人员分组信æ¯ä¸ºç©º!"); + } + + try + { + examTaskDataService.saveData(examTaskData); + } + catch(Exception e) { + return AjaxResult.error(-1, e.getMessage()); + } + return AjaxResult.success("ä¿å­˜æˆåŠŸ"); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskGroupController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskGroupController.java new file mode 100644 index 0000000..6fb9a41 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskGroupController.java @@ -0,0 +1,106 @@ +package com.yanzhu.exam.exam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.exam.domain.ExamTaskGroup; +import com.yanzhu.exam.exam.service.IExamTaskGroupService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 任务分组Controller + * + * @author qnsdt + * @date 2023-02-10 + */ +@RestController +@RequestMapping("/exam/taskgroup") +public class ExamTaskGroupController extends BaseController +{ + @Autowired + private IExamTaskGroupService examTaskGroupService; + + /** + * 查询任务分组列表 + */ + @GetMapping("/list") + public TableDataInfo list(ExamTaskGroup examTaskGroup) + { + startPage(); + List list = examTaskGroupService.selectExamTaskGroupList(examTaskGroup); + return getDataTable(list); + } + + /** + * 导出任务分组列表 + */ + @GetMapping("/export") + public AjaxResult export(ExamTaskGroup examTaskGroup) + { + List list = examTaskGroupService.selectExamTaskGroupList(examTaskGroup); + ExcelUtil util = new ExcelUtil(ExamTaskGroup.class); + return util.exportExcel(list, "任务分组数æ®"); + } + + /** + * 获å–ä»»åŠ¡åˆ†ç»„è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examTaskGroupService.selectExamTaskGroupById(examCode)); + } + + /** + * 新增任务分组 + */ + @PostMapping + public AjaxResult add(@RequestBody ExamTaskGroup examTaskGroup) + { + return toAjax(examTaskGroupService.insertExamTaskGroup(examTaskGroup)); + } + + /** + * 修改任务分组 + */ + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamTaskGroup examTaskGroup) + { + return toAjax(examTaskGroupService.updateExamTaskGroup(examTaskGroup)); + } + + @PostMapping("/batchupdate") + public AjaxResult batchUpdate(@RequestBody List examTaskGroupList) + { + try + { + examTaskGroupService.batchUpdateExamTaskGroup(examTaskGroupList); + } + catch(Exception e) { + return AjaxResult.error(e.getMessage()); + } + + return AjaxResult.success(); + } + /** + * 删除任务分组 + */ + @GetMapping("/delete/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examTaskGroupService.deleteExamTaskGroupByIds(examCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskManagerController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskManagerController.java new file mode 100644 index 0000000..e27f2d1 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskManagerController.java @@ -0,0 +1,174 @@ +package com.yanzhu.exam.exam.controller; + +import java.util.List; +import java.util.Map; + + +import cn.hutool.core.date.DateUtil; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.cms.utils.FileUpload; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.domain.ExamTaskPicture; +import com.yanzhu.exam.exam.service.IExamTaskManagerService; +import com.yanzhu.exam.exam.service.IExamTaskPictureService; +import com.yanzhu.exam.questions.domain.ExamBankPicture; + +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 创建考试Controller + * + * @author qnsdt + * @date 2023-01-06 + */ +@RestController +@RequestMapping("/exam/examtask") +public class ExamTaskManagerController extends BaseController +{ + @Value("${cms.exam.photo-path:/photo/exam}") + private String photopath; + + @Autowired + private IExamTaskManagerService examTaskManagerService; + + @Autowired + private TokenService tokenService; + + @Autowired + private IExamTaskPictureService examTaskPictureService; + /** + * 查询创建考试列表 + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:list')") + @GetMapping("/list") + public TableDataInfo list(ExamTaskManager examTaskManager) + { + + if (examTaskManager.getStartTime() != null) { + examTaskManager.setStartDateText(DateUtil.formatDate(examTaskManager.getStartTime())); + } + + if (examTaskManager.getEndTime() != null) { + examTaskManager.setEndDateText(DateUtil.formatDate(examTaskManager.getEndTime())); + } + + startPage(); + List list = examTaskManagerService.selectExamTaskManagerList(examTaskManager); + return getDataTable(list); + } + + /** + * 导出创建考试列表 + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:export')") + @Log(title = "创建考试", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamTaskManager examTaskManager) + { + List list = examTaskManagerService.selectExamTaskManagerList(examTaskManager); + ExcelUtil util = new ExcelUtil(ExamTaskManager.class); + return util.exportExcel(list, "创建考试数æ®"); + } + + /** + * 获å–åˆ›å»ºè€ƒè¯•è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:query')") + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examTaskManagerService.selectExamTaskManagerById(examCode)); + } + + /** + * 新增创建考试 + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:add')") + @Log(title = "创建考试", businessType = BusinessType.INSERT) + @PostMapping("/add") + public AjaxResult add(@RequestBody ExamTaskManager examTaskManager) + { + return toAjax(examTaskManagerService.insertExamTaskManager(examTaskManager)); + } + + /** + * 修改创建考试 + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:edit')") + @Log(title = "创建考试", businessType = BusinessType.UPDATE) + // @PutMapping + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamTaskManager examTaskManager) + { + return toAjax(examTaskManagerService.updateExamTaskManager(examTaskManager)); + } + + /** + * 删除创建考试 + */ + @PreAuthorize("@ss.hasPermi('exam:examtask:remove')") + @Log(title = "创建考试", businessType = BusinessType.DELETE) + @GetMapping("/delete/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examTaskManagerService.deleteExamTaskManagerByIds(examCodes)); + } + + /** + * æ–°å¢žå‚æ•°é…ç½® + */ + @PostMapping("/uploadphoto/{examCodes}") + public AjaxResult uploadPhoto(@PathVariable String examCodes, + @RequestParam("file") MultipartFile file) + { + // å–得原始文件å + String originalfile = file.getOriginalFilename(); + + // 拼接路径 + String path = RuoYiConfig.getProfile() + photopath; + String filename = FileUpload.writeUploadFile(file,path); + String fileurl = photopath + "/" + filename; + + int count = 0; + + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + + ExamTaskPicture examTaskPicture = new ExamTaskPicture(examCodes,path,fileurl,filename,originalfile,loginUser.getUser().getUserName()); + System.out.println("examTaskPicture:" + examTaskPicture.toString()); + + try + { + examTaskPictureService.deleteExamTaskPictureById(examCodes); + count = examTaskPictureService.insertExamTaskPicture(examTaskPicture); + } + catch(Exception e) + { + return AjaxResult.error(e.getMessage()); + } + + + return AjaxResult.success(examTaskPicture); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPersonController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPersonController.java new file mode 100644 index 0000000..f126bcb --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPersonController.java @@ -0,0 +1,111 @@ +package com.yanzhu.exam.exam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.exam.domain.ExamTaskPerson; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试人员Controller + * + * @author qnsdt + * @date 2023-01-06 + */ +@RestController +@RequestMapping("/exam/taskperson") +public class ExamTaskPersonController extends BaseController +{ + @Autowired + private IExamTaskPersonService examTaskPersonService; + + /** + * 查询考试人员列表 + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:list')") + @GetMapping("/list") + public TableDataInfo list(ExamTaskPerson examTaskPerson) + { + startPage(); + List list = examTaskPersonService.selectExamTaskPersonList(examTaskPerson); + return getDataTable(list); + } + + /** + * 导出考试人员列表 + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:export')") + @Log(title = "考试人员", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamTaskPerson examTaskPerson) + { + List list = examTaskPersonService.selectExamTaskPersonList(examTaskPerson); + ExcelUtil util = new ExcelUtil(ExamTaskPerson.class); + return util.exportExcel(list, "考试人员数æ®"); + } + + /** + * 获å–è€ƒè¯•äººå‘˜è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:query')") + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examTaskPersonService.selectExamTaskPersonById(examCode)); + } + + /** + * 新增考试人员 + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:add')") + @Log(title = "考试人员", businessType = BusinessType.INSERT) + @PostMapping("/add") + public AjaxResult add(@RequestBody ExamTaskPerson examTaskPerson) + { + return toAjax(examTaskPersonService.insertExamTaskPerson(examTaskPerson)); + } + + /** + * 修改考试人员 + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:edit')") + @Log(title = "考试人员", businessType = BusinessType.UPDATE) + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamTaskPerson examTaskPerson) + { + return toAjax(examTaskPersonService.updateExamTaskPerson(examTaskPerson)); + } + + /** + * 更新考试开始时间 + */ + @PostMapping("/starttime") + public AjaxResult updateStartTime(@RequestBody ExamTaskPerson examTaskPerson) + { + return toAjax(examTaskPersonService.updateStartTime(examTaskPerson)); + } + /** + * 删除考试人员 + */ + @PreAuthorize("@ss.hasPermi('exam:taskperson:remove')") + @Log(title = "考试人员", businessType = BusinessType.DELETE) + @GetMapping("/delete/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examTaskPersonService.deleteExamTaskPersonByIds(examCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPictureController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPictureController.java new file mode 100644 index 0000000..1e602f9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskPictureController.java @@ -0,0 +1,103 @@ +package com.yanzhu.exam.exam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.exam.domain.ExamTaskPicture; +import com.yanzhu.exam.exam.service.IExamTaskPictureService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试任务图片管ç†Controller + * + * @author qnsdt + * @date 2023-01-18 + */ +@RestController +@RequestMapping("/exam/exampicture") +public class ExamTaskPictureController extends BaseController +{ + @Autowired + private IExamTaskPictureService examTaskPictureService; + + /** + * 查询考试任务图片管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:list')") + @GetMapping("/list") + public TableDataInfo list(ExamTaskPicture examTaskPicture) + { + startPage(); + List list = examTaskPictureService.selectExamTaskPictureList(examTaskPicture); + return getDataTable(list); + } + + /** + * 导出考试任务图片管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:export')") + @Log(title = "考试任务图片管ç†", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamTaskPicture examTaskPicture) + { + List list = examTaskPictureService.selectExamTaskPictureList(examTaskPicture); + ExcelUtil util = new ExcelUtil(ExamTaskPicture.class); + return util.exportExcel(list, "è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç†æ•°æ®"); + } + + /** + * 获å–考试任务图片管ç†è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:query')") + @GetMapping(value = "/{photoCode}") + public AjaxResult getInfo(@PathVariable("photoCode") String photoCode) + { + return AjaxResult.success(examTaskPictureService.selectExamTaskPictureById(photoCode)); + } + + /** + * æ–°å¢žè€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:add')") + @Log(title = "考试任务图片管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamTaskPicture examTaskPicture) + { + return toAjax(examTaskPictureService.insertExamTaskPicture(examTaskPicture)); + } + + /** + * ä¿®æ”¹è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:edit')") + @Log(title = "考试任务图片管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamTaskPicture examTaskPicture) + { + return toAjax(examTaskPictureService.updateExamTaskPicture(examTaskPicture)); + } + + /** + * åˆ é™¤è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('exam:exampicture:remove')") + @Log(title = "考试任务图片管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{photoCodes}") + public AjaxResult remove(@PathVariable String[] photoCodes) + { + return toAjax(examTaskPictureService.deleteExamTaskPictureByIds(photoCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskQuestionsController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskQuestionsController.java new file mode 100644 index 0000000..e4da2a1 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/controller/ExamTaskQuestionsController.java @@ -0,0 +1,100 @@ +package com.yanzhu.exam.exam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.exam.domain.ExamTaskQuestions; +import com.yanzhu.exam.exam.service.IExamTaskQuestionsService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 任务题目Controller + * + * @author qnsdt + * @date 2023-02-10 + */ +@RestController +@RequestMapping("/exam/taskquestions") +public class ExamTaskQuestionsController extends BaseController +{ + @Autowired + private IExamTaskQuestionsService examTaskQuestionsService; + + /** + * 查询任务题目列表 + */ + @GetMapping("/list") + public TableDataInfo list(ExamTaskQuestions examTaskQuestions) + { + startPage(); + List list = examTaskQuestionsService.selectExamTaskQuestionsList(examTaskQuestions); + return getDataTable(list); + } + + /** + * 导出任务题目列表 + */ + @GetMapping("/export") + public AjaxResult export(ExamTaskQuestions examTaskQuestions) + { + List list = examTaskQuestionsService.selectExamTaskQuestionsList(examTaskQuestions); + ExcelUtil util = new ExcelUtil(ExamTaskQuestions.class); + return util.exportExcel(list, "任务题目数æ®"); + } + + /** + * 获å–ä»»åŠ¡é¢˜ç›®è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examTaskQuestionsService.selectExamTaskQuestionsById(examCode)); + } + + + @PostMapping("/batchupdate") + public AjaxResult batchUpdate(@RequestBody List examTaskQuestionsList) + { + int count = -1; + + try + { + count = examTaskQuestionsService.batchUpdateExamTaskQuestions(examTaskQuestionsList); + } + catch(Exception e) { + return AjaxResult.error(e.getMessage()); + } + return AjaxResult.success("æ›´æ–°æˆåŠŸ"); + } + + /** + * 修改任务题目 + */ + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamTaskQuestions examTaskQuestions) + { + return toAjax(examTaskQuestionsService.updateExamTaskQuestions(examTaskQuestions)); + } + + /** + * 删除任务题目 + */ + @GetMapping("/delete/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examTaskQuestionsService.deleteExamTaskQuestionsByIds(examCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskData.java new file mode 100644 index 0000000..4eaca82 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskData.java @@ -0,0 +1,13 @@ +package com.yanzhu.exam.exam.domain; + +import java.util.List; + +import lombok.Data; + +@Data +public class ExamTaskData { + private ExamTaskManager examTaskManager; + private List taskGroupList; + private List taskQuestionsList; + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskGroup.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskGroup.java new file mode 100644 index 0000000..ce9794e --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskGroup.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.exam.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 任务分组对象 exam_task_group + * + * @author qnsdt + * @date 2023-02-10 + */ +public class ExamTaskGroup extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + @Excel(name = "考试代ç ") + private String examCode; + + /** åˆ†ç»„ä»£ç  */ + @Excel(name = "分组代ç ") + private String groupCode; + + /** 排åºç¼–å· */ + @Excel(name = "排åºç¼–å·") + private Long orderId; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setGroupCode(String groupCode) + { + this.groupCode = groupCode; + } + + public String getGroupCode() + { + return groupCode; + } + public void setOrderId(Long orderId) + { + this.orderId = orderId; + } + + public Long getOrderId() + { + return orderId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("groupCode", getGroupCode()) + .append("orderId", getOrderId()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskManager.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskManager.java new file mode 100644 index 0000000..a35df52 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskManager.java @@ -0,0 +1,270 @@ +package com.yanzhu.exam.exam.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 创建考试对象 exam_task_manager + * + * @author qnsdt + * @date 2023-01-06 + */ +public class ExamTaskManager extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 考试åºå· */ + @Excel(name = "考试åºå·") + private Long examId; + + /** è€ƒè¯•ä»£ç  */ + @Excel(name = "考试代ç ") + private String examCode; + + /** 考试åç§° */ + @Excel(name = "考试åç§°") + private String examName; + + /** 考试说明 */ + @Excel(name = "考试说明") + private String examDescribe; + + /** ç»„å·æ–¹å¼ */ + @Excel(name = "ç»„å·æ–¹å¼") + private String buildType; + + /** å¼ºåˆ¶æŠ½å· */ + @Excel(name = "强制抽å·") + private String forceDone; + + /** 考试题库 */ + @Excel(name = "考试题库") + private String examBank; + + /** 考试题库文字 */ + @Excel(name = "考试题库文字") + private String examBankText; + + @Excel(name = "考试类型1 固定时间考试 2固定时间段考试") + private Integer examType; + + public Integer getExamType() { + return examType; + } + + public void setExamType(Integer examType) { + this.examType = examType; + } + + public Integer getExamTimes() { + return examTimes; + } + + public void setExamTimes(Integer examTimes) { + this.examTimes = examTimes; + } + + @Excel(name = "考试次数") + private Integer examTimes; + + /** 图片链接 */ + @Excel(name = "图片链接") + private String pictureUrl; + + /** 开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date startTime; + + /** ç»“æŸæ—¶é—´ */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ç»“æŸæ—¶é—´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + + /** 考试时长 */ + @Excel(name = "考试时长") + private String examDuration; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + private String startDateText; + + public String getStartDateText() { + return startDateText; + } + + public void setStartDateText(String startDateText) { + this.startDateText = startDateText; + } + + + private String endDateText; + + public String getEndDateText() { + return endDateText; + } + + public void setEndDateText(String endDateText) { + this.endDateText = endDateText; + } + + /** 创建部门 */ + private Long createDept; + + public void setExamId(Long examId) + { + this.examId = examId; + } + + public Long getExamId() + { + return examId; + } + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setExamName(String examName) + { + this.examName = examName; + } + + public String getExamName() + { + return examName; + } + public void setExamDescribe(String examDescribe) + { + this.examDescribe = examDescribe; + } + + public String getExamDescribe() + { + return examDescribe; + } + public void setBuildType(String buildType) + { + this.buildType = buildType; + } + + public String getBuildType() + { + return buildType; + } + public void setForceDone(String forceDone) + { + this.forceDone = forceDone; + } + + public String getForceDone() + { + return forceDone; + } + public void setExamBank(String examBank) + { + this.examBank = examBank; + } + + public String getExamBank() + { + return examBank; + } + public void setPictureUrl(String pictureUrl) + { + this.pictureUrl = pictureUrl; + } + + public void setExamBankText(String examBankText) + { + this.examBankText = examBankText; + } + + public String getExamBankText() + { + return examBankText; + } + + public String getPictureUrl() + { + return pictureUrl; + } + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStartTime() + { + return startTime; + } + public void setEndTime(Date endTime) + { + this.endTime = endTime; + } + + public Date getEndTime() + { + return endTime; + } + public void setExamDuration(String examDuration) + { + this.examDuration = examDuration; + } + + public String getExamDuration() + { + return examDuration; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + public void setCreateDept(Long createDept) + { + this.createDept = createDept; + } + + public Long getCreateDept() + { + return createDept; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examId", getExamId()) + .append("examCode", getExamCode()) + .append("examName", getExamName()) + .append("examDescribe", getExamDescribe()) + .append("buildType", getBuildType()) + .append("forceDone", getForceDone()) + .append("examBank", getExamBank()) + .append("examBankText", getExamBankText()) + .append("pictureUrl", getPictureUrl()) + .append("startTime", getStartTime()) + .append("endTime", getEndTime()) + .append("examDuration", getExamDuration()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createDept", getCreateDept()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPerson.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPerson.java new file mode 100644 index 0000000..2e14ec1 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPerson.java @@ -0,0 +1,111 @@ +package com.yanzhu.exam.exam.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试人员对象 exam_task_person + * + * @author qnsdt + * @date 2023-02-14 + */ +public class ExamTaskPerson extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + @Excel(name = "考试代ç ") + private String examCode; + + /** 考试人员 */ + @Excel(name = "考试人员") + private String userCode; + + /** ä¸ªäººä»»åŠ¡ç  */ + private String taskCode; + + /** 开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date startTime; + + /** ç»“æŸæ—¶é—´ */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "ç»“æŸæ—¶é—´", width = 30, dateFormat = "yyyy-MM-dd") + private Date endTime; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setuserCode(String userCode) + { + this.userCode = userCode; + } + + public String getuserCode() + { + return userCode; + } + public void setTaskCode(String taskCode) + { + this.taskCode = taskCode; + } + + public String getTaskCode() + { + return taskCode; + } + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStartTime() + { + return startTime; + } + public void setEndTime(Date endTime) + { + this.endTime = endTime; + } + + public Date getEndTime() + { + return endTime; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("userCode", getuserCode()) + .append("taskCode", getTaskCode()) + .append("startTime", getStartTime()) + .append("endTime", getEndTime()) + .append("status", getStatus()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPicture.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPicture.java new file mode 100644 index 0000000..4d68109 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskPicture.java @@ -0,0 +1,145 @@ +package com.yanzhu.exam.exam.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试任务图片管ç†å¯¹è±¡ exam_task_picture + * + * @author qnsdt + * @date 2023-01-18 + */ +public class ExamTaskPicture extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 图片åºå· */ + private Long photoId; + + /** å›¾ç‰‡ä»£ç  */ + private String photoCode; + + /** æ–‡æ¡£ä»£ç  */ + @Excel(name = "文档代ç ") + private String photoPath; + + /** 图片链接 */ + @Excel(name = "图片链接") + private String photoUrl; + + /** 文件åç§° */ + @Excel(name = "文件åç§°") + private String fileName; + + /** 原始åç§° */ + @Excel(name = "原始åç§°") + private String originalName; + + private String createBy; + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + public void setPhotoId(Long photoId) + { + this.photoId = photoId; + } + + public Long getPhotoId() + { + return photoId; + } + public void setPhotoCode(String photoCode) + { + this.photoCode = photoCode; + } + + public String getPhotoCode() + { + return photoCode; + } + public void setPhotoPath(String photoPath) + { + this.photoPath = photoPath; + } + + public String getPhotoPath() + { + return photoPath; + } + public void setPhotoUrl(String photoUrl) + { + this.photoUrl = photoUrl; + } + + public String getPhotoUrl() + { + return photoUrl; + } + public void setFileName(String fileName) + { + this.fileName = fileName; + } + + public String getFileName() + { + return fileName; + } + public void setOriginalName(String originalName) + { + this.originalName = originalName; + } + + public String getOriginalName() + { + return originalName; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + + + + + public ExamTaskPicture(String photoCode, String photoPath, String photoUrl, String fileName, String originalName, + String createBy) { + super(); + this.photoCode = photoCode; + this.photoPath = photoPath; + this.photoUrl = photoUrl; + this.fileName = fileName; + this.originalName = originalName; + this.createBy = createBy; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("photoId", getPhotoId()) + .append("photoCode", getPhotoCode()) + .append("photoPath", getPhotoPath()) + .append("photoUrl", getPhotoUrl()) + .append("fileName", getFileName()) + .append("originalName", getOriginalName()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("status", getStatus()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskQuestions.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskQuestions.java new file mode 100644 index 0000000..36d33ad --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/domain/ExamTaskQuestions.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.exam.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 任务题目对象 exam_task_questions + * + * @author qnsdt + * @date 2023-02-15 + */ +public class ExamTaskQuestions extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + @Excel(name = "考试代ç ") + private String examCode; + + /** é¢˜ç›®ä»£ç  */ + @Excel(name = "题目代ç ") + private String questionsCode; + + /** é¢˜å· */ + @Excel(name = "题å·") + private int questionsNumber; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsNumber(int questionsNumber) + { + this.questionsNumber = questionsNumber; + } + + public int getQuestionsNumber() + { + return questionsNumber; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("questionsCode", getQuestionsCode()) + .append("questionsNumber", getQuestionsNumber()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskGroupMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskGroupMapper.java new file mode 100644 index 0000000..b74ea5a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskGroupMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.exam.mapper; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskGroup; + +/** + * 任务分组MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-10 + */ +public interface ExamTaskGroupMapper +{ + /** + * 查询任务分组 + * + * @param examCode 任务分组ID + * @return 任务分组 + */ + public ExamTaskGroup selectExamTaskGroupById(String examCode); + + /** + * 查询任务分组列表 + * + * @param examTaskGroup 任务分组 + * @return ä»»åŠ¡åˆ†ç»„é›†åˆ + */ + public List selectExamTaskGroupList(ExamTaskGroup examTaskGroup); + + /** + * 新增任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + public int insertExamTaskGroup(ExamTaskGroup examTaskGroup); + + /** + * 修改任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + public int updateExamTaskGroup(ExamTaskGroup examTaskGroup); + + /** + * 删除任务分组 + * + * @param examCode 任务分组ID + * @return 结果 + */ + public int deleteExamTaskGroupById(String examCode); + + /** + * 批é‡åˆ é™¤ä»»åŠ¡åˆ†ç»„ + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskGroupByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskManagerMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskManagerMapper.java new file mode 100644 index 0000000..8864f0a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskManagerMapper.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.exam.mapper; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import org.apache.ibatis.annotations.Param; + +/** + * 创建考试MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-06 + */ +public interface ExamTaskManagerMapper +{ + /** + * 查询创建考试 + * + * @param examCode 创建考试ID + * @return 创建考试 + */ + public ExamTaskManager selectExamTaskManagerById(String examCode); + + + /** + * 查询创建考试列表 + * + * @param examTaskManager 创建考试 + * @return åˆ›å»ºè€ƒè¯•é›†åˆ + */ + public List selectExamTaskManagerList(ExamTaskManager examTaskManager); + + /** + * 新增创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + public int insertExamTaskManager(ExamTaskManager examTaskManager); + + /** + * 修改创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + public int updateExamTaskManager(ExamTaskManager examTaskManager); + + /** + * 删除创建考试 + * + * @param examCode 创建考试ID + * @return 结果 + */ + public int deleteExamTaskManagerById(String examCode); + + /** + * 批é‡åˆ é™¤åˆ›å»ºè€ƒè¯• + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskManagerByIds(String[] examCodes); + + public List selectCurrentExam(@Param("userCode") String userCode); + + public List countExamScore(@Param("examCodeList") List examCodeList); + + public List groupExamTypeCount(@Param("examCodeList") List examCodeList); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPersonMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPersonMapper.java new file mode 100644 index 0000000..dd93633 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPersonMapper.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.exam.mapper; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskPerson; + +/** + * 考试人员MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-06 + */ +public interface ExamTaskPersonMapper +{ + /** + * 查询考试人员 + * + * @param examCode 考试人员ID + * @return 考试人员 + */ + public ExamTaskPerson selectExamTaskPersonById(String examCode); + + /** + * 查询考试人员 + * + * @param examTaskPerson 考试人员 + * @return 考试人员 + */ + public ExamTaskPerson selectExamTaskPerson(ExamTaskPerson examTaskPerson); + + /** + * 查询考试人员列表 + * + * @param examTaskPerson 考试人员 + * @return è€ƒè¯•äººå‘˜é›†åˆ + */ + public List selectExamTaskPersonList(ExamTaskPerson examTaskPerson); + + /** + * 新增考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int insertExamTaskPerson(ExamTaskPerson examTaskPerson); + + /** + * æ‰¹é‡æ‹·è´è€ƒè¯•人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int batchInsertPerson(String examCode); + + /** + * 修改考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateExamTaskPerson(ExamTaskPerson examTaskPerson); + + /** + * 更新考试开始时间 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateStartTime(ExamTaskPerson examTaskPerson); + + /** + * 更新完æˆçŠ¶æ€ + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateDoneStatus(ExamTaskPerson examTaskPerson); + + /** + * 删除考试人员 + * + * @param examCode 考试人员ID + * @return 结果 + */ + public int deleteExamTaskPersonById(String examCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•人员 + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskPersonByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPictureMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPictureMapper.java new file mode 100644 index 0000000..886d7b8 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskPictureMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.exam.mapper; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskPicture; + +/** + * 考试任务图片管ç†MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-18 + */ +public interface ExamTaskPictureMapper +{ + /** + * æŸ¥è¯¢è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCode 考试任务图片管ç†ID + * @return è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + public ExamTaskPicture selectExamTaskPictureById(String photoCode); + + /** + * 查询考试任务图片管ç†åˆ—表 + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 考试任务图片管ç†é›†åˆ + */ + public List selectExamTaskPictureList(ExamTaskPicture examTaskPicture); + + /** + * æ–°å¢žè€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int insertExamTaskPicture(ExamTaskPicture examTaskPicture); + + /** + * ä¿®æ”¹è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int updateExamTaskPicture(ExamTaskPicture examTaskPicture); + + /** + * åˆ é™¤è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCode 考试任务图片管ç†ID + * @return 结果 + */ + public int deleteExamTaskPictureById(String photoCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskPictureByIds(String[] photoCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskQuestionsMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskQuestionsMapper.java new file mode 100644 index 0000000..99bdf4a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/mapper/ExamTaskQuestionsMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.exam.mapper; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskQuestions; + +/** + * 任务题目MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-10 + */ +public interface ExamTaskQuestionsMapper +{ + /** + * 查询任务题目 + * + * @param examCode 任务题目ID + * @return 任务题目 + */ + public ExamTaskQuestions selectExamTaskQuestionsById(String examCode); + + /** + * 查询任务题目列表 + * + * @param examTaskQuestions 任务题目 + * @return ä»»åŠ¡é¢˜ç›®é›†åˆ + */ + public List selectExamTaskQuestionsList(ExamTaskQuestions examTaskQuestions); + + /** + * 新增任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + public int insertExamTaskQuestions(ExamTaskQuestions examTaskQuestions); + + /** + * 修改任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + public int updateExamTaskQuestions(ExamTaskQuestions examTaskQuestions); + + /** + * 删除任务题目 + * + * @param examCode 任务题目ID + * @return 结果 + */ + public int deleteExamTaskQuestionsById(String examCode); + + /** + * 批é‡åˆ é™¤ä»»åŠ¡é¢˜ç›® + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskQuestionsByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskDataService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskDataService.java new file mode 100644 index 0000000..8031384 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskDataService.java @@ -0,0 +1,7 @@ +package com.yanzhu.exam.exam.service; + +import com.yanzhu.exam.exam.domain.ExamTaskData; + +public interface IExamTaskDataService { + public int saveData(ExamTaskData examTaskData) throws Exception; +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskGroupService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskGroupService.java new file mode 100644 index 0000000..73c5f12 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskGroupService.java @@ -0,0 +1,70 @@ +package com.yanzhu.exam.exam.service; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskGroup; + +/** + * 任务分组ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-10 + */ +public interface IExamTaskGroupService +{ + /** + * 查询任务分组 + * + * @param examCode 任务分组ID + * @return 任务分组 + */ + public ExamTaskGroup selectExamTaskGroupById(String examCode); + + /** + * 查询任务分组列表 + * + * @param examTaskGroup 任务分组 + * @return ä»»åŠ¡åˆ†ç»„é›†åˆ + */ + public List selectExamTaskGroupList(ExamTaskGroup examTaskGroup); + + /** + * 新增任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + public int insertExamTaskGroup(ExamTaskGroup examTaskGroup); + + /** + * 修改任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + public int updateExamTaskGroup(ExamTaskGroup examTaskGroup); + + /** + * 修改任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + * @throws Exception + */ + public int batchUpdateExamTaskGroup(List examTaskGroupList) throws Exception; + + /** + * 批é‡åˆ é™¤ä»»åŠ¡åˆ†ç»„ + * + * @param examCodes 需è¦åˆ é™¤çš„任务分组ID + * @return 结果 + */ + public int deleteExamTaskGroupByIds(String[] examCodes); + + /** + * åˆ é™¤ä»»åŠ¡åˆ†ç»„ä¿¡æ¯ + * + * @param examCode 任务分组ID + * @return 结果 + */ + public int deleteExamTaskGroupById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskManagerService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskManagerService.java new file mode 100644 index 0000000..4c780d5 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskManagerService.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.exam.service; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; + +/** + * 创建考试ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-06 + */ +public interface IExamTaskManagerService +{ + /** + * 查询创建考试 + * + * @param examCode 创建考试ID + * @return 创建考试 + */ + public ExamTaskManager selectExamTaskManagerById(String examCode); + + /** + * 查询创建考试列表 + * + * @param examTaskManager 创建考试 + * @return åˆ›å»ºè€ƒè¯•é›†åˆ + */ + public List selectExamTaskManagerList(ExamTaskManager examTaskManager); + + /** + * 新增创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + public int insertExamTaskManager(ExamTaskManager examTaskManager); + + /** + * 修改创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + public int updateExamTaskManager(ExamTaskManager examTaskManager); + + /** + * 批é‡åˆ é™¤åˆ›å»ºè€ƒè¯• + * + * @param examCodes 需è¦åˆ é™¤çš„创建考试ID + * @return 结果 + */ + public int deleteExamTaskManagerByIds(String[] examCodes); + + /** + * åˆ é™¤åˆ›å»ºè€ƒè¯•ä¿¡æ¯ + * + * @param examCode 创建考试ID + * @return 结果 + */ + public int deleteExamTaskManagerById(String examCode); + + /** + * 获å–当å‰ç”¨æˆ·å¯ä»¥å‚加的考试 + * @param userCode + * @return + */ + public List selectCurrentExam(String userCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPersonService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPersonService.java new file mode 100644 index 0000000..c2c6403 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPersonService.java @@ -0,0 +1,97 @@ +package com.yanzhu.exam.exam.service; + +import java.util.List; + +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.domain.ExamTaskPerson; + +/** + * 考试人员ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-06 + */ +public interface IExamTaskPersonService +{ + /** + * 查询考试人员 + * + * @param examCode 考试人员ID + * @return 考试人员 + */ + public ExamTaskPerson selectExamTaskPersonById(String examCode); + + /** + * 查询考试人员 + * + * @param examTaskPerson 考试人员 + * @return 考试人员 + */ + public ExamTaskPerson selectExamTaskPerson(ExamTaskPerson examTaskPerson); + + /** + * 查询考试人员列表 + * + * @param examTaskPerson 考试人员 + * @return è€ƒè¯•äººå‘˜é›†åˆ + */ + public List selectExamTaskPersonList(ExamTaskPerson examTaskPerson); + + /** + * 新增考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int insertExamTaskPerson(ExamTaskPerson examTaskPerson); + + /** + * æ‰¹é‡æ‹·è´è€ƒè¯•人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int batchInsertPerson(String examCode); + + /** + * 修改考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateExamTaskPerson(ExamTaskPerson examTaskPerson); + + + /** + * 更新考试开始时间 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateStartTime(ExamTaskPerson examTaskPerson); + + /** + * 更新完æˆçŠ¶æ€ + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + public int updateDoneStatus(ExamTaskPerson examTaskPerson); + + + /** + * 批é‡åˆ é™¤è€ƒè¯•人员 + * + * @param examCodes 需è¦åˆ é™¤çš„考试人员ID + * @return 结果 + */ + public int deleteExamTaskPersonByIds(String[] examCodes); + + /** + * åˆ é™¤è€ƒè¯•äººå‘˜ä¿¡æ¯ + * + * @param examCode 考试人员ID + * @return 结果 + */ + public int deleteExamTaskPersonById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPictureService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPictureService.java new file mode 100644 index 0000000..d1716e7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskPictureService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.exam.service; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskPicture; + +/** + * 考试任务图片管ç†ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-18 + */ +public interface IExamTaskPictureService +{ + /** + * æŸ¥è¯¢è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCode 考试任务图片管ç†ID + * @return è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + public ExamTaskPicture selectExamTaskPictureById(String photoCode); + + /** + * 查询考试任务图片管ç†åˆ—表 + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 考试任务图片管ç†é›†åˆ + */ + public List selectExamTaskPictureList(ExamTaskPicture examTaskPicture); + + /** + * æ–°å¢žè€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int insertExamTaskPicture(ExamTaskPicture examTaskPicture); + + /** + * ä¿®æ”¹è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int updateExamTaskPicture(ExamTaskPicture examTaskPicture); + + /** + * 批é‡åˆ é™¤è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCodes 需è¦åˆ é™¤çš„考试任务图片管ç†ID + * @return 结果 + */ + public int deleteExamTaskPictureByIds(String[] photoCodes); + + /** + * 删除考试任务图片管ç†ä¿¡æ¯ + * + * @param photoCode 考试任务图片管ç†ID + * @return 结果 + */ + public int deleteExamTaskPictureById(String photoCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskQuestionsService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskQuestionsService.java new file mode 100644 index 0000000..d597f8d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/IExamTaskQuestionsService.java @@ -0,0 +1,63 @@ +package com.yanzhu.exam.exam.service; + +import java.util.List; +import com.yanzhu.exam.exam.domain.ExamTaskQuestions; + +/** + * 任务题目ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-10 + */ +public interface IExamTaskQuestionsService +{ + /** + * 查询任务题目 + * + * @param examCode 任务题目ID + * @return 任务题目 + */ + public ExamTaskQuestions selectExamTaskQuestionsById(String examCode); + + /** + * 查询任务题目列表 + * + * @param examTaskQuestions 任务题目 + * @return ä»»åŠ¡é¢˜ç›®é›†åˆ + */ + public List selectExamTaskQuestionsList(ExamTaskQuestions examTaskQuestions); + + /** + * 新增任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + public int insertExamTaskQuestions(ExamTaskQuestions examTaskQuestions); + + public int batchUpdateExamTaskQuestions(List examTaskQuestionsList) throws Exception; + + /** + * 修改任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + public int updateExamTaskQuestions(ExamTaskQuestions examTaskQuestions); + + /** + * 批é‡åˆ é™¤ä»»åŠ¡é¢˜ç›® + * + * @param examCodes 需è¦åˆ é™¤çš„任务题目ID + * @return 结果 + */ + public int deleteExamTaskQuestionsByIds(String[] examCodes); + + /** + * åˆ é™¤ä»»åŠ¡é¢˜ç›®ä¿¡æ¯ + * + * @param examCode 任务题目ID + * @return 结果 + */ + public int deleteExamTaskQuestionsById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskDataServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskDataServiceImpl.java new file mode 100644 index 0000000..02dcd3b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskDataServiceImpl.java @@ -0,0 +1,95 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.exam.domain.ExamTaskData; +import com.yanzhu.exam.exam.domain.ExamTaskGroup; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.domain.ExamTaskQuestions; +import com.yanzhu.exam.exam.service.IExamTaskDataService; +import com.yanzhu.exam.exam.service.IExamTaskGroupService; +import com.yanzhu.exam.exam.service.IExamTaskManagerService; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; +import com.yanzhu.exam.exam.service.IExamTaskQuestionsService; + +@Service +public class ExamTaskDataServiceImpl implements IExamTaskDataService { + @Autowired + private IExamTaskGroupService examTaskGroupService; + + @Autowired + private IExamTaskManagerService examTaskManagerService; + + @Autowired + private IExamTaskQuestionsService examTaskQuestionsService; + + @Autowired + private IExamTaskPersonService examTaskPersonService; + + + @Override + public int saveData(ExamTaskData examTaskData) throws Exception { + // TODO Auto-generated method stub + ExamTaskManager examTaskManager = examTaskData.getExamTaskManager(); + + int count = 0; + try + { + // 安全删除 + examTaskManagerService.deleteExamTaskManagerById(examTaskManager.getExamCode()); + + // ä¿å­˜æ•°æ® + count = examTaskManagerService.insertExamTaskManager(examTaskManager); + } + catch(Exception e) { + throw new Exception("ä¿å­˜å±žæ€§å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + + List questionsList = examTaskData.getTaskQuestionsList(); + + // 安全删除 + examTaskQuestionsService.deleteExamTaskQuestionsById(examTaskManager.getExamCode()); + + for(ExamTaskQuestions examTaskQuestions: questionsList) { + try + { + count = examTaskQuestionsService.insertExamTaskQuestions(examTaskQuestions); + } + catch(Exception e) { + throw new Exception("ä¿å­˜é¢˜ç›®ä¿¡æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + } + + List groupList = examTaskData.getTaskGroupList(); + + // 安全删除 + examTaskGroupService.deleteExamTaskGroupById(examTaskManager.getExamCode()); + + for (ExamTaskGroup examTaskGroup: groupList) { + try + { + count = examTaskGroupService.insertExamTaskGroup(examTaskGroup); + } + catch(Exception e) { + throw new Exception("ä¿å­˜åˆ†ç»„ä¿¡æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + } + + // 安全删除 + examTaskPersonService.deleteExamTaskPersonById(examTaskManager.getExamCode()); + + try + { + count = examTaskPersonService.batchInsertPerson(examTaskManager.getExamCode()); + } + catch(Exception e) { + throw new Exception("ä¿å­˜è€ƒè¯•人员信æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + + return 1; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskGroupServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskGroupServiceImpl.java new file mode 100644 index 0000000..625ef83 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskGroupServiceImpl.java @@ -0,0 +1,127 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.exam.mapper.ExamTaskGroupMapper; +import com.yanzhu.exam.exam.domain.ExamTaskGroup; +import com.yanzhu.exam.exam.service.IExamTaskGroupService; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; + +/** + * 任务分组Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-10 + */ +@Service +public class ExamTaskGroupServiceImpl implements IExamTaskGroupService +{ + @Autowired + private ExamTaskGroupMapper examTaskGroupMapper; + + @Autowired + private IExamTaskPersonService examTaskPersonService; + /** + * 查询任务分组 + * + * @param examCode 任务分组ID + * @return 任务分组 + */ + @Override + public ExamTaskGroup selectExamTaskGroupById(String examCode) + { + return examTaskGroupMapper.selectExamTaskGroupById(examCode); + } + + /** + * 查询任务分组列表 + * + * @param examTaskGroup 任务分组 + * @return 任务分组 + */ + @Override + public List selectExamTaskGroupList(ExamTaskGroup examTaskGroup) + { + return examTaskGroupMapper.selectExamTaskGroupList(examTaskGroup); + } + + /** + * 新增任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + @Override + public int insertExamTaskGroup(ExamTaskGroup examTaskGroup) + { + return examTaskGroupMapper.insertExamTaskGroup(examTaskGroup); + } + + /** + * 修改任务分组 + * + * @param examTaskGroup 任务分组 + * @return 结果 + */ + @Override + public int updateExamTaskGroup(ExamTaskGroup examTaskGroup) + { + return examTaskGroupMapper.updateExamTaskGroup(examTaskGroup); + } + + /** + * 批é‡åˆ é™¤ä»»åŠ¡åˆ†ç»„ + * + * @param examCodes 需è¦åˆ é™¤çš„任务分组ID + * @return 结果 + */ + @Override + public int deleteExamTaskGroupByIds(String[] examCodes) + { + return examTaskGroupMapper.deleteExamTaskGroupByIds(examCodes); + } + + /** + * åˆ é™¤ä»»åŠ¡åˆ†ç»„ä¿¡æ¯ + * + * @param examCode 任务分组ID + * @return 结果 + */ + @Override + public int deleteExamTaskGroupById(String examCode) + { + return examTaskGroupMapper.deleteExamTaskGroupById(examCode); + } + + @Override + public int batchUpdateExamTaskGroup(List examTaskGroupList) throws Exception { + // TODO Auto-generated method stub + // 安全删除 + int count = 0; + String examCode = examTaskGroupList.get(0).getExamCode(); + examTaskGroupMapper.deleteExamTaskGroupById(examCode); + + for (ExamTaskGroup examTaskGroup: examTaskGroupList) { + try + { + count = examTaskGroupMapper.insertExamTaskGroup(examTaskGroup); + } + catch(Exception e) { + throw new Exception("ä¿å­˜åˆ†ç»„ä¿¡æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + } + + // 安全删除 + examTaskPersonService.deleteExamTaskPersonById(examCode); + + try + { + count = examTaskPersonService.batchInsertPerson(examCode); + } + catch(Exception e) { + throw new Exception("ä¿å­˜è€ƒè¯•人员信æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + return 1; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskManagerServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskManagerServiceImpl.java new file mode 100644 index 0000000..ebfa2d0 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskManagerServiceImpl.java @@ -0,0 +1,187 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.bean.BeanUtil; +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.exam.mapper.ExamTaskManagerMapper; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.service.IExamTaskGroupService; +import com.yanzhu.exam.exam.service.IExamTaskManagerService; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; +import com.yanzhu.exam.exam.service.IExamTaskQuestionsService; + +/** + * 创建考试Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-01-06 + */ +@Service +public class ExamTaskManagerServiceImpl implements IExamTaskManagerService +{ + @Autowired + private ExamTaskManagerMapper examTaskManagerMapper; + + @Autowired + private IExamTaskGroupService examTaskGroupService; + + @Autowired + private IExamTaskQuestionsService examTaskQuestionsService; + + @Autowired + private IExamTaskPersonService examTaskPersonService; + + /** + * 查询创建考试 + * + * @param examCode 创建考试ID + * @return 创建考试 + */ + @Override + public ExamTaskManager selectExamTaskManagerById(String examCode) + { + return examTaskManagerMapper.selectExamTaskManagerById(examCode); + } + + /** + * 查询创建考试列表 + * + * @param examTaskManager 创建考试 + * @return 创建考试 + */ + @Override + public List selectExamTaskManagerList(ExamTaskManager examTaskManager) + { + return examTaskManagerMapper.selectExamTaskManagerList(examTaskManager); + } + + /** + * 新增创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + @Override + public int insertExamTaskManager(ExamTaskManager examTaskManager) + { + examTaskManager.setCreateTime(DateUtils.getNowDate()); + return examTaskManagerMapper.insertExamTaskManager(examTaskManager); + } + + /** + * 修改创建考试 + * + * @param examTaskManager 创建考试 + * @return 结果 + */ + @Override + public int updateExamTaskManager(ExamTaskManager examTaskManager) + { + return examTaskManagerMapper.updateExamTaskManager(examTaskManager); + } + + /** + * 批é‡åˆ é™¤åˆ›å»ºè€ƒè¯• + * + * @param examCodes 需è¦åˆ é™¤çš„创建考试ID + * @return 结果 + */ + @Override + public int deleteExamTaskManagerByIds(String[] examCodes) + { + // 删除题目 + examTaskQuestionsService.deleteExamTaskQuestionsByIds(examCodes); + // 删除人员分组 + examTaskGroupService.deleteExamTaskGroupByIds(examCodes); + // 删除人员 + examTaskPersonService.deleteExamTaskPersonByIds(examCodes); + + return examTaskManagerMapper.deleteExamTaskManagerByIds(examCodes); + } + + /** + * åˆ é™¤åˆ›å»ºè€ƒè¯•ä¿¡æ¯ + * + * @param examCode 创建考试ID + * @return 结果 + */ + @Override + public int deleteExamTaskManagerById(String examCode) + { + return examTaskManagerMapper.deleteExamTaskManagerById(examCode); + } + + /** + * 获å–当å‰ç”¨æˆ·å¯ä»¥å‚加的考试 + * @param userCode + * @return + */ + @Override + public List selectCurrentExam(String userCode) { + //先根æ®å½“剿—¶é—´å’ŒstartDateå’ŒendDate过滤一下 + List list=examTaskManagerMapper.selectCurrentExam(userCode); + List retList=new ArrayList<>(); + List examCodeList=new ArrayList<>(); + for(ExamTaskManager examTaskManager:list){ + if(examTaskManager.getExamType()==1){ + if(!checkCanRun(examTaskManager)){ + continue; + } + }else{ + + } + ExamTitleData ed=new ExamTitleData(); + examCodeList.add(examTaskManager.getExamCode()); + // 使用 Hutool çš„ BeanUtil.copyProperties 方法å¤åˆ¶å±žæ€§ + BeanUtil.copyProperties(examTaskManager, ed); + retList.add(ed); + } + if(examCodeList.isEmpty()){ + return retList; + } + List listScore=examTaskManagerMapper.countExamScore(examCodeList); + List listTypeCount=examTaskManagerMapper.groupExamTypeCount(examCodeList); + for(ExamTitleData item :retList){ + List tmp= listScore.stream().filter(d->d.getExamCode().equals(item.getExamCode())).collect(Collectors.toList()); + if(tmp.size()>0){ + item.setQuestionsScore(tmp.get(0).getExamType()); + } + tmp=listTypeCount.stream().filter(d->d.getExamCode().equals(item.getExamCode()) && d.getExamId()==1).collect(Collectors.toList()); + if(tmp.size()>0){ + item.setJudgeNumber(tmp.get(0).getExamType()); + } + tmp=listTypeCount.stream().filter(d->d.getExamCode().equals(item.getExamCode()) && d.getExamId()==2).collect(Collectors.toList()); + if(tmp.size()>0){ + item.setRadioNumber(tmp.get(0).getExamType()); + } + tmp=listTypeCount.stream().filter(d->d.getExamCode().equals(item.getExamCode()) && d.getExamId()==3).collect(Collectors.toList()); + if(tmp.size()>0){ + item.setChoiceNumber(tmp.get(0).getExamType()); + } + } + return retList; + } + + private boolean checkCanRun(ExamTaskManager examTaskManager) { + //开始时间+考试时长 å°äºŽå½“剿—¶é—´è¡¨ç¤ºè€ƒè¯•å·²å‘结æŸ,大于表示还å¯èƒ½ç»§ç»­è€ƒè¯• + DateTime dtStart=new DateTime( examTaskManager.getStartTime()); + String sp=examTaskManager.getExamDuration(); + String[] timeParts = sp.split(":"); + int hours = Integer.parseInt(timeParts[0]); + int minutes = Integer.parseInt(timeParts[1]); + // è®¡ç®—ç»“æŸæ—¶é—´ + DateTime endDateTime = dtStart.offset(DateField.HOUR_OF_DAY, hours) + .offset(DateField.MINUTE, minutes); + return endDateTime.isAfter(DateUtils.getNowDate()); + + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPersonServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPersonServiceImpl.java new file mode 100644 index 0000000..8fb1cb4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPersonServiceImpl.java @@ -0,0 +1,125 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.exam.mapper.ExamTaskPersonMapper; +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.domain.ExamTaskPerson; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; + +/** + * 考试人员Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-01-06 + */ +@Service +public class ExamTaskPersonServiceImpl implements IExamTaskPersonService +{ + @Autowired + private ExamTaskPersonMapper examTaskPersonMapper; + + /** + * 查询考试人员 + * + * @param examCode 考试人员ID + * @return 考试人员 + */ + @Override + public ExamTaskPerson selectExamTaskPersonById(String examCode) + { + return examTaskPersonMapper.selectExamTaskPersonById(examCode); + } + + /** + * 查询考试人员列表 + * + * @param examTaskPerson 考试人员 + * @return 考试人员 + */ + @Override + public List selectExamTaskPersonList(ExamTaskPerson examTaskPerson) + { + return examTaskPersonMapper.selectExamTaskPersonList(examTaskPerson); + } + + /** + * 新增考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + @Override + public int insertExamTaskPerson(ExamTaskPerson examTaskPerson) + { + return examTaskPersonMapper.insertExamTaskPerson(examTaskPerson); + } + + /** + * 修改考试人员 + * + * @param examTaskPerson 考试人员 + * @return 结果 + */ + @Override + public int updateExamTaskPerson(ExamTaskPerson examTaskPerson) + { + return examTaskPersonMapper.updateExamTaskPerson(examTaskPerson); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•人员 + * + * @param examCodes 需è¦åˆ é™¤çš„考试人员ID + * @return 结果 + */ + @Override + public int deleteExamTaskPersonByIds(String[] examCodes) + { + return examTaskPersonMapper.deleteExamTaskPersonByIds(examCodes); + } + + /** + * åˆ é™¤è€ƒè¯•äººå‘˜ä¿¡æ¯ + * + * @param examCode 考试人员ID + * @return 结果 + */ + @Override + public int deleteExamTaskPersonById(String examCode) + { + return examTaskPersonMapper.deleteExamTaskPersonById(examCode); + } + + @Override + public int batchInsertPerson(String examCode) { + // TODO Auto-generated method stub + return examTaskPersonMapper.batchInsertPerson(examCode); + } + + @Override + public int updateStartTime(ExamTaskPerson examTaskPerson) { + // TODO Auto-generated method stub + ExamTaskPerson taskPerson = examTaskPersonMapper.selectExamTaskPerson(examTaskPerson); + + if (taskPerson != null && taskPerson.getStartTime() == null) { + examTaskPersonMapper.updateStartTime(examTaskPerson); + } + return 1; + } + + @Override + public ExamTaskPerson selectExamTaskPerson(ExamTaskPerson examTaskPerson) { + // TODO Auto-generated method stub + return examTaskPersonMapper.selectExamTaskPerson(examTaskPerson); + } + + @Override + public int updateDoneStatus(ExamTaskPerson examTaskPerson) { + // TODO Auto-generated method stub + return examTaskPersonMapper.updateDoneStatus(examTaskPerson); + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPictureServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPictureServiceImpl.java new file mode 100644 index 0000000..b1199d3 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskPictureServiceImpl.java @@ -0,0 +1,95 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.exam.mapper.ExamTaskPictureMapper; +import com.yanzhu.exam.exam.domain.ExamTaskPicture; +import com.yanzhu.exam.exam.service.IExamTaskPictureService; + +/** + * 考试任务图片管ç†Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-01-18 + */ +@Service +public class ExamTaskPictureServiceImpl implements IExamTaskPictureService +{ + @Autowired + private ExamTaskPictureMapper examTaskPictureMapper; + + /** + * æŸ¥è¯¢è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCode 考试任务图片管ç†ID + * @return è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + @Override + public ExamTaskPicture selectExamTaskPictureById(String photoCode) + { + return examTaskPictureMapper.selectExamTaskPictureById(photoCode); + } + + /** + * 查询考试任务图片管ç†åˆ—表 + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + */ + @Override + public List selectExamTaskPictureList(ExamTaskPicture examTaskPicture) + { + return examTaskPictureMapper.selectExamTaskPictureList(examTaskPicture); + } + + /** + * æ–°å¢žè€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + @Override + public int insertExamTaskPicture(ExamTaskPicture examTaskPicture) + { + examTaskPicture.setCreateTime(DateUtils.getNowDate()); + return examTaskPictureMapper.insertExamTaskPicture(examTaskPicture); + } + + /** + * ä¿®æ”¹è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param examTaskPicture è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + @Override + public int updateExamTaskPicture(ExamTaskPicture examTaskPicture) + { + return examTaskPictureMapper.updateExamTaskPicture(examTaskPicture); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•ä»»åŠ¡å›¾ç‰‡ç®¡ç† + * + * @param photoCodes 需è¦åˆ é™¤çš„考试任务图片管ç†ID + * @return 结果 + */ + @Override + public int deleteExamTaskPictureByIds(String[] photoCodes) + { + return examTaskPictureMapper.deleteExamTaskPictureByIds(photoCodes); + } + + /** + * 删除考试任务图片管ç†ä¿¡æ¯ + * + * @param photoCode 考试任务图片管ç†ID + * @return 结果 + */ + @Override + public int deleteExamTaskPictureById(String photoCode) + { + return examTaskPictureMapper.deleteExamTaskPictureById(photoCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskQuestionsServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskQuestionsServiceImpl.java new file mode 100644 index 0000000..4fb96ae --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/exam/service/impl/ExamTaskQuestionsServiceImpl.java @@ -0,0 +1,113 @@ +package com.yanzhu.exam.exam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.exam.mapper.ExamTaskQuestionsMapper; +import com.yanzhu.exam.exam.domain.ExamTaskQuestions; +import com.yanzhu.exam.exam.service.IExamTaskQuestionsService; + +/** + * 任务题目Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-10 + */ +@Service +public class ExamTaskQuestionsServiceImpl implements IExamTaskQuestionsService +{ + @Autowired + private ExamTaskQuestionsMapper examTaskQuestionsMapper; + + /** + * 查询任务题目 + * + * @param examCode 任务题目ID + * @return 任务题目 + */ + @Override + public ExamTaskQuestions selectExamTaskQuestionsById(String examCode) + { + return examTaskQuestionsMapper.selectExamTaskQuestionsById(examCode); + } + + /** + * 查询任务题目列表 + * + * @param examTaskQuestions 任务题目 + * @return 任务题目 + */ + @Override + public List selectExamTaskQuestionsList(ExamTaskQuestions examTaskQuestions) + { + return examTaskQuestionsMapper.selectExamTaskQuestionsList(examTaskQuestions); + } + + /** + * 新增任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + @Override + public int insertExamTaskQuestions(ExamTaskQuestions examTaskQuestions) + { + return examTaskQuestionsMapper.insertExamTaskQuestions(examTaskQuestions); + } + + /** + * 修改任务题目 + * + * @param examTaskQuestions 任务题目 + * @return 结果 + */ + @Override + public int updateExamTaskQuestions(ExamTaskQuestions examTaskQuestions) + { + return examTaskQuestionsMapper.updateExamTaskQuestions(examTaskQuestions); + } + + /** + * 批é‡åˆ é™¤ä»»åŠ¡é¢˜ç›® + * + * @param examCodes 需è¦åˆ é™¤çš„任务题目ID + * @return 结果 + */ + @Override + public int deleteExamTaskQuestionsByIds(String[] examCodes) + { + return examTaskQuestionsMapper.deleteExamTaskQuestionsByIds(examCodes); + } + + /** + * åˆ é™¤ä»»åŠ¡é¢˜ç›®ä¿¡æ¯ + * + * @param examCode 任务题目ID + * @return 结果 + */ + @Override + public int deleteExamTaskQuestionsById(String examCode) + { + return examTaskQuestionsMapper.deleteExamTaskQuestionsById(examCode); + } + + @Override + public int batchUpdateExamTaskQuestions(List examTaskQuestionsList) throws Exception { + // TODO Auto-generated method stub + // 安全删除 + + examTaskQuestionsMapper.deleteExamTaskQuestionsById(examTaskQuestionsList.get(0).getExamCode()); + + for(ExamTaskQuestions examTaskQuestions: examTaskQuestionsList) { + try + { + examTaskQuestionsMapper.insertExamTaskQuestions(examTaskQuestions); + } + catch(Exception e) { + throw new Exception("ä¿å­˜é¢˜ç›®ä¿¡æ¯å‡ºé”™,ä¿¡æ¯:" + e.getMessage()); + } + + } + return 1; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/common/NotSameFileExpection.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/common/NotSameFileExpection.java new file mode 100644 index 0000000..bd04409 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/common/NotSameFileExpection.java @@ -0,0 +1,7 @@ +package com.yanzhu.exam.fms.common; + +public class NotSameFileExpection extends Exception { + public NotSameFileExpection() { + super("File MD5 Different"); + } +} \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsFilesController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsFilesController.java new file mode 100644 index 0000000..fc708d3 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsFilesController.java @@ -0,0 +1,195 @@ +package com.yanzhu.exam.fms.controller; + +import java.io.File; +import java.util.Date; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.date.DateUtil; +import org.springframework.security.access.prepost.PreAuthorize; +import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.fms.common.NotSameFileExpection; +import com.yanzhu.exam.fms.domain.FmsFiles; +import com.yanzhu.exam.fms.domain.MultipartFileParam; +import com.yanzhu.exam.fms.domain.dto.StdOut; +import com.yanzhu.exam.fms.service.ChunkService; +import com.yanzhu.exam.fms.service.IFmsFilesService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 文件管ç†Controller + * + * @author qnsdt + * @date 2021-12-17 + */ +@RestController +@RequestMapping("/fms/files") +public class FmsFilesController extends BaseController +{ + @Autowired + private IFmsFilesService fmsFilesService; + + @Autowired + ChunkService chunkService; + + @Value("${cms.files.photo-path}") + private String filespath; + + /** + * 查询文件管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('fms:files:list')") + @GetMapping("/list") + public TableDataInfo list(FmsFiles fmsFiles) + { + startPage(); + List list = fmsFilesService.selectFmsFilesList(fmsFiles); + // System.out.println("文件列表:" + list.toString()); + return getDataTable(list); + } + + /** + * 导出文件管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('fms:files:export')") + @Log(title = "文件管ç†", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(FmsFiles fmsFiles) + { + List list = fmsFilesService.selectFmsFilesList(fmsFiles); + ExcelUtil util = new ExcelUtil(FmsFiles.class); + return util.exportExcel(list, "æ–‡ä»¶ç®¡ç†æ•°æ®"); + } + + /** + * èŽ·å–æ–‡ä»¶ç®¡ç†è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('fms:files:query')") + @GetMapping(value = "/{fileId}") + public AjaxResult getInfo(@PathVariable("fileId") Long fileId) + { + return AjaxResult.success(fmsFilesService.selectFmsFilesById(fileId)); + } + + /** + * æ–°å¢žæ–‡ä»¶ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('fms:files:add')") + @Log(title = "文件管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody FmsFiles fmsFiles) + { + return toAjax(fmsFilesService.insertFmsFiles(fmsFiles)); + } + + @RequestMapping("/chunkupload/{guid}/{username}") + // @PostMapping(value = "/chunkupload") + public StdOut chunkUpload(@PathVariable String guid,@PathVariable String username,MultipartFileParam param, HttpServletRequest request, HttpServletResponse response) { + StdOut out = new StdOut(); + + // 在此更æ¢è·¯å¾„ + // File file = new File("D:\\chunk_test");//存储路径 + // 拼接路径 + String fileurl = filespath + "/" + DateUtil.format(new Date(),"yyyyMMddHHmmss") + "/" + guid ; + // System.out.println("拼接地å€ä¸º:" + fileurl); + String filepath = RuoYiConfig.getProfile() + fileurl; + // System.out.println("拼接路径为:" + filepath); + File file = new File(filepath);//存储路径 + + + String path = file.getAbsolutePath(); + response.setContentType("text/html;charset=UTF-8"); + + try { + //判断å‰ç«¯Formè¡¨å•æ ¼å¼æ˜¯å¦æ”¯æŒæ–‡ä»¶ä¸Šä¼  + boolean isMultipart = ServletFileUpload.isMultipartContent(request); + if (!isMultipart) { + out.setCode(StdOut.PARAMETER_NULL); + out.setMessage("è¡¨å•æ ¼å¼é”™è¯¯"); + return out; + } else { + param.setTaskId(param.getIdentifier()); + out.setModel(chunkService.chunkUploadByMappedByteBuffer(param, path)); + // System.out.println("ä¿å­˜åŽ:" + out.toString()); + if (out.getModel() != null) { + // System.out.println("文件å:" + out.getModel().toString()); + // ä¿å­˜æ–‡ä»¶ä¿¡æ¯ + // å–得文件å + String filename = out.getModel().toString(); + // å–æ–‡ä»¶ç±»åž‹ + String suffix = getSuffix(filename); + + // 开始ä¿å­˜ + // String fileTitle, String fileDescribe, String fileName, String filePath, String fileUrl, + // String fileSuffix, String originalName, String uploadName + FmsFiles fmsFiles = new FmsFiles(null, null, filename, filepath, fileurl, suffix, filename, username); + System.out.println(fmsFiles.toString()); + int count = fmsFilesService.insertFmsFiles(fmsFiles); + + } + return out; + } + } catch (NotSameFileExpection e) { + out.setCode(StdOut.FAIL); + out.setMessage("MD5校验失败"); + return out; + } catch (Exception e) { + out.setCode(StdOut.FAIL); + out.setMessage("上传失败"); + return out; + } + } + + private String getSuffix(String filename) { + String suffix = null; + try + { + suffix = filename.substring(filename.lastIndexOf(".") + 1); + } + catch(Exception e) { + + } + + return suffix; + } + /** + * ä¿®æ”¹æ–‡ä»¶ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('fms:files:edit')") + @Log(title = "文件管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody FmsFiles fmsFiles) + { + System.out.println("fmsFiles:" + fmsFiles.toString()); + return toAjax(fmsFilesService.updateFmsFiles(fmsFiles)); + } + + /** + * åˆ é™¤æ–‡ä»¶ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('fms:files:remove')") + @Log(title = "文件管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{fileIds}") + public AjaxResult remove(@PathVariable Long[] fileIds) + { + return toAjax(fmsFilesService.deleteFmsFilesByIds(fileIds)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsPhotoController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsPhotoController.java new file mode 100644 index 0000000..0d61a8b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/controller/FmsPhotoController.java @@ -0,0 +1,181 @@ +package com.yanzhu.exam.fms.controller; + +import java.util.Date; +import java.util.List; + +import cn.hutool.core.date.DateUtil; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.cms.utils.FileUpload; +import com.yanzhu.exam.fms.domain.FmsPhoto; +import com.yanzhu.exam.fms.service.IFmsPhotoService; + +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 图片管ç†Controller + * + * @author qnsdt + * @date 2021-12-14 + */ +@RestController +@RequestMapping("/fms/photo") +public class FmsPhotoController extends BaseController +{ + @Autowired + private IFmsPhotoService fmsPhotoService; + + @Value("${cms.fms.photo-path}") + private String fmspath; + + private TokenService tokenService; + + /** + * 查询图片管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('fms:photo:list')") + @GetMapping("/list") + public TableDataInfo list(FmsPhoto fmsPhoto) + { + startPage(); + List list = fmsPhotoService.selectFmsPhotoList(fmsPhoto); + return getDataTable(list); + } + + /** + * 导出图片管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('fms:photo:export')") + @Log(title = "图片管ç†", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(FmsPhoto fmsPhoto) + { + List list = fmsPhotoService.selectFmsPhotoList(fmsPhoto); + ExcelUtil util = new ExcelUtil(FmsPhoto.class); + return util.exportExcel(list, "å›¾ç‰‡ç®¡ç†æ•°æ®"); + } + + /** + * 获å–图片管ç†è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('fms:photo:query')") + @GetMapping(value = "/{photoId}") + public AjaxResult getInfo(@PathVariable("photoId") Long photoId) + { + return AjaxResult.success(fmsPhotoService.selectFmsPhotoById(photoId)); + } + + /** + * æ–°å¢žå›¾ç‰‡ç®¡ç† + */ + // @PreAuthorize("@ss.hasPermi('fms:photo:add')") + // @Log(title = "图片管ç†", businessType = BusinessType.INSERT) + @PostMapping(value = "/add/{username}") + public AjaxResult add(@PathVariable String username,@RequestParam("file") MultipartFile file) + { + if (username == null || username.trim().equals("")) { + return AjaxResult.error("用户åä¸èƒ½ä¸ºç©º"); + } + System.out.println("当剿—¥æœŸ:" + DateUtil.format(new Date(),"yyyyMMddHHmmss")); + // å–得原始文件å + String originalfile = file.getOriginalFilename(); + + // 拼接路径 + String path = RuoYiConfig.getProfile() + fmspath + "/" + DateUtil.format(new Date(),"yyyyMMddHHmmss"); + System.out.println("拼接路径为:" + path); + String filename = FileUpload.writeUploadFile(file,path); + String fileurl = fmspath + "/" + DateUtil.format(new Date(),"yyyyMMddHHmmss") + "/" + filename; + System.out.println(fileurl); + + + int count = 0; + + // System.out.println("photoid:" + swipperid); + + System.out.println("RuoYiConfig.getProfile()" + RuoYiConfig.getProfile()); + + /*LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + SysUser user = loginUser.getUser(); + + System.out.println("å–得用户信æ¯:" + user.toString());*/ + + // String fileName, String photoPath, String photoUrl, String originalName, String uploadName,String uploadDept, Long status + FmsPhoto fmsPhoto = new FmsPhoto(filename, path, fileurl, originalfile, username, "", (long) 0); + + // System.out.println("fmsPhoto:" + fmsPhoto.toString()); + try + { + return toAjax(fmsPhotoService.insertFmsPhoto(fmsPhoto)); + } + catch(Exception e) + { + return AjaxResult.error(e.getMessage()); + } + // select photo_id,file_name,photo_path,photo_url,original_name,upload_name,upload_dept,upload_time,status from fms_photo; + + // 相应赋值 + //int photoId, int swipperId, String photoPath, String photoUrl, String fileName,String originalName + + /*SysSwipper sysSwipper = new SysSwipper(Integer.parseInt(swipperid), path, fileurl, filename, originalfile); + + System.out.println("sysSwipper:" + sysSwipper.toString()); + try + { + count = swipperService.insertSwipper(sysSwipper); + } + catch(Exception e) + { + return AjaxResult.error(e.getMessage()); + }*/ + + // FmsPhoto fmsPhoto + + // return AjaxResult.success(sysSwipper); + + + } + + /** + * ä¿®æ”¹å›¾ç‰‡ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('fms:photo:edit')") + @Log(title = "图片管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody FmsPhoto fmsPhoto) + { + return toAjax(fmsPhotoService.updateFmsPhoto(fmsPhoto)); + } + + /** + * åˆ é™¤å›¾ç‰‡ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('fms:photo:remove')") + @Log(title = "图片管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{photoIds}") + public AjaxResult remove(@PathVariable Long[] photoIds) + { + return toAjax(fmsPhotoService.deleteFmsPhotoByIds(photoIds)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsFiles.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsFiles.java new file mode 100644 index 0000000..7b04074 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsFiles.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.fms.domain; + +import java.util.Date; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; + +import lombok.Data; + +@Data +public class FmsFiles { + /** 文件åºå· */ + private int fileId; + + /** 文件标题 */ + @Excel(name = "文件标题") + private String fileTitle; + + /** 文件æè¿° */ + @Excel(name = "文件æè¿°") + private String fileDescribe; + + /** 文件åç§° */ + private String fileName; + + /** 文件路径 */ + private String filePath; + + /** 文件链接 */ + private String fileUrl; + + /** 文件类型 */ + private String fileSuffix; + + /** 原始åç§° */ + private String originalName; + + /** 上传者 */ + @Excel(name = "上传者") + private String uploadName; + + /** 上传部门 */ + private String uploadDept; + + /** 上传时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "上传时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date uploadTime; + + /** çŠ¶æ€ */ + private int status; + + public FmsFiles() { + super(); + } + + public FmsFiles(String fileTitle, String fileDescribe, String fileName, String filePath, String fileUrl, + String fileSuffix, String originalName, String uploadName) { + super(); + this.fileTitle = fileTitle; + this.fileDescribe = fileDescribe; + this.fileName = fileName; + this.filePath = filePath; + this.fileUrl = fileUrl; + this.fileSuffix = fileSuffix; + this.originalName = originalName; + this.uploadName = uploadName; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("fileId", getFileId()) + .append("fileTitle", getFileTitle()) + .append("fileDescribe", getFileDescribe()) + .append("fileName", getFileName()) + .append("filePath", getFilePath()) + .append("fileUrl", getFileUrl()) + .append("fileSuffix", getFileSuffix()) + .append("originalName", getOriginalName()) + .append("uploadName", getUploadName()) + .append("uploadDept", getUploadDept()) + .append("uploadTime", getUploadTime()) + .append("status", getStatus()) + .toString(); + } + + + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsPhoto.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsPhoto.java new file mode 100644 index 0000000..a3d3309 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/FmsPhoto.java @@ -0,0 +1,166 @@ +package com.yanzhu.exam.fms.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 图片管ç†å¯¹è±¡ fms_photo + * + * @author qnsdt + * @date 2021-12-14 + */ +public class FmsPhoto extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 图片åºå· */ + @Excel(name = "图片åºå·") + private Long photoId; + + /** 文件åç§° */ + @Excel(name = "文件åç§°") + private String fileName; + + /** 图片路径 */ + @Excel(name = "图片路径") + private String photoPath; + + /** 图片链接 */ + @Excel(name = "图片链接") + private String photoUrl; + + /** 原始åç§° */ + @Excel(name = "原始åç§°") + private String originalName; + + /** 上传者 */ + @Excel(name = "上传者") + private String uploadName; + + /** 上传部门 */ + @Excel(name = "上传部门") + private String uploadDept; + + /** 上传时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "上传时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date uploadTime; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + public void setPhotoId(Long photoId) + { + this.photoId = photoId; + } + + public Long getPhotoId() + { + return photoId; + } + public void setFileName(String fileName) + { + this.fileName = fileName; + } + + public String getFileName() + { + return fileName; + } + public void setPhotoPath(String photoPath) + { + this.photoPath = photoPath; + } + + public String getPhotoPath() + { + return photoPath; + } + public void setPhotoUrl(String photoUrl) + { + this.photoUrl = photoUrl; + } + + public String getPhotoUrl() + { + return photoUrl; + } + public void setOriginalName(String originalName) + { + this.originalName = originalName; + } + + public String getOriginalName() + { + return originalName; + } + public void setUploadName(String uploadName) + { + this.uploadName = uploadName; + } + + public String getUploadName() + { + return uploadName; + } + public void setUploadDept(String uploadDept) + { + this.uploadDept = uploadDept; + } + + public String getUploadDept() + { + return uploadDept; + } + public void setUploadTime(Date uploadTime) + { + this.uploadTime = uploadTime; + } + + public Date getUploadTime() + { + return uploadTime; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + + + public FmsPhoto(String fileName, String photoPath, String photoUrl, String originalName, String uploadName, + String uploadDept, Long status) { + super(); + this.fileName = fileName; + this.photoPath = photoPath; + this.photoUrl = photoUrl; + this.originalName = originalName; + this.uploadName = uploadName; + this.uploadDept = uploadDept; + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("photoId", getPhotoId()) + .append("fileName", getFileName()) + .append("photoPath", getPhotoPath()) + .append("photoUrl", getPhotoUrl()) + .append("originalName", getOriginalName()) + .append("uploadName", getUploadName()) + .append("uploadDept", getUploadDept()) + .append("uploadTime", getUploadTime()) + .append("status", getStatus()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/MultipartFileParam.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/MultipartFileParam.java new file mode 100644 index 0000000..7b313b0 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/MultipartFileParam.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.fms.domain; + +import org.springframework.web.multipart.MultipartFile; + +public class MultipartFileParam { + private String taskId; + private int chunkNumber; + private long chunkSize; + private int totalChunks; + private String identifier; + private MultipartFile file; + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public int getChunkNumber() { + return chunkNumber; + } + + public void setChunkNumber(int chunkNumber) { + this.chunkNumber = chunkNumber; + } + + public long getChunkSize() { + return chunkSize; + } + + public void setChunkSize(long chunkSize) { + this.chunkSize = chunkSize; + } + + public int getTotalChunks() { + return totalChunks; + } + + public void setTotalChunks(int totalChunks) { + this.totalChunks = totalChunks; + } + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public MultipartFile getFile() { + return file; + } + + public void setFile(MultipartFile file) { + this.file = file; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/dto/StdOut.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/dto/StdOut.java new file mode 100644 index 0000000..8e08821 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/domain/dto/StdOut.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.fms.domain.dto; + +import java.util.List; +import java.util.Map; + +import com.alibaba.fastjson2.JSON; + +public class StdOut { + public static final int SUCCESS = 200; + public static final int FAIL = 400; + public static final int PARAMETER_NULL = 500; + public static final int NO_LOGIN = 600; + private int code = 200; + private Object model = null; + private String message = null; + + public StdOut() { + this.setCode(200); + this.setModel((Object)null); + } + + public StdOut(int code) { + this.setCode(code); + this.setModel((Object)null); + } + + public StdOut(List> model) { + this.setCode(200); + this.setModel(model); + } + + public StdOut(int code, List> model) { + this.setCode(code); + this.setModel(model); + } + + public int getCode() { + return this.code; + } + + public void setCode(int code) { + this.code = code; + } + + public String toString() { + return JSON.toJSONString(this); + } + + public Object getModel() { + return this.model; + } + + public void setModel(Object model) { + this.model = model; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsFilesMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsFilesMapper.java new file mode 100644 index 0000000..985c195 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsFilesMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.fms.mapper; + +import java.util.List; +import com.yanzhu.exam.fms.domain.FmsFiles; + +/** + * 文件管ç†MapperæŽ¥å£ + * + * @author qnsdt + * @date 2021-12-17 + */ +public interface FmsFilesMapper +{ + /** + * æŸ¥è¯¢æ–‡ä»¶ç®¡ç† + * + * @param fileId 文件管ç†ID + * @return æ–‡ä»¶ç®¡ç† + */ + public FmsFiles selectFmsFilesById(Long fileId); + + /** + * 查询文件管ç†åˆ—表 + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 文件管ç†é›†åˆ + */ + public List selectFmsFilesList(FmsFiles fmsFiles); + + /** + * æ–°å¢žæ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + public int insertFmsFiles(FmsFiles fmsFiles); + + /** + * ä¿®æ”¹æ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + public int updateFmsFiles(FmsFiles fmsFiles); + + /** + * åˆ é™¤æ–‡ä»¶ç®¡ç† + * + * @param fileId 文件管ç†ID + * @return 结果 + */ + public int deleteFmsFilesById(Long fileId); + + /** + * 批é‡åˆ é™¤æ–‡ä»¶ç®¡ç† + * + * @param fileIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteFmsFilesByIds(Long[] fileIds); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsPhotoMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsPhotoMapper.java new file mode 100644 index 0000000..ed1ee64 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/mapper/FmsPhotoMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.fms.mapper; + +import java.util.List; +import com.yanzhu.exam.fms.domain.FmsPhoto; + +/** + * 图片管ç†MapperæŽ¥å£ + * + * @author qnsdt + * @date 2021-12-14 + */ +public interface FmsPhotoMapper +{ + /** + * æŸ¥è¯¢å›¾ç‰‡ç®¡ç† + * + * @param photoId 图片管ç†ID + * @return å›¾ç‰‡ç®¡ç† + */ + public FmsPhoto selectFmsPhotoById(Long photoId); + + /** + * 查询图片管ç†åˆ—表 + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 图片管ç†é›†åˆ + */ + public List selectFmsPhotoList(FmsPhoto fmsPhoto); + + /** + * æ–°å¢žå›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int insertFmsPhoto(FmsPhoto fmsPhoto); + + /** + * ä¿®æ”¹å›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int updateFmsPhoto(FmsPhoto fmsPhoto); + + /** + * åˆ é™¤å›¾ç‰‡ç®¡ç† + * + * @param photoId 图片管ç†ID + * @return 结果 + */ + public int deleteFmsPhotoById(Long photoId); + + /** + * 批é‡åˆ é™¤å›¾ç‰‡ç®¡ç† + * + * @param photoIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteFmsPhotoByIds(Long[] photoIds); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/ChunkService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/ChunkService.java new file mode 100644 index 0000000..e39250d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/ChunkService.java @@ -0,0 +1,16 @@ +package com.yanzhu.exam.fms.service; + +import java.io.File; +import java.io.IOException; + +import com.yanzhu.exam.fms.common.NotSameFileExpection; +import com.yanzhu.exam.fms.domain.MultipartFileParam; + + +public interface ChunkService { + public String chunkUploadByMappedByteBuffer(MultipartFileParam param, String filePath) throws IOException, NotSameFileExpection; + + public void renameFile(File toBeRenamed, String toFileNewName); + + public boolean checkUploadStatus(MultipartFileParam param, String fileName, String filePath) throws IOException; +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsFilesService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsFilesService.java new file mode 100644 index 0000000..b231005 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsFilesService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.fms.service; + +import java.util.List; +import com.yanzhu.exam.fms.domain.FmsFiles; + +/** + * 文件管ç†ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2021-12-17 + */ +public interface IFmsFilesService +{ + /** + * æŸ¥è¯¢æ–‡ä»¶ç®¡ç† + * + * @param fileId 文件管ç†ID + * @return æ–‡ä»¶ç®¡ç† + */ + public FmsFiles selectFmsFilesById(Long fileId); + + /** + * 查询文件管ç†åˆ—表 + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 文件管ç†é›†åˆ + */ + public List selectFmsFilesList(FmsFiles fmsFiles); + + /** + * æ–°å¢žæ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + public int insertFmsFiles(FmsFiles fmsFiles); + + /** + * ä¿®æ”¹æ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + public int updateFmsFiles(FmsFiles fmsFiles); + + /** + * 批é‡åˆ é™¤æ–‡ä»¶ç®¡ç† + * + * @param fileIds 需è¦åˆ é™¤çš„æ–‡ä»¶ç®¡ç†ID + * @return 结果 + */ + public int deleteFmsFilesByIds(Long[] fileIds); + + /** + * 删除文件管ç†ä¿¡æ¯ + * + * @param fileId 文件管ç†ID + * @return 结果 + */ + public int deleteFmsFilesById(Long fileId); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsPhotoService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsPhotoService.java new file mode 100644 index 0000000..1d43261 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/IFmsPhotoService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.fms.service; + +import java.util.List; +import com.yanzhu.exam.fms.domain.FmsPhoto; + +/** + * 图片管ç†ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2021-12-14 + */ +public interface IFmsPhotoService +{ + /** + * æŸ¥è¯¢å›¾ç‰‡ç®¡ç† + * + * @param photoId 图片管ç†ID + * @return å›¾ç‰‡ç®¡ç† + */ + public FmsPhoto selectFmsPhotoById(Long photoId); + + /** + * 查询图片管ç†åˆ—表 + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 图片管ç†é›†åˆ + */ + public List selectFmsPhotoList(FmsPhoto fmsPhoto); + + /** + * æ–°å¢žå›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int insertFmsPhoto(FmsPhoto fmsPhoto); + + /** + * ä¿®æ”¹å›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + public int updateFmsPhoto(FmsPhoto fmsPhoto); + + /** + * 批é‡åˆ é™¤å›¾ç‰‡ç®¡ç† + * + * @param photoIds 需è¦åˆ é™¤çš„图片管ç†ID + * @return 结果 + */ + public int deleteFmsPhotoByIds(Long[] photoIds); + + /** + * 删除图片管ç†ä¿¡æ¯ + * + * @param photoId 图片管ç†ID + * @return 结果 + */ + public int deleteFmsPhotoById(Long photoId); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/ChunkServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/ChunkServiceImpl.java new file mode 100644 index 0000000..8ed8ef3 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/ChunkServiceImpl.java @@ -0,0 +1,104 @@ +package com.yanzhu.exam.fms.service.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.UUID; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.fms.common.NotSameFileExpection; +import com.yanzhu.exam.fms.domain.MultipartFileParam; +import com.yanzhu.exam.fms.service.ChunkService; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.FileUtils; + + +@Service +public class ChunkServiceImpl implements ChunkService { + + @Override + public String chunkUploadByMappedByteBuffer(MultipartFileParam param, String filePath) throws IOException, NotSameFileExpection { + // TODO Auto-generated method stub + if (param.getTaskId() == null || "".equals(param.getTaskId())) { + param.setTaskId(UUID.randomUUID().toString()); + } + + String fileName = param.getFile().getOriginalFilename(); + String tempFileName = param.getTaskId() + fileName.substring(fileName.lastIndexOf(".")) + "_tmp"; + File fileDir = new File(filePath); + if (!fileDir.exists()) { + fileDir.mkdirs(); + } + File tempFile = new File(filePath, tempFileName); + //第一步 打开将è¦å†™å…¥çš„æ–‡ä»¶ + RandomAccessFile raf = new RandomAccessFile(tempFile, "rw"); + //第二步 æ‰“å¼€é€šé“ + FileChannel fileChannel = raf.getChannel(); + //第三步 计算åç§»é‡ + long position = (param.getChunkNumber() - 1) * param.getChunkSize(); + //第四步 获å–åˆ†ç‰‡æ•°æ® + byte[] fileData = param.getFile().getBytes(); + //第五步 å†™å…¥æ•°æ® + fileChannel.position(position); + fileChannel.write(ByteBuffer.wrap(fileData)); + fileChannel.force(true); + fileChannel.close(); + raf.close(); + //判断是å¦å®Œæˆæ–‡ä»¶çš„传输并进行校验与é‡å‘½å + boolean isComplete = checkUploadStatus(param, fileName, filePath); + if (isComplete) { + FileInputStream fileInputStream = new FileInputStream(tempFile.getPath()); + String md5 = DigestUtils.md5Hex(fileInputStream); + fileInputStream.close(); + if (StringUtils.isNotBlank(md5) && !md5.equals(param.getIdentifier())) { + throw new NotSameFileExpection(); + } + renameFile(tempFile, fileName); + return fileName; + } + return null; + } + + @Override + public void renameFile(File toBeRenamed, String toFileNewName) { + // TODO Auto-generated method stub + if (!toBeRenamed.exists() || toBeRenamed.isDirectory()) { + System.err.println("文件ä¸å­˜åœ¨"); + return; + } + String p = toBeRenamed.getParent(); + File newFile = new File(p + File.separatorChar + toFileNewName); + toBeRenamed.renameTo(newFile); + + } + + @Override + public boolean checkUploadStatus(MultipartFileParam param, String fileName, String filePath) throws IOException { + // TODO Auto-generated method stub + File confFile = new File(filePath, fileName + ".conf"); + RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw"); + //设置文件长度 + confAccessFile.setLength(param.getTotalChunks()); + //设置起始åç§»é‡ + confAccessFile.seek(param.getChunkNumber() - 1); + //将指定的一个字节写入文件中 127, + confAccessFile.write(Byte.MAX_VALUE); + byte[] completeStatusList = FileUtils.readFileToByteArray(confFile); + confAccessFile.close();//ä¸å…³é—­ä¼šé€ æˆæ— æ³•å ç”¨ + //创建conf文件文件长度为总分片数,æ¯ä¸Šä¼ ä¸€ä¸ªåˆ†å—å³å‘conf文件中写入一个127,那么没上传的ä½ç½®å°±æ˜¯é»˜è®¤çš„0,已上传的就是127 + for (int i = 0; i < completeStatusList.length; i++) { + if (completeStatusList[i] != Byte.MAX_VALUE) { + return false; + } + } + confFile.delete(); + return true; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsFilesServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsFilesServiceImpl.java new file mode 100644 index 0000000..e497595 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsFilesServiceImpl.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.fms.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.fms.mapper.FmsFilesMapper; +import com.yanzhu.exam.fms.domain.FmsFiles; +import com.yanzhu.exam.fms.service.IFmsFilesService; + +/** + * 文件管ç†Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2021-12-17 + */ +@Service +public class FmsFilesServiceImpl implements IFmsFilesService +{ + @Autowired + private FmsFilesMapper fmsFilesMapper; + + /** + * æŸ¥è¯¢æ–‡ä»¶ç®¡ç† + * + * @param fileId 文件管ç†ID + * @return æ–‡ä»¶ç®¡ç† + */ + @Override + public FmsFiles selectFmsFilesById(Long fileId) + { + return fmsFilesMapper.selectFmsFilesById(fileId); + } + + /** + * 查询文件管ç†åˆ—表 + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return æ–‡ä»¶ç®¡ç† + */ + @Override + public List selectFmsFilesList(FmsFiles fmsFiles) + { + return fmsFilesMapper.selectFmsFilesList(fmsFiles); + } + + /** + * æ–°å¢žæ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + @Override + public int insertFmsFiles(FmsFiles fmsFiles) + { + return fmsFilesMapper.insertFmsFiles(fmsFiles); + } + + /** + * ä¿®æ”¹æ–‡ä»¶ç®¡ç† + * + * @param fmsFiles æ–‡ä»¶ç®¡ç† + * @return 结果 + */ + @Override + public int updateFmsFiles(FmsFiles fmsFiles) + { + return fmsFilesMapper.updateFmsFiles(fmsFiles); + } + + /** + * 批é‡åˆ é™¤æ–‡ä»¶ç®¡ç† + * + * @param fileIds 需è¦åˆ é™¤çš„æ–‡ä»¶ç®¡ç†ID + * @return 结果 + */ + @Override + public int deleteFmsFilesByIds(Long[] fileIds) + { + return fmsFilesMapper.deleteFmsFilesByIds(fileIds); + } + + /** + * 删除文件管ç†ä¿¡æ¯ + * + * @param fileId 文件管ç†ID + * @return 结果 + */ + @Override + public int deleteFmsFilesById(Long fileId) + { + return fmsFilesMapper.deleteFmsFilesById(fileId); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsPhotoServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsPhotoServiceImpl.java new file mode 100644 index 0000000..f6a37ba --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/service/impl/FmsPhotoServiceImpl.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.fms.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.fms.mapper.FmsPhotoMapper; +import com.yanzhu.exam.fms.domain.FmsPhoto; +import com.yanzhu.exam.fms.service.IFmsPhotoService; + +/** + * 图片管ç†Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2021-12-14 + */ +@Service +public class FmsPhotoServiceImpl implements IFmsPhotoService +{ + @Autowired + private FmsPhotoMapper fmsPhotoMapper; + + /** + * æŸ¥è¯¢å›¾ç‰‡ç®¡ç† + * + * @param photoId 图片管ç†ID + * @return å›¾ç‰‡ç®¡ç† + */ + @Override + public FmsPhoto selectFmsPhotoById(Long photoId) + { + return fmsPhotoMapper.selectFmsPhotoById(photoId); + } + + /** + * 查询图片管ç†åˆ—表 + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return å›¾ç‰‡ç®¡ç† + */ + @Override + public List selectFmsPhotoList(FmsPhoto fmsPhoto) + { + return fmsPhotoMapper.selectFmsPhotoList(fmsPhoto); + } + + /** + * æ–°å¢žå›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + @Override + public int insertFmsPhoto(FmsPhoto fmsPhoto) + { + return fmsPhotoMapper.insertFmsPhoto(fmsPhoto); + } + + /** + * ä¿®æ”¹å›¾ç‰‡ç®¡ç† + * + * @param fmsPhoto å›¾ç‰‡ç®¡ç† + * @return 结果 + */ + @Override + public int updateFmsPhoto(FmsPhoto fmsPhoto) + { + return fmsPhotoMapper.updateFmsPhoto(fmsPhoto); + } + + /** + * 批é‡åˆ é™¤å›¾ç‰‡ç®¡ç† + * + * @param photoIds 需è¦åˆ é™¤çš„图片管ç†ID + * @return 结果 + */ + @Override + public int deleteFmsPhotoByIds(Long[] photoIds) + { + return fmsPhotoMapper.deleteFmsPhotoByIds(photoIds); + } + + /** + * 删除图片管ç†ä¿¡æ¯ + * + * @param photoId 图片管ç†ID + * @return 结果 + */ + @Override + public int deleteFmsPhotoById(Long photoId) + { + return fmsPhotoMapper.deleteFmsPhotoById(photoId); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/FileUpload.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/FileUpload.java new file mode 100644 index 0000000..5037b2a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/FileUpload.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.fms.utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.springframework.web.multipart.MultipartFile; + +public class FileUpload { + /** + * æ–‡ä»¶ä¸Šä¼ å¤„ç† + * + * @param file + * @return + */ + public static String writeUploadFile(MultipartFile file,String path) { + String filename = file.getOriginalFilename(); + System.out.println("原始文件å:" + filename); + // String realpath = "D:/image/photo/" + module +"/"; + File fileDir = new File(path); + if (!fileDir.exists()) + fileDir.mkdirs(); + + String extname = FilenameUtils.getExtension(filename); + String allowImgFormat = "gif,jpg,jpeg,png"; + if (!allowImgFormat.contains(extname.toLowerCase())) { + return "NOT_IMAGE"; + } + + filename = Math.abs(file.getOriginalFilename().hashCode()) + RandomUtils.createRandomString( 4 ) + "." + extname; + InputStream input = null; + FileOutputStream fos = null; + try { + input = file.getInputStream(); + fos = new FileOutputStream(path + "/" + filename); + IOUtils.copy(input, fos); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + /*IOUtils.closeQuietly(input); + IOUtils.closeQuietly(fos);*/ + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + } + return filename; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/RandomUtils.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/RandomUtils.java new file mode 100644 index 0000000..c619a08 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/fms/utils/RandomUtils.java @@ -0,0 +1,35 @@ +package com.yanzhu.exam.fms.utils; + +public class RandomUtils { + private static final String charlist = "0123456789"; + + public static String createRandomString(int len) { + String str = new String(); + for (int i = 0; i < len; i++) { + str += charlist.charAt(getRandom(charlist.length())); + } + return str; + } + + public static int getRandom(int mod) { + if (mod < 1) { + return 0; + } + int ret = getInt() % mod; + return ret; + } + + private static int getInt() { + int ret = Math.abs(Long.valueOf(getRandomNumString()).intValue()); + return ret; + } + + private static String getRandomNumString() { + double d = Math.random(); + String dStr = String.valueOf(d).replaceAll("[^\\d]", ""); + if (dStr.length() > 1) { + dStr = dStr.substring(0, dStr.length() - 1); + } + return dStr; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamFinishAnswerController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamFinishAnswerController.java new file mode 100644 index 0000000..ee59ffe --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamFinishAnswerController.java @@ -0,0 +1,113 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.onlineexam.domain.ExamFinishAnswer; +import com.yanzhu.exam.onlineexam.service.IExamFinishAnswerService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试æˆç»©Controller + * + * @author qnsdt + * @date 2023-02-24 + */ +@RestController +@RequestMapping("/onlineexam/finishanswer") +public class ExamFinishAnswerController extends BaseController +{ + @Autowired + private IExamFinishAnswerService examFinishAnswerService; + + /** + * 查询考试æˆç»©åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:list')") + @GetMapping("/list") + public TableDataInfo list(ExamFinishAnswer examFinishAnswer) + { + startPage(); + List list = examFinishAnswerService.selectExamFinishAnswerList(examFinishAnswer); + return getDataTable(list); + } + + /** + * 导出考试æˆç»©åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:export')") + @Log(title = "考试æˆç»©", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamFinishAnswer examFinishAnswer) + { + List list = examFinishAnswerService.selectExamFinishAnswerList(examFinishAnswer); + ExcelUtil util = new ExcelUtil(ExamFinishAnswer.class); + return util.exportExcel(list, "考试æˆç»©æ•°æ®"); + } + + /** + * 获å–考试æˆç»©è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:query')") + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examFinishAnswerService.selectExamFinishAnswerById(examCode)); + } + + /** + * 新增考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:add')") + @Log(title = "考试æˆç»©", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamFinishAnswer examFinishAnswer) + { + return toAjax(examFinishAnswerService.insertExamFinishAnswer(examFinishAnswer)); + } + + /** + * 维护考试æˆç»© + */ + @PostMapping("/save") + public AjaxResult save(@RequestBody ExamFinishAnswer examFinishAnswer) + { + System.out.println("examFinishAnswer:" + examFinishAnswer.toString()); + return toAjax(examFinishAnswerService.intoExamFinishAnswer(examFinishAnswer)); + } + + /** + * 修改考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:edit')") + @Log(title = "考试æˆç»©", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamFinishAnswer examFinishAnswer) + { + return toAjax(examFinishAnswerService.updateExamFinishAnswer(examFinishAnswer)); + } + + /** + * 删除考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:finishanswer:remove')") + @Log(title = "考试æˆç»©", businessType = BusinessType.DELETE) + @DeleteMapping("/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examFinishAnswerService.deleteExamFinishAnswerByIds(examCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsContentDataController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsContentDataController.java new file mode 100644 index 0000000..e1e5b50 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsContentDataController.java @@ -0,0 +1,55 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; + +import cn.hutool.core.date.DateUtil; +import com.yanzhu.exam.cms.utils.DigitUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsContentData; +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsData; +import com.yanzhu.exam.onlineexam.service.IExamQuestionsContentDataService; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; +import com.yanzhu.exam.questions.service.IExamQuestionsAnswerService; + +import com.ruoyi.common.core.domain.AjaxResult; + +@RestController +@RequestMapping("/onlineexam") +public class ExamQuestionsContentDataController { + @Autowired + private IExamQuestionsContentDataService examQuestionsContentDataService; + + @Autowired + private IExamQuestionsAnswerService examQuestionsAnswerService; + + @GetMapping("/content") + public AjaxResult option(@RequestBody ExamQuestionsContentData examQuestionsContentData) + { + ExamQuestionsContentData contentData = examQuestionsContentDataService.selectExamQuestionsContent(examQuestionsContentData); + return AjaxResult.success(contentData); + } + + @PostMapping("/data") + public AjaxResult data(@RequestBody ExamQuestionsContentData examQuestionsContentData) + { + ExamQuestionsContentData contentData = examQuestionsContentDataService.selectExamQuestionsContent(examQuestionsContentData); + + // 转æ¢é¢˜å· + + String str = DigitUtils.toChinese(String.valueOf(contentData.getQuestionsNumber())); + + contentData.setQuestionsNumberText("第" + str + "题"); + + List examQuestionsOptionList = examQuestionsAnswerService.selectExamQuestionsOptionList(examQuestionsContentData.getQuestionsCode()); + + ExamQuestionsData examQuestionsData = new ExamQuestionsData(contentData, examQuestionsOptionList); + return AjaxResult.success(examQuestionsData); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsListDataController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsListDataController.java new file mode 100644 index 0000000..50e3bcc --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamQuestionsListDataController.java @@ -0,0 +1,29 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsListData; +import com.yanzhu.exam.onlineexam.service.IExamQuestionsListDataService; +import com.ruoyi.common.core.domain.AjaxResult; + +@RestController +@RequestMapping("/onlineexam/questionslist") +public class ExamQuestionsListDataController { + + @Autowired + IExamQuestionsListDataService examQuestionsListDataService; + + @GetMapping() + public AjaxResult getQuestionsList(ExamQuestionsListData examQuestionsListData) + { + List examQuestionsList = examQuestionsListDataService.selectQuestionsList(examQuestionsListData); + return AjaxResult.success(examQuestionsList); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTaskAnswerController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTaskAnswerController.java new file mode 100644 index 0000000..0fceae9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTaskAnswerController.java @@ -0,0 +1,103 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.onlineexam.domain.ExamTaskAnswer; +import com.yanzhu.exam.onlineexam.service.IExamTaskAnswerService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试实时数æ®Controller + * + * @author qnsdt + * @date 2023-02-24 + */ +@RestController +@RequestMapping("/onlineexam/taskanswer") +public class ExamTaskAnswerController extends BaseController +{ + @Autowired + private IExamTaskAnswerService examTaskAnswerService; + + /** + * 查询考试实时数æ®åˆ—表 + */ + @GetMapping("/list") + public TableDataInfo list(ExamTaskAnswer examTaskAnswer) + { + startPage(); + List list = examTaskAnswerService.selectExamTaskAnswerList(examTaskAnswer); + return getDataTable(list); + } + + /** + * 导出考试实时数æ®åˆ—表 + */ + @GetMapping("/export") + public AjaxResult export(ExamTaskAnswer examTaskAnswer) + { + List list = examTaskAnswerService.selectExamTaskAnswerList(examTaskAnswer); + ExcelUtil util = new ExcelUtil(ExamTaskAnswer.class); + return util.exportExcel(list, "è€ƒè¯•å®žæ—¶æ•°æ®æ•°æ®"); + } + + /** + * 获å–考试实时数æ®è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examTaskAnswerService.selectExamTaskAnswerById(examCode)); + } + + /** + * æ–°å¢žè€ƒè¯•å®žæ—¶æ•°æ® + */ + @PostMapping + public AjaxResult add(@RequestBody ExamTaskAnswer examTaskAnswer) + { + + return toAjax(examTaskAnswerService.insertExamTaskAnswer(examTaskAnswer)); + } + + /** + * ä¿®æ”¹è€ƒè¯•å®žæ—¶æ•°æ® + */ + @PutMapping + public AjaxResult edit(@RequestBody ExamTaskAnswer examTaskAnswer) + { + return toAjax(examTaskAnswerService.updateExamTaskAnswer(examTaskAnswer)); + } + + /** + * åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + */ + @GetMapping("/remove/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examTaskAnswerService.deleteExamTaskAnswerByIds(examCodes)); + } + + /** + * åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + */ + @PostMapping("/delete") + public AjaxResult delete(ExamTaskAnswer examTaskAnswer) + { + return toAjax(examTaskAnswerService.deleteExamTaskAnswer(examTaskAnswer)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTitleController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTitleController.java new file mode 100644 index 0000000..0117c90 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamTitleController.java @@ -0,0 +1,39 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; + +import com.yanzhu.exam.exam.domain.ExamTaskManager; +import com.yanzhu.exam.exam.service.IExamTaskManagerService; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; +import com.yanzhu.exam.onlineexam.service.IExamTitleDataService; +import com.ruoyi.common.core.domain.AjaxResult; + +@RestController +@RequestMapping("/onlineexam/examtitle") +public class ExamTitleController { + + @Autowired + IExamTitleDataService examTitleDataService; + + @Autowired + IExamTaskManagerService examTaskManagerService; + + @GetMapping(value = "/selectCurrentExam") + public AjaxResult selectCurrentExam() + { + + LoginUser user=SecurityUtils.getLoginUser(); + List list= examTaskManagerService.selectCurrentExam(""+user.getUser().getUserId()); + //ExamTitleData examTitleData = examTitleDataService.selectCurrentExam(user.getUser().getUserCode()); + //return AjaxResult.success(examTitleData); + return AjaxResult.success(list); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamUserScoreController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamUserScoreController.java new file mode 100644 index 0000000..cfb0c25 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/controller/ExamUserScoreController.java @@ -0,0 +1,112 @@ +package com.yanzhu.exam.onlineexam.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; +import com.yanzhu.exam.onlineexam.service.IExamUserScoreService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试æˆç»©Controller + * + * @author qnsdt + * @date 2023-03-03 + */ +@RestController +@RequestMapping("/onlineexam/userscore") +public class ExamUserScoreController extends BaseController +{ + @Autowired + private IExamUserScoreService examUserScoreService; + + /** + * 查询考试æˆç»©åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:list')") + @GetMapping("/list") + public TableDataInfo list(ExamUserScore examUserScore) + { + startPage(); + List list = examUserScoreService.selectExamUserScoreList(examUserScore); + return getDataTable(list); + } + + /** + * 导出考试æˆç»©åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:export')") + @Log(title = "考试æˆç»©", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamUserScore examUserScore) + { + List list = examUserScoreService.selectExamUserScoreList(examUserScore); + ExcelUtil util = new ExcelUtil(ExamUserScore.class); + return util.exportExcel(list, "考试æˆç»©æ•°æ®"); + } + + /** + * 获å–考试æˆç»©è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:query')") + @GetMapping(value = "/{examCode}") + public AjaxResult getInfo(@PathVariable("examCode") String examCode) + { + return AjaxResult.success(examUserScoreService.selectExamUserScoreById(examCode)); + } + + /** + * 新增考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:add')") + @Log(title = "考试æˆç»©", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamUserScore examUserScore) + { + return toAjax(examUserScoreService.insertExamUserScore(examUserScore)); + } + + /** + * 维护考试æˆç»© + */ + @PostMapping("/into") + public AjaxResult into(@RequestBody ExamUserScore examUserScore) + { + return toAjax(examUserScoreService.intoExamUserScore(examUserScore)); + } + + /** + * 修改考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:edit')") + @Log(title = "考试æˆç»©", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamUserScore examUserScore) + { + return toAjax(examUserScoreService.updateExamUserScore(examUserScore)); + } + + /** + * 删除考试æˆç»© + */ + @PreAuthorize("@ss.hasPermi('onlineexam:userscore:remove')") + @Log(title = "考试æˆç»©", businessType = BusinessType.DELETE) + @DeleteMapping("/{examCodes}") + public AjaxResult remove(@PathVariable String[] examCodes) + { + return toAjax(examUserScoreService.deleteExamUserScoreByIds(examCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamFinishAnswer.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamFinishAnswer.java new file mode 100644 index 0000000..91eadc6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamFinishAnswer.java @@ -0,0 +1,119 @@ +package com.yanzhu.exam.onlineexam.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试æˆç»©å¯¹è±¡ exam_finish_answer + * + * @author qnsdt + * @date 2023-03-02 + */ +public class ExamFinishAnswer extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + private String examCode; + + /** 考试用户 */ + private String userCode; + + /** é¢˜ç›®ä»£ç  */ + private String questionsCode; + + /** 正确答案 */ + @Excel(name = "正确答案") + private String rightAnswer; + + /** 分数 */ + @Excel(name = "分数") + private Long examScore; + + /** 题目回答 */ + @Excel(name = "题目回答") + private String questionsAnswer; + + /** 题目得分 */ + @Excel(name = "题目得分") + private Long questionsScore; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setUserCode(String userCode) + { + this.userCode = userCode; + } + + public String getUserCode() + { + return userCode; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setRightAnswer(String rightAnswer) + { + this.rightAnswer = rightAnswer; + } + + public String getRightAnswer() + { + return rightAnswer; + } + public void setExamScore(Long examScore) + { + this.examScore = examScore; + } + + public Long getExamScore() + { + return examScore; + } + public void setQuestionsAnswer(String questionsAnswer) + { + this.questionsAnswer = questionsAnswer; + } + + public String getQuestionsAnswer() + { + return questionsAnswer; + } + public void setQuestionsScore(Long questionsScore) + { + this.questionsScore = questionsScore; + } + + public Long getQuestionsScore() + { + return questionsScore; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("userCode", getUserCode()) + .append("questionsCode", getQuestionsCode()) + .append("rightAnswer", getRightAnswer()) + .append("examScore", getExamScore()) + .append("questionsAnswer", getQuestionsAnswer()) + .append("questionsScore", getQuestionsScore()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamTaskAnswer.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamTaskAnswer.java new file mode 100644 index 0000000..b9743c6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamTaskAnswer.java @@ -0,0 +1,147 @@ +package com.yanzhu.exam.onlineexam.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试实时数æ®å¯¹è±¡ exam_task_answer + * + * @author qnsdt + * @date 2023-02-24 + */ +public class ExamTaskAnswer extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + @Excel(name = "考试代ç ") + private String examCode; + + /** 考试用户 */ + @Excel(name = "考试用户") + private String userCode; + + /** é¢˜ç›®ä»£ç  */ + @Excel(name = "题目代ç ") + private String questionsCode; + + + private String examTimes; + + public String getExamTimes() { + return examTimes; + } + + public void setExamTimes(String examTimes) { + this.examTimes = examTimes; + } + + /** é¢˜å· */ + @Excel(name = "题å·") + private Long questionsNumber; + + /** 试题类型 */ + @Excel(name = "试题类型") + private Long questionsType; + + /** 题目回答 */ + @Excel(name = "题目回答") + private String questionsAnswer; + + /** æ˜¯å¦æ ‡è®° */ + @Excel(name = "æ˜¯å¦æ ‡è®°") + private String isMark; + + /** 是å¦å½“å‰ */ + @Excel(name = "是å¦å½“å‰") + private String isCurrent; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setUserCode(String userCode) + { + this.userCode = userCode; + } + + public String getUserCode() + { + return userCode; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsNumber(Long questionsNumber) + { + this.questionsNumber = questionsNumber; + } + + public Long getQuestionsNumber() + { + return questionsNumber; + } + public void setQuestionsType(Long questionsType) + { + this.questionsType = questionsType; + } + + public Long getQuestionsType() + { + return questionsType; + } + public void setQuestionsAnswer(String questionsAnswer) + { + this.questionsAnswer = questionsAnswer; + } + + public String getQuestionsAnswer() + { + return questionsAnswer; + } + public void setIsMark(String isMark) + { + this.isMark = isMark; + } + + public String getIsMark() + { + return isMark; + } + public void setIsCurrent(String isCurrent) + { + this.isCurrent = isCurrent; + } + + public String getIsCurrent() + { + return isCurrent; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("userCode", getUserCode()) + .append("questionsCode", getQuestionsCode()) + .append("questionsNumber", getQuestionsNumber()) + .append("questionsType", getQuestionsType()) + .append("questionsAnswer", getQuestionsAnswer()) + .append("isMark", getIsMark()) + .append("isCurrent", getIsCurrent()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamUserScore.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamUserScore.java new file mode 100644 index 0000000..83e8724 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/ExamUserScore.java @@ -0,0 +1,166 @@ +package com.yanzhu.exam.onlineexam.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试æˆç»©å¯¹è±¡ exam_user_score + * + * @author qnsdt + * @date 2023-03-03 + */ +public class ExamUserScore extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è€ƒè¯•ä»£ç  */ + private String examCode; + + /** 考试人员 */ + private String userCode; + + /** 开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date startTime; + + /** ç»“æŸæ—¶é—´ */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "ç»“æŸæ—¶é—´", width = 30, dateFormat = "yyyy-MM-dd") + private Date endTime; + + /** 分数 */ + @Excel(name = "分数") + private Integer examScore; + + /** 题目分数 */ + @Excel(name = "题目分数") + private Integer questionsScore; + + /** 题目数 */ + @Excel(name = "题目数") + private Integer examNumber; + + /** 答题数 */ + @Excel(name = "答题数") + private Integer answeredNumber; + + /** 未答题数 */ + @Excel(name = "未答题数") + private Integer notAnswered; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Integer status; + + public void setExamCode(String examCode) + { + this.examCode = examCode; + } + + public String getExamCode() + { + return examCode; + } + public void setUserCode(String userCode) + { + this.userCode = userCode; + } + + public String getUserCode() + { + return userCode; + } + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStartTime() + { + return startTime; + } + public void setEndTime(Date endTime) + { + this.endTime = endTime; + } + + public Date getEndTime() + { + return endTime; + } + public void setExamScore(Integer examScore) + { + this.examScore = examScore; + } + + public Integer getExamScore() + { + return examScore; + } + public void setQuestionsScore(Integer questionsScore) + { + this.questionsScore = questionsScore; + } + + public Integer getQuestionsScore() + { + return questionsScore; + } + public void setExamNumber(Integer examNumber) + { + this.examNumber = examNumber; + } + + public Integer getExamNumber() + { + return examNumber; + } + public void setAnsweredNumber(Integer answeredNumber) + { + this.answeredNumber = answeredNumber; + } + + public Integer getAnsweredNumber() + { + return answeredNumber; + } + public void setNotAnswered(Integer notAnswered) + { + this.notAnswered = notAnswered; + } + + public Integer getNotAnswered() + { + return notAnswered; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("examCode", getExamCode()) + .append("userCode", getUserCode()) + .append("startTime", getStartTime()) + .append("endTime", getEndTime()) + .append("examScore", getExamScore()) + .append("questionsScore", getQuestionsScore()) + .append("examNumber", getExamNumber()) + .append("answeredNumber", getAnsweredNumber()) + .append("notAnswered", getNotAnswered()) + .append("status", getStatus()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsContentData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsContentData.java new file mode 100644 index 0000000..ea0cc3d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsContentData.java @@ -0,0 +1,17 @@ +package com.yanzhu.exam.onlineexam.domain.dto; + +import lombok.Data; + +@Data +public class ExamQuestionsContentData { + private String bankCode; + private String examCode; + private int questionsId; + private int questionsNumber; + private String questionsNumberText; + private String questionsCode; + private String questionsContent; + private int questionsType; + private int questionsScore; + private int rateNumber; +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsData.java new file mode 100644 index 0000000..b0f5710 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsData.java @@ -0,0 +1,24 @@ +package com.yanzhu.exam.onlineexam.domain.dto; + +import java.util.List; + +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; + +import lombok.Data; + +@Data +public class ExamQuestionsData { + + private ExamQuestionsContentData examQuestionsContentData; + private List examQuestionsOptionList; + + + public ExamQuestionsData(ExamQuestionsContentData examQuestionsContentData, + List examQuestionsOptionList) { + super(); + this.examQuestionsContentData = examQuestionsContentData; + this.examQuestionsOptionList = examQuestionsOptionList; + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsListData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsListData.java new file mode 100644 index 0000000..97be0f8 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamQuestionsListData.java @@ -0,0 +1,16 @@ +package com.yanzhu.exam.onlineexam.domain.dto; + +import lombok.Data; + +@Data +public class ExamQuestionsListData { + private String examCode; + private String userCode; + private String questionsCode; + private int questionsNumber; + private int questionsType; + private int questionsScore; + private String questionsAnswer; + private int isMark; + private int isCurrent; +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamTitleData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamTitleData.java new file mode 100644 index 0000000..22d36c5 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/domain/dto/ExamTitleData.java @@ -0,0 +1,74 @@ +package com.yanzhu.exam.onlineexam.domain.dto; + +import java.util.Date; + +import lombok.Data; + + +@Data +public class ExamTitleData { + /** 考试åºå· */ + private Long examId; + + /** è€ƒè¯•ä»£ç  */ + private String examCode; + + /** 考试åç§° */ + private String examName; + + private Integer examType; + private Integer examTimes; + /** 考试说明 */ + private String examDescribe; + + /** ç»„å·æ–¹å¼ */ + private String buildType; + + /** å¼ºåˆ¶æŠ½å· */ + private String forceDone; + + /** 考试题库 */ + private String examBank; + + /** 考试题库文字 */ + private String examBankText; + + + /** 图片链接 */ + private String pictureUrl; + + /** 开始时间 */ + private Date startTime; + + /** ç»“æŸæ—¶é—´ */ + private Date endTime; + + /** 当剿—¥æœŸ */ + private Date currentDate; + /** 考试时长 */ + private String examDuration; + + private int diffTime; + + /** 判断题数 */ + private int judgeNumber; + + /** å•选题数 */ + private int radioNumber; + + /** 多选题数 */ + private int choiceNumber; + + private int questionsScore; + /** çŠ¶æ€ */ + private Long status; + + /** 创建人 */ + private String createBy; + + /** 创建部门 */ + private int createDept; + + /** 创建时间 */ + private Date createTime; +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamFinishAnswerMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamFinishAnswerMapper.java new file mode 100644 index 0000000..4102317 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamFinishAnswerMapper.java @@ -0,0 +1,77 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamFinishAnswer; + +/** + * 考试æˆç»©MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-24 + */ +public interface ExamFinishAnswerMapper +{ + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + public ExamFinishAnswer selectExamFinishAnswerById(String examCode); + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examFinishAnswer 考试æˆç»© + * @return 考试æˆç»©é›†åˆ + */ + public List selectExamFinishAnswerList(ExamFinishAnswer examFinishAnswer); + + /** + * 新增考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int insertExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 考试结æŸå°†è€ƒè¯•æˆç»©æ‹·å…¥ + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int intoExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 修改考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int updateExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 删除考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamFinishAnswerById(String examCode); + + /** + * 删除个人考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int deleteExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamFinishAnswerByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsContentDataMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsContentDataMapper.java new file mode 100644 index 0000000..9dff300 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsContentDataMapper.java @@ -0,0 +1,10 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import java.util.List; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsContentData; + +public interface ExamQuestionsContentDataMapper { + public ExamQuestionsContentData selectExamQuestionsContent(ExamQuestionsContentData questionsContentData); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsListDataMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsListDataMapper.java new file mode 100644 index 0000000..d9ecde9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamQuestionsListDataMapper.java @@ -0,0 +1,9 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import java.util.List; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsListData; + +public interface ExamQuestionsListDataMapper { + public List selectQuestionsList(ExamQuestionsListData examQuestionsListData); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTaskAnswerMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTaskAnswerMapper.java new file mode 100644 index 0000000..7f66794 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTaskAnswerMapper.java @@ -0,0 +1,68 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamTaskAnswer; + +/** + * 考试实时数æ®MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-24 + */ +public interface ExamTaskAnswerMapper +{ + /** + * æŸ¥è¯¢è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return è€ƒè¯•å®žæ—¶æ•°æ® + */ + public ExamTaskAnswer selectExamTaskAnswerById(String examCode); + + /** + * 查询考试实时数æ®åˆ—表 + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 考试实时数æ®é›†åˆ + */ + public List selectExamTaskAnswerList(ExamTaskAnswer examTaskAnswer); + + /** + * æ–°å¢žè€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + public int insertExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + + /** + * ä¿®æ”¹è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + public int updateExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + + /** + * åˆ é™¤ä¸ªäººå•æ¡è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + /** + * åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswerById(String examCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswerByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTitleDataMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTitleDataMapper.java new file mode 100644 index 0000000..5ee4dd7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamTitleDataMapper.java @@ -0,0 +1,7 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; + +public interface ExamTitleDataMapper { + public ExamTitleData selectCurrentExam(String userCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamUserScoreMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamUserScoreMapper.java new file mode 100644 index 0000000..66dcd5c --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/mapper/ExamUserScoreMapper.java @@ -0,0 +1,78 @@ +package com.yanzhu.exam.onlineexam.mapper; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; + +/** + * 考试æˆç»©MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-03-03 + */ +public interface ExamUserScoreMapper +{ + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + public ExamUserScore selectExamUserScoreById(String examCode); + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examUserScore 考试æˆç»© + * @return 考试æˆç»©é›†åˆ + */ + public List selectExamUserScoreList(ExamUserScore examUserScore); + + /** + * 新增考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int insertExamUserScore(ExamUserScore examUserScore); + + /** + * 维护考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int intoExamUserScore(ExamUserScore examUserScore); + + /** + * 修改考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int updateExamUserScore(ExamUserScore examUserScore); + + /** + * 删除考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamUserScore(ExamUserScore examUserScore); + + + /** + * 删除考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamUserScoreById(String examCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamUserScoreByIds(String[] examCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamFinishAnswerService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamFinishAnswerService.java new file mode 100644 index 0000000..4138642 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamFinishAnswerService.java @@ -0,0 +1,77 @@ +package com.yanzhu.exam.onlineexam.service; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamFinishAnswer; + +/** + * 考试æˆç»©ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-24 + */ +public interface IExamFinishAnswerService +{ + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + public ExamFinishAnswer selectExamFinishAnswerById(String examCode); + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examFinishAnswer 考试æˆç»© + * @return 考试æˆç»©é›†åˆ + */ + public List selectExamFinishAnswerList(ExamFinishAnswer examFinishAnswer); + + /** + * 新增考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int insertExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 考试结æŸå°†è€ƒè¯•æˆç»©æ‹·å…¥ + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int intoExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 修改考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int updateExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„考试æˆç»©ID + * @return 结果 + */ + public int deleteExamFinishAnswerByIds(String[] examCodes); + + /** + * 删除个人考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + public int deleteExamFinishAnswer(ExamFinishAnswer examFinishAnswer); + + /** + * 删除考试æˆç»©ä¿¡æ¯ + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamFinishAnswerById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsContentDataService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsContentDataService.java new file mode 100644 index 0000000..1279e1a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsContentDataService.java @@ -0,0 +1,10 @@ +package com.yanzhu.exam.onlineexam.service; + +import java.util.List; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsContentData; + +public interface IExamQuestionsContentDataService { + public ExamQuestionsContentData selectExamQuestionsContent(ExamQuestionsContentData questionsContentData); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsListDataService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsListDataService.java new file mode 100644 index 0000000..8efc60d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamQuestionsListDataService.java @@ -0,0 +1,10 @@ +package com.yanzhu.exam.onlineexam.service; + +import java.util.List; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsListData; + +public interface IExamQuestionsListDataService { + public List selectQuestionsList(ExamQuestionsListData examQuestionsListData); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTaskAnswerService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTaskAnswerService.java new file mode 100644 index 0000000..069ecdc --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTaskAnswerService.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.onlineexam.service; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamTaskAnswer; + +/** + * 考试实时数æ®ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-24 + */ +public interface IExamTaskAnswerService +{ + /** + * æŸ¥è¯¢è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return è€ƒè¯•å®žæ—¶æ•°æ® + */ + public ExamTaskAnswer selectExamTaskAnswerById(String examCode); + + /** + * 查询考试实时数æ®åˆ—表 + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 考试实时数æ®é›†åˆ + */ + public List selectExamTaskAnswerList(ExamTaskAnswer examTaskAnswer); + + /** + * æ–°å¢žè€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + public int insertExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + + /** + * ä¿®æ”¹è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + public int updateExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + + /** + * åˆ é™¤ä¸ªäººå•æ¡è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswer(ExamTaskAnswer examTaskAnswer); + + /** + * 批é‡åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCodes 需è¦åˆ é™¤çš„考试实时数æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswerByIds(String[] examCodes); + + /** + * 删除考试实时数æ®ä¿¡æ¯ + * + * @param examCode 考试实时数æ®ID + * @return 结果 + */ + public int deleteExamTaskAnswerById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTitleDataService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTitleDataService.java new file mode 100644 index 0000000..8b09228 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamTitleDataService.java @@ -0,0 +1,7 @@ +package com.yanzhu.exam.onlineexam.service; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; + +public interface IExamTitleDataService { + public ExamTitleData selectCurrentExam(String userCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamUserScoreService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamUserScoreService.java new file mode 100644 index 0000000..bc0e971 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/IExamUserScoreService.java @@ -0,0 +1,78 @@ +package com.yanzhu.exam.onlineexam.service; + +import java.util.List; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; + +/** + * 考试æˆç»©ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-03-03 + */ +public interface IExamUserScoreService +{ + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + public ExamUserScore selectExamUserScoreById(String examCode); + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examUserScore 考试æˆç»© + * @return 考试æˆç»©é›†åˆ + */ + public List selectExamUserScoreList(ExamUserScore examUserScore); + + /** + * 新增考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int insertExamUserScore(ExamUserScore examUserScore); + + /** + * 维护考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int intoExamUserScore(ExamUserScore examUserScore); + + /** + * 修改考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + public int updateExamUserScore(ExamUserScore examUserScore); + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„考试æˆç»©ID + * @return 结果 + */ + + /** + * 删除考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamUserScore(ExamUserScore examUserScore); + + public int deleteExamUserScoreByIds(String[] examCodes); + + /** + * 删除考试æˆç»©ä¿¡æ¯ + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + public int deleteExamUserScoreById(String examCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamFinishAnswerServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamFinishAnswerServiceImpl.java new file mode 100644 index 0000000..87b559e --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamFinishAnswerServiceImpl.java @@ -0,0 +1,132 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.onlineexam.mapper.ExamFinishAnswerMapper; +import com.yanzhu.exam.exam.domain.ExamTaskPerson; +import com.yanzhu.exam.exam.service.IExamTaskPersonService; +import com.yanzhu.exam.onlineexam.domain.ExamFinishAnswer; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; +import com.yanzhu.exam.onlineexam.service.IExamFinishAnswerService; +import com.yanzhu.exam.onlineexam.service.IExamUserScoreService; + +/** + * 考试æˆç»©Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-24 + */ +@Service +public class ExamFinishAnswerServiceImpl implements IExamFinishAnswerService +{ + @Autowired + private ExamFinishAnswerMapper examFinishAnswerMapper; + + @Autowired + private IExamUserScoreService examUserScoreService; + + @Autowired + private IExamTaskPersonService examTaskPersonService; + + + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + @Override + public ExamFinishAnswer selectExamFinishAnswerById(String examCode) + { + return examFinishAnswerMapper.selectExamFinishAnswerById(examCode); + } + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examFinishAnswer 考试æˆç»© + * @return 考试æˆç»© + */ + @Override + public List selectExamFinishAnswerList(ExamFinishAnswer examFinishAnswer) + { + return examFinishAnswerMapper.selectExamFinishAnswerList(examFinishAnswer); + } + + /** + * 新增考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + @Override + public int insertExamFinishAnswer(ExamFinishAnswer examFinishAnswer) + { + return examFinishAnswerMapper.insertExamFinishAnswer(examFinishAnswer); + } + + /** + * 修改考试æˆç»© + * + * @param examFinishAnswer 考试æˆç»© + * @return 结果 + */ + @Override + public int updateExamFinishAnswer(ExamFinishAnswer examFinishAnswer) + { + return examFinishAnswerMapper.updateExamFinishAnswer(examFinishAnswer); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„考试æˆç»©ID + * @return 结果 + */ + @Override + public int deleteExamFinishAnswerByIds(String[] examCodes) + { + return examFinishAnswerMapper.deleteExamFinishAnswerByIds(examCodes); + } + + /** + * 删除考试æˆç»©ä¿¡æ¯ + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + @Override + public int deleteExamFinishAnswerById(String examCode) + { + return examFinishAnswerMapper.deleteExamFinishAnswerById(examCode); + } + + @Override + public int intoExamFinishAnswer(ExamFinishAnswer examFinishAnswer) { + // TODO Auto-generated method stub + examFinishAnswerMapper.deleteExamFinishAnswer(examFinishAnswer); + + int result = examFinishAnswerMapper.intoExamFinishAnswer(examFinishAnswer); + + // 维护æˆç»©æ•°æ® + ExamUserScore examUserScore = new ExamUserScore(); + examUserScore.setExamCode(examFinishAnswer.getExamCode()); + examUserScore.setUserCode(examFinishAnswer.getUserCode()); + + result = examUserScoreService.intoExamUserScore(examUserScore); + + // æ›´æ–°çŠ¶æ€ + ExamTaskPerson examTaskPerson = new ExamTaskPerson(); + examTaskPerson.setExamCode(examFinishAnswer.getExamCode()); + examTaskPerson.setuserCode(examFinishAnswer.getUserCode()); + examTaskPersonService.updateDoneStatus(examTaskPerson); + return result; + } + + @Override + public int deleteExamFinishAnswer(ExamFinishAnswer examFinishAnswer) { + // TODO Auto-generated method stub + return examFinishAnswerMapper.deleteExamFinishAnswer(examFinishAnswer); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsContentDataServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsContentDataServiceImpl.java new file mode 100644 index 0000000..ed0728c --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsContentDataServiceImpl.java @@ -0,0 +1,24 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsContentData; +import com.yanzhu.exam.onlineexam.mapper.ExamQuestionsContentDataMapper; +import com.yanzhu.exam.onlineexam.service.IExamQuestionsContentDataService; + +@Service +public class ExamQuestionsContentDataServiceImpl implements IExamQuestionsContentDataService { + @Autowired + ExamQuestionsContentDataMapper examQuestionsContentDataMapper; + + + @Override + public ExamQuestionsContentData selectExamQuestionsContent(ExamQuestionsContentData questionsContentData) { + // TODO Auto-generated method stub + return examQuestionsContentDataMapper.selectExamQuestionsContent(questionsContentData); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsListDataServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsListDataServiceImpl.java new file mode 100644 index 0000000..cf69292 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamQuestionsListDataServiceImpl.java @@ -0,0 +1,23 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamQuestionsListData; +import com.yanzhu.exam.onlineexam.mapper.ExamQuestionsListDataMapper; +import com.yanzhu.exam.onlineexam.service.IExamQuestionsListDataService; + +@Service +public class ExamQuestionsListDataServiceImpl implements IExamQuestionsListDataService { + @Autowired + ExamQuestionsListDataMapper examQuestionsListDataMapper; + + @Override + public List selectQuestionsList(ExamQuestionsListData examQuestionsListData) { + // TODO Auto-generated method stub + return examQuestionsListDataMapper.selectQuestionsList(examQuestionsListData); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTaskAnswerServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTaskAnswerServiceImpl.java new file mode 100644 index 0000000..fa55d32 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTaskAnswerServiceImpl.java @@ -0,0 +1,105 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.onlineexam.mapper.ExamTaskAnswerMapper; +import com.yanzhu.exam.onlineexam.domain.ExamTaskAnswer; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; +import com.yanzhu.exam.onlineexam.service.IExamTaskAnswerService; +import com.yanzhu.exam.onlineexam.service.IExamUserScoreService; + +/** + * 考试实时数æ®Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-24 + */ +@Service +public class ExamTaskAnswerServiceImpl implements IExamTaskAnswerService +{ + @Autowired + private ExamTaskAnswerMapper examTaskAnswerMapper; + + + /** + * æŸ¥è¯¢è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCode 考试实时数æ®ID + * @return è€ƒè¯•å®žæ—¶æ•°æ® + */ + @Override + public ExamTaskAnswer selectExamTaskAnswerById(String examCode) + { + return examTaskAnswerMapper.selectExamTaskAnswerById(examCode); + } + + /** + * 查询考试实时数æ®åˆ—表 + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return è€ƒè¯•å®žæ—¶æ•°æ® + */ + @Override + public List selectExamTaskAnswerList(ExamTaskAnswer examTaskAnswer) + { + return examTaskAnswerMapper.selectExamTaskAnswerList(examTaskAnswer); + } + + /** + * æ–°å¢žè€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + @Override + public int insertExamTaskAnswer(ExamTaskAnswer examTaskAnswer) + { + // 安全删除 + examTaskAnswerMapper.deleteExamTaskAnswer(examTaskAnswer); + + return examTaskAnswerMapper.insertExamTaskAnswer(examTaskAnswer); + } + + /** + * ä¿®æ”¹è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examTaskAnswer è€ƒè¯•å®žæ—¶æ•°æ® + * @return 结果 + */ + @Override + public int updateExamTaskAnswer(ExamTaskAnswer examTaskAnswer) + { + return examTaskAnswerMapper.updateExamTaskAnswer(examTaskAnswer); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•å®žæ—¶æ•°æ® + * + * @param examCodes 需è¦åˆ é™¤çš„考试实时数æ®ID + * @return 结果 + */ + @Override + public int deleteExamTaskAnswerByIds(String[] examCodes) + { + return examTaskAnswerMapper.deleteExamTaskAnswerByIds(examCodes); + } + + /** + * 删除考试实时数æ®ä¿¡æ¯ + * + * @param examCode 考试实时数æ®ID + * @return 结果 + */ + @Override + public int deleteExamTaskAnswerById(String examCode) + { + return examTaskAnswerMapper.deleteExamTaskAnswerById(examCode); + } + + @Override + public int deleteExamTaskAnswer(ExamTaskAnswer examTaskAnswer) { + // TODO Auto-generated method stub + return examTaskAnswerMapper.deleteExamTaskAnswer(examTaskAnswer); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTitleDataServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTitleDataServiceImpl.java new file mode 100644 index 0000000..193a5a0 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamTitleDataServiceImpl.java @@ -0,0 +1,21 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.onlineexam.domain.dto.ExamTitleData; +import com.yanzhu.exam.onlineexam.mapper.ExamTitleDataMapper; +import com.yanzhu.exam.onlineexam.service.IExamTitleDataService; + +@Service +public class ExamTitleDataServiceImpl implements IExamTitleDataService { + @Autowired + ExamTitleDataMapper examTitleDataMapper; + + @Override + public ExamTitleData selectCurrentExam(String userCode) { + // TODO Auto-generated method stub + return examTitleDataMapper.selectCurrentExam(userCode); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamUserScoreServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamUserScoreServiceImpl.java new file mode 100644 index 0000000..dcb3851 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/onlineexam/service/impl/ExamUserScoreServiceImpl.java @@ -0,0 +1,107 @@ +package com.yanzhu.exam.onlineexam.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.onlineexam.mapper.ExamUserScoreMapper; +import com.yanzhu.exam.onlineexam.domain.ExamUserScore; +import com.yanzhu.exam.onlineexam.service.IExamUserScoreService; + +/** + * 考试æˆç»©Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-03-03 + */ +@Service +public class ExamUserScoreServiceImpl implements IExamUserScoreService +{ + @Autowired + private ExamUserScoreMapper examUserScoreMapper; + + /** + * 查询考试æˆç»© + * + * @param examCode 考试æˆç»©ID + * @return 考试æˆç»© + */ + @Override + public ExamUserScore selectExamUserScoreById(String examCode) + { + return examUserScoreMapper.selectExamUserScoreById(examCode); + } + + /** + * 查询考试æˆç»©åˆ—表 + * + * @param examUserScore 考试æˆç»© + * @return 考试æˆç»© + */ + @Override + public List selectExamUserScoreList(ExamUserScore examUserScore) + { + return examUserScoreMapper.selectExamUserScoreList(examUserScore); + } + + /** + * 新增考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + @Override + public int insertExamUserScore(ExamUserScore examUserScore) + { + return examUserScoreMapper.insertExamUserScore(examUserScore); + } + + /** + * 修改考试æˆç»© + * + * @param examUserScore 考试æˆç»© + * @return 结果 + */ + @Override + public int updateExamUserScore(ExamUserScore examUserScore) + { + return examUserScoreMapper.updateExamUserScore(examUserScore); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•æˆç»© + * + * @param examCodes 需è¦åˆ é™¤çš„考试æˆç»©ID + * @return 结果 + */ + @Override + public int deleteExamUserScoreByIds(String[] examCodes) + { + return examUserScoreMapper.deleteExamUserScoreByIds(examCodes); + } + + /** + * 删除考试æˆç»©ä¿¡æ¯ + * + * @param examCode 考试æˆç»©ID + * @return 结果 + */ + @Override + public int deleteExamUserScoreById(String examCode) + { + return examUserScoreMapper.deleteExamUserScoreById(examCode); + } + + @Override + public int intoExamUserScore(ExamUserScore examUserScore) { + // TODO Auto-generated method stub + // 安全删除 + examUserScoreMapper.deleteExamUserScore(examUserScore); + return examUserScoreMapper.intoExamUserScore(examUserScore); + } + + @Override + public int deleteExamUserScore(ExamUserScore examUserScore) { + // TODO Auto-generated method stub + return examUserScoreMapper.deleteExamUserScore(examUserScore); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamBankPictureController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamBankPictureController.java new file mode 100644 index 0000000..f0caf81 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamBankPictureController.java @@ -0,0 +1,103 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamBankPicture; +import com.yanzhu.exam.questions.service.IExamBankPictureService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 题库图片Controller + * + * @author qnsdt + * @date 2022-12-22 + */ +@RestController +@RequestMapping("/questions/bankpicture") +public class ExamBankPictureController extends BaseController +{ + @Autowired + private IExamBankPictureService examBankPictureService; + + /** + * 查询题库图片列表 + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:list')") + @GetMapping("/list") + public TableDataInfo list(ExamBankPicture examBankPicture) + { + startPage(); + List list = examBankPictureService.selectExamBankPictureList(examBankPicture); + return getDataTable(list); + } + + /** + * 导出题库图片列表 + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:export')") + @Log(title = "题库图片", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamBankPicture examBankPicture) + { + List list = examBankPictureService.selectExamBankPictureList(examBankPicture); + ExcelUtil util = new ExcelUtil(ExamBankPicture.class); + return util.exportExcel(list, "题库图片数æ®"); + } + + /** + * 获å–é¢˜åº“å›¾ç‰‡è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:query')") + @GetMapping(value = "/{photoCode}") + public AjaxResult getInfo(@PathVariable("photoCode") String photoCode) + { + return AjaxResult.success(examBankPictureService.selectExamBankPictureById(photoCode)); + } + + /** + * 新增题库图片 + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:add')") + @Log(title = "题库图片", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamBankPicture examBankPicture) + { + return toAjax(examBankPictureService.insertExamBankPicture(examBankPicture)); + } + + /** + * 修改题库图片 + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:edit')") + @Log(title = "题库图片", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamBankPicture examBankPicture) + { + return toAjax(examBankPictureService.updateExamBankPicture(examBankPicture)); + } + + /** + * 删除题库图片 + */ + @PreAuthorize("@ss.hasPermi('questions:bankpicture:remove')") + @Log(title = "题库图片", businessType = BusinessType.DELETE) + @DeleteMapping("/{photoCodes}") + public AjaxResult remove(@PathVariable String[] photoCodes) + { + return toAjax(examBankPictureService.deleteExamBankPictureByIds(photoCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsAnswerController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsAnswerController.java new file mode 100644 index 0000000..b1caf53 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsAnswerController.java @@ -0,0 +1,109 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; +import com.yanzhu.exam.questions.service.IExamQuestionsAnswerService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试题目答案Controller + * + * @author qnsdt + * @date 2022-12-29 + */ +@RestController +@RequestMapping("/questions/answer") +public class ExamQuestionsAnswerController extends BaseController +{ + @Autowired + private IExamQuestionsAnswerService examQuestionsAnswerService; + + /** + * 查询考试题目答案列表 + */ + @GetMapping("/list") + public TableDataInfo list(ExamQuestionsAnswer examQuestionsAnswer) + { + startPage(); + List list = examQuestionsAnswerService.selectExamQuestionsAnswerList(examQuestionsAnswer); + return getDataTable(list); + } + + @GetMapping("/optionlist/{questionsCode}") + public AjaxResult optionList(@PathVariable("questionsCode") String questionsCode) + { + List list = examQuestionsAnswerService.selectExamQuestionsOptionList(questionsCode); + return AjaxResult.success(list); + } + + /** + * 导出考试题目答案列表 + */ + @PreAuthorize("@ss.hasPermi('questions:answer:export')") + @Log(title = "考试题目答案", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamQuestionsAnswer examQuestionsAnswer) + { + List list = examQuestionsAnswerService.selectExamQuestionsAnswerList(examQuestionsAnswer); + ExcelUtil util = new ExcelUtil(ExamQuestionsAnswer.class); + return util.exportExcel(list, "考试题目答案数æ®"); + } + + /** + * 获å–è€ƒè¯•é¢˜ç›®ç­”æ¡ˆè¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:answer:query')") + @GetMapping(value = "/{questionsCode}") + public AjaxResult getInfo(@PathVariable("questionsCode") String questionsCode) + { + return AjaxResult.success(examQuestionsAnswerService.selectExamQuestionsAnswerById(questionsCode)); + } + + /** + * 新增考试题目答案 + */ + @PreAuthorize("@ss.hasPermi('questions:answer:add')") + @Log(title = "考试题目答案", businessType = BusinessType.INSERT) + @PostMapping("/add") + public AjaxResult add(@RequestBody ExamQuestionsAnswer examQuestionsAnswer) + { + return toAjax(examQuestionsAnswerService.insertExamQuestionsAnswer(examQuestionsAnswer)); + } + + /** + * 修改考试题目答案 + */ + @PreAuthorize("@ss.hasPermi('questions:answer:edit')") + @Log(title = "考试题目答案", businessType = BusinessType.UPDATE) + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamQuestionsAnswer examQuestionsAnswer) + { + return toAjax(examQuestionsAnswerService.updateExamQuestionsAnswer(examQuestionsAnswer)); + } + + /** + * 删除考试题目答案 + */ + @PreAuthorize("@ss.hasPermi('questions:answer:remove')") + @Log(title = "考试题目答案", businessType = BusinessType.DELETE) + @GetMapping("/delete/{questionsCodes}") + public AjaxResult remove(@PathVariable String[] questionsCodes) + { + return toAjax(examQuestionsAnswerService.deleteExamQuestionsAnswerByIds(questionsCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsBankController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsBankController.java new file mode 100644 index 0000000..4d37469 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsBankController.java @@ -0,0 +1,212 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.cms.utils.FileUpload; +import com.yanzhu.exam.questions.domain.ExamBankPicture; +import com.yanzhu.exam.questions.domain.ExamQuestionsBank; +import com.yanzhu.exam.questions.service.IExamBankPictureService; +import com.yanzhu.exam.questions.service.IExamQuestionsBankService; + +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 题库管ç†Controller + * + * @author qnsdt + * @date 2022-12-19 + */ +@RestController +@RequestMapping("/questions/questionsbank") +public class ExamQuestionsBankController extends BaseController +{ + private static final Logger log = LoggerFactory.getLogger(ExamQuestionsBankController.class); + + @Value("${cms.exam.photo-path:/photo/exam}") + private String photopath; + + @Autowired + private IExamQuestionsBankService examQuestionsBankService; + + @Autowired + private TokenService tokenService; + + @Autowired + private IExamBankPictureService examBankPictureService; + + /** + * 查询题库管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:list')") + @GetMapping("/list") + public TableDataInfo list(ExamQuestionsBank examQuestionsBank) + { + startPage(); + List list = examQuestionsBankService.selectExamQuestionsBankList(examQuestionsBank); + return getDataTable(list); + } + + @GetMapping("/arraylist/{bankCodes}") + public AjaxResult arrayList(@PathVariable("bankCodes") String bankCodes) + { + // startPage(); + // log.debug("bankCodes: {}", bankCodes); + List list = examQuestionsBankService.selectExamQuestionsBankListByCode(bankCodes.split(",")); + return AjaxResult.success(list); + } + + /** + * 导出题库管ç†åˆ—表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:export')") + @Log(title = "题库管ç†", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamQuestionsBank examQuestionsBank) + { + List list = examQuestionsBankService.selectExamQuestionsBankList(examQuestionsBank); + ExcelUtil util = new ExcelUtil(ExamQuestionsBank.class); + return util.exportExcel(list, "é¢˜åº“ç®¡ç†æ•°æ®"); + } + + /** + * å¯¼å…¥é¢˜åº“ç®¡ç†æ•°æ® + */ + @Log(title = "题库管ç†", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('questions:questionsbank:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception + { + ExcelUtil util = new ExcelUtil(ExamQuestionsBank.class); + List examQuestionsBankList = util.importExcel(file.getInputStream()); + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + String operName = loginUser.getUsername(); + String message = examQuestionsBankService.importExamQuestionsBank(examQuestionsBankList, updateSupport, operName); + return AjaxResult.success(message); + } + + /** + * 下载题库管ç†å¯¼å…¥æ¨¡æ¿ + */ + @GetMapping("/importTemplate") + public AjaxResult importTemplate() + { + ExcelUtil util = new ExcelUtil(ExamQuestionsBank.class); + return util.importTemplateExcel("é¢˜åº“ç®¡ç†æ•°æ®"); + } + + /** + * 获å–题库管ç†è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:query')") + @GetMapping(value = "/{bankCode}") + public AjaxResult getInfo(@PathVariable("bankCode") String bankCode) + { + return AjaxResult.success(examQuestionsBankService.selectExamQuestionsBankById(bankCode)); + } + + /** + * æ–°å¢žé¢˜åº“ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:add')") + @Log(title = "题库管ç†", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamQuestionsBank examQuestionsBank) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + log.debug("用户å: {}", loginUser.getUser().getUserName()); + log.debug("部门ID: {}", loginUser.getUser().getDept().getDeptId()); + examQuestionsBank.setCreateBy(loginUser.getUser().getUserName()); + examQuestionsBank.setCreateDept(loginUser.getUser().getDept().getDeptId()); + examQuestionsBank.setBankCode(UUID.randomUUID().toString()); + + log.debug("examQuestionsBank: {}", examQuestionsBank.toString()); + return toAjax(examQuestionsBankService.insertExamQuestionsBank(examQuestionsBank)); + } + + /** + * ä¿®æ”¹é¢˜åº“ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:edit')") + @Log(title = "题库管ç†", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamQuestionsBank examQuestionsBank) + { + log.debug("examQuestionsBank: {}", examQuestionsBank.toString()); + return toAjax(examQuestionsBankService.updateExamQuestionsBank(examQuestionsBank)); + } + + /** + * åˆ é™¤é¢˜åº“ç®¡ç† + */ + @PreAuthorize("@ss.hasPermi('questions:questionsbank:remove')") + @Log(title = "题库管ç†", businessType = BusinessType.DELETE) + @DeleteMapping("/{bankCodes}") + public AjaxResult remove(@PathVariable String[] bankCodes) + { + return toAjax(examQuestionsBankService.deleteExamQuestionsBankByIds(bankCodes)); + } + + /** + * æ–°å¢žå‚æ•°é…ç½® + */ + @PostMapping("/uploadphoto/{bankcode}") + public AjaxResult uploadPhoto(@PathVariable String bankcode, + @RequestParam("file") MultipartFile file) + { + // å–得原始文件å + String originalfile = file.getOriginalFilename(); + + // 拼接路径 + String path = RuoYiConfig.getProfile() + photopath; + log.debug("拼接路径为: {}", path); + String filename = FileUpload.writeUploadFile(file,path); + String fileurl = photopath + "/" + filename; + log.debug("fileurl: {}", fileurl); + + + int count = 0; + + // 相应赋值 + ExamBankPicture examBankPicture = new ExamBankPicture(bankcode, path, fileurl, filename, originalfile); + + log.debug("examBankPicture: {}", examBankPicture.toString()); + + try + { + examBankPictureService.deleteExamBankPictureById(bankcode); + count = examBankPictureService.insertExamBankPicture(examBankPicture); + } + catch(Exception e) + { + return AjaxResult.error(e.getMessage()); + } + + return AjaxResult.success(examBankPicture); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsContentController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsContentController.java new file mode 100644 index 0000000..4a06373 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsContentController.java @@ -0,0 +1,102 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; +import com.yanzhu.exam.questions.service.IExamQuestionsContentService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 题目内容表Controller + * + * @author qnsdt + * @date 2022-12-28 + */ +@RestController +@RequestMapping("/questions/questionscontent") +public class ExamQuestionsContentController extends BaseController +{ + @Autowired + private IExamQuestionsContentService examQuestionsContentService; + + /** + * 查询题目内容表列表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionscontent:list')") + @GetMapping("/list") + public TableDataInfo list(ExamQuestionsContent examQuestionsContent) + { + startPage(); + List list = examQuestionsContentService.selectExamQuestionsContentList(examQuestionsContent); + return getDataTable(list); + } + + /** + * 导出题目内容表列表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionscontent:export')") + @Log(title = "题目内容表", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamQuestionsContent examQuestionsContent) + { + List list = examQuestionsContentService.selectExamQuestionsContentList(examQuestionsContent); + ExcelUtil util = new ExcelUtil(ExamQuestionsContent.class); + return util.exportExcel(list, "题目内容表数æ®"); + } + + /** + * 获å–é¢˜ç›®å†…å®¹è¡¨è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{questionsCode}") + public AjaxResult getInfo(@PathVariable("questionsCode") String questionsCode) + { + return AjaxResult.success(examQuestionsContentService.selectExamQuestionsContentById(questionsCode)); + } + + /** + * 新增题目内容表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionscontent:add')") + @Log(title = "题目内容表", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamQuestionsContent examQuestionsContent) + { + return toAjax(examQuestionsContentService.insertExamQuestionsContent(examQuestionsContent)); + } + + /** + * 修改题目内容表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionscontent:edit')") + @Log(title = "题目内容表", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamQuestionsContent examQuestionsContent) + { + return toAjax(examQuestionsContentService.updateExamQuestionsContent(examQuestionsContent)); + } + + /** + * 删除题目内容表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionscontent:remove')") + @Log(title = "题目内容表", businessType = BusinessType.DELETE) + @DeleteMapping("/{questionsCodes}") + public AjaxResult remove(@PathVariable String[] questionsCodes) + { + return toAjax(examQuestionsContentService.deleteExamQuestionsContentByIds(questionsCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsController.java new file mode 100644 index 0000000..a737456 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsController.java @@ -0,0 +1,267 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.*; + +import com.ruoyi.common.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamQuestions; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.service.IExamQuestionsAnswerService; +import com.yanzhu.exam.questions.service.IExamQuestionsContentService; +import com.yanzhu.exam.questions.service.IExamQuestionsPropertyService; +import com.yanzhu.exam.questions.service.IExamQuestionsService; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 考试题目Controller + * + * @author qnsdt + * @date 2022-12-28 + */ +@RestController +@RequestMapping("/questions/examquestions") +public class ExamQuestionsController extends BaseController +{ + private static final Logger log = LoggerFactory.getLogger(ExamQuestionsController.class); + + @Autowired + private IExamQuestionsService examQuestionsService; + + @Autowired + private TokenService tokenService; + + @Autowired + private IExamQuestionsAnswerService examQuestionsAnswerService; + + @Autowired + private IExamQuestionsContentService examQuestionsContentService; + + @Autowired + private IExamQuestionsPropertyService examQuestionsPropertyService; + + /** + * 查询考试题目列表 + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:list')") + @GetMapping("/list") + public TableDataInfo list(ExamQuestions examQuestions) + { + startPage(); + List list = examQuestionsService.selectExamQuestionsList(examQuestions); + return getDataTable(list); + } + + /** + * 导出考试题目列表 + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:export')") + @Log(title = "考试题目", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamQuestions examQuestions) + { + List list = examQuestionsService.selectExamQuestionsList(examQuestions); + ExcelUtil util = new ExcelUtil(ExamQuestions.class); + return util.exportExcel(list, "考试题目数æ®"); + } + + /** + * å¯¼å…¥è€ƒè¯•é¢˜ç›®æ•°æ® + */ + @Log(title = "考试题目", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('questions:examquestions:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport,String bankCode) throws Exception + { + ExcelUtil util = new ExcelUtil(ExamQuestions.class); + List examQuestionsList = util.importExcel(file.getInputStream()); + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + String operName = loginUser.getUsername(); + List examQuestions=new ArrayList<>(); + examQuestionsList.forEach(x->{ + x.setBankCode(bankCode); + String tmp= x.getQuestionsTypeStr(); + boolean flag=false; + if("判断题".equals(tmp)){ + x.setQuestionsType(1); + flag=true; + } + if("å•选题".equals(tmp)){ + x.setQuestionsType(2); + flag=true; + } + if("多选题".equals(tmp)){ + x.setQuestionsType(3); + flag=true; + } + if(flag){ + examQuestions.add(x); + } + if(StringUtils.isEmpty(x.getRateNumberStr())){ + x.setRateNumber(0); + }else{ + x.setRateNumber(x.getRateNumberStr().length()/2); + } + x.setCreateBy(operName); + x.setCreateTime(new Date()); + x.setQuestionsCode(UUID.randomUUID().toString()); + }); + if(CollectionUtils.isEmpty(examQuestions)){ + return AjaxResult.error("导入数æ®ä¸ºç©ºï¼"); + } + + String message = examQuestionsService.importExamQuestions(examQuestions, updateSupport, operName); + return AjaxResult.success(message); + } + + /** + * ä¸‹è½½è€ƒè¯•é¢˜ç›®å¯¼å…¥æ¨¡æ¿ + */ + @GetMapping("/importTemplate") + public AjaxResult importTemplate() + { + ExcelUtil util = new ExcelUtil(ExamQuestions.class); + return util.importTemplateExcel("考试题目数æ®"); + } + + /** + * 获å–è€ƒè¯•é¢˜ç›®è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:query')") + @GetMapping(value = "/{questionsCode}") + public AjaxResult getInfo(@PathVariable("questionsCode") String questionsCode) + { + return AjaxResult.success(examQuestionsService.selectExamQuestionsById(questionsCode)); + } + + /** + * 新增考试题目 + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:add')") + @Log(title = "考试题目", businessType = BusinessType.INSERT) + @PostMapping("/add") + public AjaxResult add(@RequestBody ExamQuestions examQuestions) + { + // å–得用户å•ä½ + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + examQuestions.setCreateBy(loginUser.getUser().getUserName()); + examQuestions.setCreateDept(loginUser.getUser().getDept().getDeptId()); + List answerList = examQuestions.getAnswerList(); + + ExamQuestionsProperty examQuestionsProperty = new ExamQuestionsProperty(examQuestions.getBankCode(),null,examQuestions.getQuestionsCode(),examQuestions.getQuestionsTitle(), + examQuestions.getQuestionsType(),examQuestions.getQuestionsScore(),examQuestions.getRateNumber(),examQuestions.getRightAnswer(),examQuestions.getAnswerAnalyse(), + 0,examQuestions.getCreateBy(), examQuestions.getCreateDept()); + + ExamQuestionsContent examQuestionsContent = new ExamQuestionsContent(examQuestions.getQuestionsCode(), examQuestions.getQuestionsContent()); + + log.debug("examQuestionsContent: {}", examQuestionsContent.toString()); + + // 开始ä¿å­˜æ•°æ® + + // ä¿å­˜é¢˜ç›®é€‰é¡¹ + // 安全删除 + examQuestionsAnswerService.deleteExamQuestionsAnswerById(examQuestions.getQuestionsCode()); + for (ExamQuestionsAnswer questionsAnswer: answerList) { + questionsAnswer.setOrderId(null); + examQuestionsAnswerService.insertExamQuestionsAnswer(questionsAnswer); + } + + // ä¿å­˜é¢˜ç›®æ•°æ® + int count = 0; + examQuestionsContentService.deleteExamQuestionsContentById(examQuestions.getQuestionsCode()); + + count = examQuestionsContentService.insertExamQuestionsContent(examQuestionsContent); + + if (count == 0) { + return new AjaxResult(0,"更新题目信æ¯å‡ºé”™!"); + } + + + // 安全删除 + examQuestionsPropertyService.deleteExamQuestionsPropertyById(examQuestions.getQuestionsCode()); + + return toAjax(examQuestionsPropertyService.insertExamQuestionsProperty(examQuestionsProperty)); + } + + /** + * 修改考试题目 + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:edit')") + @Log(title = "考试题目", businessType = BusinessType.UPDATE) + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamQuestions examQuestions) + { + List answerList = examQuestions.getAnswerList(); + + ExamQuestionsProperty examQuestionsProperty = new ExamQuestionsProperty(examQuestions.getBankCode(),null,examQuestions.getQuestionsCode(),examQuestions.getQuestionsTitle(), + examQuestions.getQuestionsType(),examQuestions.getQuestionsScore(),examQuestions.getRateNumber(),examQuestions.getRightAnswer(),examQuestions.getAnswerAnalyse(), + 0,examQuestions.getCreateBy(), examQuestions.getCreateDept()); + + ExamQuestionsContent examQuestionsContent = new ExamQuestionsContent(examQuestions.getQuestionsCode(), examQuestions.getQuestionsContent()); + + + // 开始ä¿å­˜æ•°æ® + + // ä¿å­˜é¢˜ç›®é€‰é¡¹ + // 安全删除 + examQuestionsAnswerService.deleteExamQuestionsAnswerById(examQuestions.getQuestionsCode()); + for (ExamQuestionsAnswer questionsAnswer: answerList) { + examQuestionsAnswerService.insertExamQuestionsAnswer(questionsAnswer); + } + + // ä¿å­˜é¢˜ç›®æ•°æ® + int count = 0; + examQuestionsContentService.deleteExamQuestionsContentById(examQuestions.getQuestionsCode()); + + count = examQuestionsContentService.insertExamQuestionsContent(examQuestionsContent); + + if (count == 0) { + return new AjaxResult(0,"更新题目信æ¯å‡ºé”™!"); + } + + + return toAjax(examQuestionsPropertyService.updateExamQuestionsProperty(examQuestionsProperty)); + + } + + /** + * 删除考试题目 + */ + @PreAuthorize("@ss.hasPermi('questions:examquestions:remove')") + @Log(title = "考试题目", businessType = BusinessType.DELETE) + @GetMapping("/delete/{questionsCodes}") + public AjaxResult remove(@PathVariable String[] questionsCodes) + { + int count = questionsCodes.length; + for (String questionsCode: questionsCodes) { + examQuestionsAnswerService.deleteExamQuestionsAnswerById(questionsCode); + examQuestionsContentService.deleteExamQuestionsContentById(questionsCode); + examQuestionsPropertyService.deleteExamQuestionsPropertyById(questionsCode); + } + + + return toAjax(count); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsListController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsListController.java new file mode 100644 index 0000000..70696b0 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsListController.java @@ -0,0 +1,63 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamQuestionsList; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.service.IExamQuestionsListService; +import com.yanzhu.exam.questions.service.IExamQuestionsPropertyService; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 题目属性Controller + * + * @author qnsdt + * @date 2022-12-28 + */ +@RestController +@RequestMapping("/questions/questionslist") +public class ExamQuestionsListController extends BaseController +{ + @Autowired + private IExamQuestionsListService examQuestionsListService; + + @Autowired + private TokenService tokenService; + + /** + * 查询题目属性列表 + */ + @GetMapping("/list") + public TableDataInfo list(ExamQuestionsList examQuestionsList) + { + startPage(); + List list = examQuestionsListService.selectExamQuestionsList(examQuestionsList.getBankCodes()); + return getDataTable(list); + } + + @GetMapping("/selectlist/{examCode}") + public AjaxResult selectList(@PathVariable("examCode") String examCode) + { + List list = examQuestionsListService.selectChoiceExamQuestionsList(examCode); + return AjaxResult.success(list); + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsPropertyController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsPropertyController.java new file mode 100644 index 0000000..c70900c --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamQuestionsPropertyController.java @@ -0,0 +1,113 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.service.IExamQuestionsPropertyService; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 题目属性Controller + * + * @author qnsdt + * @date 2022-12-28 + */ +@RestController +@RequestMapping("/questions/questionsproperty") +public class ExamQuestionsPropertyController extends BaseController +{ + @Autowired + private IExamQuestionsPropertyService examQuestionsPropertyService; + + @Autowired + private TokenService tokenService; + + /** + * 查询题目属性列表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:list')") + @GetMapping("/list") + public TableDataInfo list(ExamQuestionsProperty examQuestionsProperty) + { + startPage(); + List list = examQuestionsPropertyService.selectExamQuestionsPropertyList(examQuestionsProperty); + return getDataTable(list); + } + + /** + * 导出题目属性列表 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:export')") + @Log(title = "题目属性", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamQuestionsProperty examQuestionsProperty) + { + List list = examQuestionsPropertyService.selectExamQuestionsPropertyList(examQuestionsProperty); + ExcelUtil util = new ExcelUtil(ExamQuestionsProperty.class); + return util.exportExcel(list, "题目属性数æ®"); + } + + /** + * 获å–é¢˜ç›®å±žæ€§è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:query')") + @GetMapping(value = "/{questionsCode}") + public AjaxResult getInfo(@PathVariable("questionsCode") String questionsCode) + { + return AjaxResult.success(examQuestionsPropertyService.selectExamQuestionsPropertyById(questionsCode)); + } + + /** + * 新增题目属性 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:add')") + @Log(title = "题目属性", businessType = BusinessType.INSERT) + @PostMapping("/add") + public AjaxResult add(@RequestBody ExamQuestionsProperty examQuestionsProperty) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + examQuestionsProperty.setCreateBy(loginUser.getUser().getUserName()); + examQuestionsProperty.setCreateDept(loginUser.getUser().getDept().getDeptId()); + + return toAjax(examQuestionsPropertyService.insertExamQuestionsProperty(examQuestionsProperty)); + } + + /** + * 修改题目属性 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:edit')") + @Log(title = "题目属性", businessType = BusinessType.UPDATE) + @PostMapping("/update") + public AjaxResult edit(@RequestBody ExamQuestionsProperty examQuestionsProperty) + { + return toAjax(examQuestionsPropertyService.updateExamQuestionsProperty(examQuestionsProperty)); + } + + /** + * 删除题目属性 + */ + @PreAuthorize("@ss.hasPermi('questions:questionsproperty:remove')") + @Log(title = "题目属性", businessType = BusinessType.DELETE) + @GetMapping("/delete/{questionsCodes}") + public AjaxResult remove(@PathVariable String[] questionsCodes) + { + return toAjax(examQuestionsPropertyService.deleteExamQuestionsPropertyByIds(questionsCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamTypeController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamTypeController.java new file mode 100644 index 0000000..307ba74 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/controller/ExamTypeController.java @@ -0,0 +1,120 @@ +package com.yanzhu.exam.questions.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.questions.domain.ExamType; +import com.yanzhu.exam.questions.service.IExamTypeService; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; + +/** + * 考试分类Controller + * + * @author qnsdt + * @date 2022-12-14 + */ +@RestController +@RequestMapping("/questions/examtype") +public class ExamTypeController extends BaseController +{ + @Autowired + private IExamTypeService examTypeService; + + @Autowired + private TokenService tokenService; + + /** + * 查询考试分类列表 + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:list')") + @GetMapping("/list") + public AjaxResult list(ExamType examType) + { + List list = examTypeService.selectExamTypeList(examType); + return AjaxResult.success(list); + } + + /** + * 导出考试分类列表 + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:export')") + @Log(title = "考试分类", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(ExamType examType) + { + List list = examTypeService.selectExamTypeList(examType); + ExcelUtil util = new ExcelUtil(ExamType.class); + return util.exportExcel(list, "考试分类数æ®"); + } + + /** + * 获å–部门下拉树列表 + */ + @GetMapping("/typetreeselect") + public AjaxResult treeselect(ExamType examType) + { + List list = examTypeService.selectExamTypeList(examType); + return AjaxResult.success(examTypeService.buildTypeTreeSelect(list)); + } + /** + * 获å–è€ƒè¯•åˆ†ç±»è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:query')") + @GetMapping(value = "/{typeId}") + public AjaxResult getInfo(@PathVariable("typeId") Long typeId) + { + return AjaxResult.success(examTypeService.selectExamTypeById(typeId)); + } + + /** + * 新增考试分类 + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:add')") + @Log(title = "考试分类", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ExamType examType) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + // System.out.println("loginUser:" + loginUser.toString()); + examType.setCreateBy(loginUser.getUser().getUserName()); + return toAjax(examTypeService.insertExamType(examType)); + } + + /** + * 修改考试分类 + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:edit')") + @Log(title = "考试分类", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ExamType examType) + { + return toAjax(examTypeService.updateExamType(examType)); + } + + /** + * 删除考试分类 + */ + @PreAuthorize("@ss.hasPermi('questions:examtype:remove')") + @Log(title = "考试分类", businessType = BusinessType.DELETE) + @DeleteMapping("/{typeIds}") + public AjaxResult remove(@PathVariable Long[] typeIds) + { + return toAjax(examTypeService.deleteExamTypeByIds(typeIds)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamBankPicture.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamBankPicture.java new file mode 100644 index 0000000..8eb6e7f --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamBankPicture.java @@ -0,0 +1,134 @@ +package com.yanzhu.exam.questions.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 题库图片对象 exam_bank_picture + * + * @author qnsdt + * @date 2022-12-22 + */ +public class ExamBankPicture extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 图片åºå· */ + @Excel(name = "图片åºå·") + private Long photoId; + + /** å›¾ç‰‡ä»£ç  */ + @Excel(name = "图片代ç ") + private String photoCode; + + /** æ–‡æ¡£ä»£ç  */ + @Excel(name = "文档代ç ") + private String photoPath; + + /** 图片链接 */ + @Excel(name = "图片链接") + private String photoUrl; + + /** 文件åç§° */ + @Excel(name = "文件åç§°") + private String fileName; + + /** 原始åç§° */ + @Excel(name = "原始åç§°") + private String originalName; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + public void setPhotoId(Long photoId) + { + this.photoId = photoId; + } + + public Long getPhotoId() + { + return photoId; + } + public void setPhotoCode(String photoCode) + { + this.photoCode = photoCode; + } + + public String getPhotoCode() + { + return photoCode; + } + public void setPhotoPath(String photoPath) + { + this.photoPath = photoPath; + } + + public String getPhotoPath() + { + return photoPath; + } + public void setPhotoUrl(String photoUrl) + { + this.photoUrl = photoUrl; + } + + public String getPhotoUrl() + { + return photoUrl; + } + public void setFileName(String fileName) + { + this.fileName = fileName; + } + + public String getFileName() + { + return fileName; + } + public void setOriginalName(String originalName) + { + this.originalName = originalName; + } + + public String getOriginalName() + { + return originalName; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + + + public ExamBankPicture(String photoCode, String photoPath, String photoUrl, String fileName, String originalName) { + super(); + this.photoCode = photoCode; + this.photoPath = photoPath; + this.photoUrl = photoUrl; + this.fileName = fileName; + this.originalName = originalName; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("photoId", getPhotoId()) + .append("photoCode", getPhotoCode()) + .append("photoPath", getPhotoPath()) + .append("photoUrl", getPhotoUrl()) + .append("fileName", getFileName()) + .append("originalName", getOriginalName()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("status", getStatus()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestions.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestions.java new file mode 100644 index 0000000..ac19d72 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestions.java @@ -0,0 +1,346 @@ +package com.yanzhu.exam.questions.domain; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试题目对象 exam_questions + * + * @author qnsdt + * @date 2022-12-28 + */ +public class ExamQuestions extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** é¢˜åº“ä»£ç  */ + @Excel(name = "题库代ç ") + private String bankCode; + + /** 试题id */ + @Excel(name = "试题id") + private Long questionsId; + + /** è¯•é¢˜ä»£ç  */ + private String questionsCode; + + /** 试题题目 */ + @Excel(name = "试题题目") + private String questionsTitle; + + /** 试题内容 */ + @Excel(name = "试题内容") + private String questionsContent; + + /** 试题类型 */ + @Excel(name = "试题类型") + private String questionsTypeStr; + + private Integer questionsType; + + /** 题目分数 */ + @Excel(name = "题目分数") + private Integer questionsScore; + + /** 夿‚度 */ + @Excel(name = "夿‚度") + private String rateNumberStr; + private Integer rateNumber; + + /** 夿‚度 */ + @Excel(name = "A") + private String answerA; + + /** 夿‚度 */ + @Excel(name = "B") + private String answerB; + + /** 夿‚度 */ + @Excel(name = "C") + private String answerC; + + /** 夿‚度 */ + @Excel(name = "D") + private String answerD; + + /** 夿‚度 */ + @Excel(name = "E") + private String answerE; + + /** 夿‚度 */ + @Excel(name = "F") + private String answerF; + + /** 夿‚度 */ + @Excel(name = "G") + private String answerG; + + /** 夿‚度 */ + @Excel(name = "H") + private String answerH; + + /** 夿‚度 */ + @Excel(name = "I") + private String answerI; + + /** 夿‚度 */ + @Excel(name = "J") + private String answerJ; + + /** 正确答案 */ + @Excel(name = "正确答案") + private String rightAnswer; + + /** ç­”æ¡ˆåˆ†æž */ + @Excel(name = "答案分æž") + private String answerAnalyse; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Integer status; + + /** 创建部门 */ + @Excel(name = "创建部门") + private Long createDept; + + /** 题目选项 */ + private List answerList ; + + public String getQuestionsTypeStr() { + return questionsTypeStr; + } + + public void setQuestionsTypeStr(String questionsTypeStr) { + this.questionsTypeStr = questionsTypeStr; + } + + public String getRateNumberStr() { + return rateNumberStr; + } + + public void setRateNumberStr(String rateNumberStr) { + this.rateNumberStr = rateNumberStr; + } + + public String getAnswerA() { + return answerA; + } + + public void setAnswerA(String answerA) { + this.answerA = answerA; + } + + public String getAnswerB() { + return answerB; + } + + public void setAnswerB(String answerB) { + this.answerB = answerB; + } + + public String getAnswerC() { + return answerC; + } + + public void setAnswerC(String answerC) { + this.answerC = answerC; + } + + public String getAnswerD() { + return answerD; + } + + public void setAnswerD(String answerD) { + this.answerD = answerD; + } + + public String getAnswerE() { + return answerE; + } + + public void setAnswerE(String answerE) { + this.answerE = answerE; + } + + public String getAnswerF() { + return answerF; + } + + public void setAnswerF(String answerF) { + this.answerF = answerF; + } + + public String getAnswerG() { + return answerG; + } + + public void setAnswerG(String answerG) { + this.answerG = answerG; + } + + public String getAnswerH() { + return answerH; + } + + public void setAnswerH(String answerH) { + this.answerH = answerH; + } + + public String getAnswerI() { + return answerI; + } + + public void setAnswerI(String answerI) { + this.answerI = answerI; + } + + public String getAnswerJ() { + return answerJ; + } + + public void setAnswerJ(String answerJ) { + this.answerJ = answerJ; + } + + public List getAnswerList() { + return answerList; + } + + public void setAnswerList(List answerList) { + this.answerList = answerList; + } + + public void setBankCode(String bankCode) + { + this.bankCode = bankCode; + } + + public String getBankCode() + { + return bankCode; + } + public void setQuestionsId(Long questionsId) + { + this.questionsId = questionsId; + } + + public Long getQuestionsId() + { + return questionsId; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsTitle(String questionsTitle) + { + this.questionsTitle = questionsTitle; + } + + public String getQuestionsTitle() + { + return questionsTitle; + } + public void setQuestionsContent(String questionsContent) + { + this.questionsContent = questionsContent; + } + + public String getQuestionsContent() + { + return questionsContent; + } + public void setQuestionsType(Integer questionsType) + { + this.questionsType = questionsType; + } + + public Integer getQuestionsType() + { + return questionsType; + } + public void setQuestionsScore(Integer questionsScore) + { + this.questionsScore = questionsScore; + } + + public Integer getQuestionsScore() + { + return questionsScore; + } + public void setRateNumber(Integer rateNumber) + { + this.rateNumber = rateNumber; + } + + public Integer getRateNumber() + { + return rateNumber; + } + public void setRightAnswer(String rightAnswer) + { + this.rightAnswer = rightAnswer; + } + + public String getRightAnswer() + { + return rightAnswer; + } + public void setAnswerAnalyse(String answerAnalyse) + { + this.answerAnalyse = answerAnalyse; + } + + public String getAnswerAnalyse() + { + return answerAnalyse; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + public void setCreateDept(Long createDept) + { + this.createDept = createDept; + } + + public Long getCreateDept() + { + return createDept; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("bankCode", getBankCode()) + .append("questionsId", getQuestionsId()) + .append("questionsCode", getQuestionsCode()) + .append("questionsTitle", getQuestionsTitle()) + .append("questionsContent", getQuestionsContent()) + .append("questionsType", getQuestionsType()) + .append("questionsScore", getQuestionsScore()) + .append("rateNumber", getRateNumber()) + .append("rightAnswer", getRightAnswer()) + .append("answerAnalyse", getAnswerAnalyse()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createDept", getCreateDept()) + .append("createTime", getCreateTime()) + .append("answerList", getAnswerList()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsAnswer.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsAnswer.java new file mode 100644 index 0000000..57f4e78 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsAnswer.java @@ -0,0 +1,94 @@ +package com.yanzhu.exam.questions.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 考试题目答案对象 exam_questions_answer + * + * @author qnsdt + * @date 2022-12-29 + */ +public class ExamQuestionsAnswer extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è¯•é¢˜ä»£ç  */ + @Excel(name = "试题代ç ") + private String questionsCode; + + /** 试题选项 */ + @Excel(name = "试题选项") + private String optionCode; + + /** 选项æè¿° */ + @Excel(name = "选项æè¿°") + private String optionDescribe; + + /** æ˜¯å¦æ­£ç¡® */ + @Excel(name = "æ˜¯å¦æ­£ç¡®") + private Integer isRight; + + /** 排åºç¼–å· */ + @Excel(name = "排åºç¼–å·") + private Long orderId; + + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setOptionCode(String optionCode) + { + this.optionCode = optionCode; + } + + public String getOptionCode() + { + return optionCode; + } + public void setOptionDescribe(String optionDescribe) + { + this.optionDescribe = optionDescribe; + } + + public String getOptionDescribe() + { + return optionDescribe; + } + public void setIsRight(Integer isRight) + { + this.isRight = isRight; + } + + public Integer getIsRight() + { + return isRight; + } + public void setOrderId(Long orderId) + { + this.orderId = orderId; + } + + public Long getOrderId() + { + return orderId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("questionsCode", getQuestionsCode()) + .append("optionCode", getOptionCode()) + .append("optionDescribe", getOptionDescribe()) + .append("isRight", getIsRight()) + .append("orderId", getOrderId()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsBank.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsBank.java new file mode 100644 index 0000000..4e4ec62 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsBank.java @@ -0,0 +1,262 @@ +package com.yanzhu.exam.questions.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 题库管ç†å¯¹è±¡ exam_questions_bank + * + * @author qnsdt + * @date 2022-12-19 + */ +public class ExamQuestionsBank extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 题库id */ + @Excel(name = "题库id") + private Long bankId; + + /** é¢˜åº“ä»£ç  */ + private String bankCode; + + /** 题库åç§° */ + @Excel(name = "题库åç§°") + private String bankName; + + /** 题库æè¿° */ + @Excel(name = "题库æè¿°") + private String bankDescribe; + + /** 题库版本 */ + @Excel(name = "题库版本") + private String bankVersion; + + /** 考试类型 */ + // @Excel(name = "考试类型") + private Long examType; + + /** 考试类型 */ + @Excel(name = "考试类型") + private String typeName; + + + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + /** 上线日期 */ + private Date onlineDate; + + /** 图片链接 */ + @Excel(name = "图片链接") + private String pictureUrl; + + /** å•选题数 */ + @Excel(name = "å•选题数") + private int radioNumber; + + + /** 多选题数 */ + @Excel(name = "多选题数") + private int choiceNumber; + + /** 判断题数 */ + @Excel(name = "判断题数") + private int judgeNumber; + + /** å•选分数 */ + @Excel(name = "å•选分数") + private double radioScore; + + /** 多选分数 */ + @Excel(name = "多选分数") + private double choiceScore; + + /** 判断分数 */ + @Excel(name = "判断分数") + private double judgeScore; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + /** 创建部门 */ + private Long createDept; + + public void setBankId(Long bankId) + { + this.bankId = bankId; + } + + public Long getBankId() + { + return bankId; + } + public void setBankCode(String bankCode) + { + this.bankCode = bankCode; + } + + public String getBankCode() + { + return bankCode; + } + public void setBankName(String bankName) + { + this.bankName = bankName; + } + + public String getBankName() + { + return bankName; + } + public void setBankDescribe(String bankDescribe) + { + this.bankDescribe = bankDescribe; + } + + public String getBankDescribe() + { + return bankDescribe; + } + public void setBankVersion(String bankVersion) + { + this.bankVersion = bankVersion; + } + + public String getBankVersion() + { + return bankVersion; + } + public void setExamType(Long examType) + { + this.examType = examType; + } + + public Long getExamType() + { + return examType; + } + public void setOnlineDate(Date onlineDate) + { + this.onlineDate = onlineDate; + } + + public Date getOnlineDate() + { + return onlineDate; + } + public void setPictureUrl(String pictureUrl) + { + this.pictureUrl = pictureUrl; + } + + public String getPictureUrl() + { + return pictureUrl; + } + public void setRadioScore(Long radioScore) + { + this.radioScore = radioScore; + } + + public int getRadioNumber() { + return radioNumber; + } + + public void setRadioNumber(int radioNumber) { + this.radioNumber = radioNumber; + } + + public int getChoiceNumber() { + return choiceNumber; + } + + public void setChoiceNumber(int choiceNumber) { + this.choiceNumber = choiceNumber; + } + + public int getJudgeNumber() { + return judgeNumber; + } + + public void setJudgeNumber(int judgeNumber) { + this.judgeNumber = judgeNumber; + } + + public double getRadioScore() + { + return radioScore; + } + public void setChoiceScore(Long choiceScore) + { + this.choiceScore = choiceScore; + } + + public double getChoiceScore() + { + return choiceScore; + } + public void setJudgeScore(Long judgeScore) + { + this.judgeScore = judgeScore; + } + + public double getJudgeScore() + { + return judgeScore; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + public void setCreateDept(Long createDept) + { + this.createDept = createDept; + } + + public Long getCreateDept() + { + return createDept; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("bankId", getBankId()) + .append("bankCode", getBankCode()) + .append("bankName", getBankName()) + .append("bankDescribe", getBankDescribe()) + .append("bankVersion", getBankVersion()) + .append("examType", getExamType()) + .append("typeName", getTypeName()) + .append("onlineDate", getOnlineDate()) + .append("pictureUrl", getPictureUrl()) + .append("radioNumber", getRadioNumber()) + .append("choiceNumber", getChoiceNumber()) + .append("judgeNumber", getJudgeNumber()) + .append("radioScore", getRadioScore()) + .append("choiceScore", getChoiceScore()) + .append("judgeScore", getJudgeScore()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createDept", getCreateDept()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsContent.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsContent.java new file mode 100644 index 0000000..39b6857 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsContent.java @@ -0,0 +1,59 @@ +package com.yanzhu.exam.questions.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 题目内容表对象 exam_questions_content + * + * @author qnsdt + * @date 2022-12-28 + */ +public class ExamQuestionsContent extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** è¯•é¢˜ä»£ç  */ + @Excel(name = "试题代ç ") + private String questionsCode; + + /** 试题题目 */ + @Excel(name = "试题题目") + private String questionsContent; + + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsContent(String questionsContent) + { + this.questionsContent = questionsContent; + } + + public String getQuestionsContent() + { + return questionsContent; + } + + + public ExamQuestionsContent(String questionsCode, String questionsContent) { + super(); + this.questionsCode = questionsCode; + this.questionsContent = questionsContent; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("questionsCode", getQuestionsCode()) + .append("questionsContent", getQuestionsContent()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsList.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsList.java new file mode 100644 index 0000000..c421147 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsList.java @@ -0,0 +1,222 @@ +package com.yanzhu.exam.questions.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 题目属性对象 exam_questions_property + * + * @author qnsdt + * @date 2022-12-28 + */ +public class ExamQuestionsList extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + private int rownum; + + public int getRownum() { + return rownum; + } + + public void setRownum(int rownum) { + this.rownum = rownum; + } + + /** é¢˜åº“ä»£ç  */ + @Excel(name = "题库代ç ") + private String bankCode; + + private String[] bankCodes; + + public String[] getBankCodes() { + return bankCodes; + } + + public void setBankCodes(String[] bankCodes) { + this.bankCodes = bankCodes; + } + + /** 题库åç§° */ + @Excel(name = "题库åç§°") + private String bankName; + + public String getBankName() { + return bankName; + } + + public void setBankName(String bankName) { + this.bankName = bankName; + } + + /** 试题id */ + @Excel(name = "试题id") + private Long questionsId; + + /** è¯•é¢˜ä»£ç  */ + private String questionsCode; + + /** 试题题目 */ + @Excel(name = "试题题目") + private String questionsTitle; + + /** 试题类型 */ + @Excel(name = "试题类型") + private Integer questionsType; + + /** 题目分数 */ + @Excel(name = "题目分数") + private Integer questionsScore; + + /** 夿‚度 */ + @Excel(name = "夿‚度") + private Integer rateNumber; + + /** 正确答案 */ + @Excel(name = "正确答案") + private String rightAnswer; + + /** ç­”æ¡ˆåˆ†æž */ + @Excel(name = "答案分æž") + private String answerAnalyse; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Integer status; + + private String createBy; + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + /** 创建部门 */ + private Long createDept; + + public void setBankCode(String bankCode) + { + this.bankCode = bankCode; + } + + public String getBankCode() + { + return bankCode; + } + public void setQuestionsId(Long questionsId) + { + this.questionsId = questionsId; + } + + public Long getQuestionsId() + { + return questionsId; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsTitle(String questionsTitle) + { + this.questionsTitle = questionsTitle; + } + + public String getQuestionsTitle() + { + return questionsTitle; + } + public void setQuestionsType(Integer questionsType) + { + this.questionsType = questionsType; + } + + public Integer getQuestionsType() + { + return questionsType; + } + public void setQuestionsScore(Integer questionsScore) + { + this.questionsScore = questionsScore; + } + + public Integer getQuestionsScore() + { + return questionsScore; + } + public void setRateNumber(Integer rateNumber) + { + this.rateNumber = rateNumber; + } + + public Integer getRateNumber() + { + return rateNumber; + } + public void setRightAnswer(String rightAnswer) + { + this.rightAnswer = rightAnswer; + } + + public String getRightAnswer() + { + return rightAnswer; + } + public void setAnswerAnalyse(String answerAnalyse) + { + this.answerAnalyse = answerAnalyse; + } + + public String getAnswerAnalyse() + { + return answerAnalyse; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + public void setCreateDept(Long createDept) + { + this.createDept = createDept; + } + + public Long getCreateDept() + { + return createDept; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("bankCode", getBankCode()) + .append("bankCodes", getBankCodes()) + .append("bankName", getBankName()) + .append("questionsId", getQuestionsId()) + .append("questionsCode", getQuestionsCode()) + .append("questionsTitle", getQuestionsTitle()) + .append("questionsType", getQuestionsType()) + .append("questionsScore", getQuestionsScore()) + .append("rateNumber", getRateNumber()) + .append("rightAnswer", getRightAnswer()) + .append("answerAnalyse", getAnswerAnalyse()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createDept", getCreateDept()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsProperty.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsProperty.java new file mode 100644 index 0000000..9e1a399 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamQuestionsProperty.java @@ -0,0 +1,241 @@ +package com.yanzhu.exam.questions.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 题目属性对象 exam_questions_property + * + * @author qnsdt + * @date 2022-12-28 + */ +public class ExamQuestionsProperty extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + private int rownum; + + public int getRownum() { + return rownum; + } + + public void setRownum(int rownum) { + this.rownum = rownum; + } + + /** é¢˜åº“ä»£ç  */ + @Excel(name = "题库代ç ") + private String bankCode; + + /** 试题id */ + @Excel(name = "试题id") + private Long questionsId; + + /** è¯•é¢˜ä»£ç  */ + private String questionsCode; + + /** 试题题目 */ + @Excel(name = "试题题目") + private String questionsTitle; + + /** 试题类型 */ + @Excel(name = "试题类型") + private Integer questionsType; + + /** 题目分数 */ + @Excel(name = "题目分数") + private Integer questionsScore; + + /** 夿‚度 */ + @Excel(name = "夿‚度") + private Integer rateNumber; + + /** 正确答案 */ + @Excel(name = "正确答案") + private String rightAnswer; + + /** ç­”æ¡ˆåˆ†æž */ + @Excel(name = "答案分æž") + private String answerAnalyse; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Integer status; + + private String createBy; + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + /** 创建部门 */ + private Long createDept; + + public void setBankCode(String bankCode) + { + this.bankCode = bankCode; + } + + public String getBankCode() + { + return bankCode; + } + public void setQuestionsId(Long questionsId) + { + this.questionsId = questionsId; + } + + public Long getQuestionsId() + { + return questionsId; + } + public void setQuestionsCode(String questionsCode) + { + this.questionsCode = questionsCode; + } + + public String getQuestionsCode() + { + return questionsCode; + } + public void setQuestionsTitle(String questionsTitle) + { + this.questionsTitle = questionsTitle; + } + + public String getQuestionsTitle() + { + return questionsTitle; + } + public void setQuestionsType(Integer questionsType) + { + this.questionsType = questionsType; + } + + public Integer getQuestionsType() + { + return questionsType; + } + public void setQuestionsScore(Integer questionsScore) + { + this.questionsScore = questionsScore; + } + + public Integer getQuestionsScore() + { + return questionsScore; + } + public void setRateNumber(Integer rateNumber) + { + this.rateNumber = rateNumber; + } + + public Integer getRateNumber() + { + return rateNumber; + } + public void setRightAnswer(String rightAnswer) + { + this.rightAnswer = rightAnswer; + } + + public String getRightAnswer() + { + return rightAnswer; + } + public void setAnswerAnalyse(String answerAnalyse) + { + this.answerAnalyse = answerAnalyse; + } + + public String getAnswerAnalyse() + { + return answerAnalyse; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + public void setCreateDept(Long createDept) + { + this.createDept = createDept; + } + + public Long getCreateDept() + { + return createDept; + } + + + + public ExamQuestionsProperty() { + super(); + } + + public ExamQuestionsProperty(int rownum, String bankCode, Long questionsId, String questionsCode, + String questionsTitle, Integer questionsType, Integer questionsScore, Integer rateNumber, + String rightAnswer, String answerAnalyse, Integer status, String createBy, Long createDept) { + super(); + this.rownum = rownum; + this.bankCode = bankCode; + this.questionsId = questionsId; + this.questionsCode = questionsCode; + this.questionsTitle = questionsTitle; + this.questionsType = questionsType; + this.questionsScore = questionsScore; + this.rateNumber = rateNumber; + this.rightAnswer = rightAnswer; + this.answerAnalyse = answerAnalyse; + this.status = status; + this.createBy = createBy; + this.createDept = createDept; + } + + public ExamQuestionsProperty(String bankCode, Long questionsId, String questionsCode, String questionsTitle, + Integer questionsType, Integer questionsScore, Integer rateNumber, String rightAnswer, String answerAnalyse, + Integer status, String createBy, Long createDept) { + super(); + this.bankCode = bankCode; + this.questionsId = questionsId; + this.questionsCode = questionsCode; + this.questionsTitle = questionsTitle; + this.questionsType = questionsType; + this.questionsScore = questionsScore; + this.rateNumber = rateNumber; + this.rightAnswer = rightAnswer; + this.answerAnalyse = answerAnalyse; + this.status = status; + this.createBy = createBy; + this.createDept = createDept; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("bankCode", getBankCode()) + .append("questionsId", getQuestionsId()) + .append("questionsCode", getQuestionsCode()) + .append("questionsTitle", getQuestionsTitle()) + .append("questionsType", getQuestionsType()) + .append("questionsScore", getQuestionsScore()) + .append("rateNumber", getRateNumber()) + .append("rightAnswer", getRightAnswer()) + .append("answerAnalyse", getAnswerAnalyse()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createDept", getCreateDept()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamType.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamType.java new file mode 100644 index 0000000..500f288 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/ExamType.java @@ -0,0 +1,126 @@ +package com.yanzhu.exam.questions.domain; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.domain.TreeEntity; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * 考试分类对象 exam_type + * + * @author qnsdt + * @date 2022-12-14 + */ +public class ExamType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 类别id */ + private Long typeId; + + /** parentid */ + private Long parentId; + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + /** ç±»åˆ«ä»£ç  */ + @Excel(name = "类别代ç ") + private String typeCode; + + /** 类别åç§° */ + @Excel(name = "类别åç§°") + private String typeName; + + /** 顺åºId */ + @Excel(name = "顺åºId") + private Long orderId; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private Long status; + + /** å­ç±»åˆ« */ + private List children = new ArrayList(); + + public void setTypeId(Long typeId) + { + this.typeId = typeId; + } + + + + + public Long getTypeId() + { + return typeId; + } + public void setTypeCode(String typeCode) + { + this.typeCode = typeCode; + } + + public String getTypeCode() + { + return typeCode; + } + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTypeName() + { + return typeName; + } + public void setOrderId(Long orderId) + { + this.orderId = orderId; + } + + public Long getOrderId() + { + return orderId; + } + public void setStatus(Long status) + { + this.status = status; + } + + public Long getStatus() + { + return status; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("typeId", getTypeId()) + .append("parentId", getParentId()) + .append("typeCode", getTypeCode()) + .append("typeName", getTypeName()) + .append("orderId", getOrderId()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/TypeTreeSelect.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/TypeTreeSelect.java new file mode 100644 index 0000000..6d7759a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/domain/TypeTreeSelect.java @@ -0,0 +1,72 @@ +package com.yanzhu.exam.questions.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * Treeselect树结构实体类 + * + * @author ruoyi + */ +public class TypeTreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点åç§° */ + private String label; + + /** å­èŠ‚ç‚¹ */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TypeTreeSelect() + { + + } + + public TypeTreeSelect(ExamType examType) + { + this.id = examType.getTypeId(); + this.label = examType.getTypeName(); + + this.children = examType.getChildren().stream().map(TypeTreeSelect::new).collect(Collectors.toList()); + } + + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamBankPictureMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamBankPictureMapper.java new file mode 100644 index 0000000..58d5bd9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamBankPictureMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamBankPicture; + +/** + * 题库图片MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-22 + */ +public interface ExamBankPictureMapper +{ + /** + * 查询题库图片 + * + * @param photoCode 题库图片ID + * @return 题库图片 + */ + public ExamBankPicture selectExamBankPictureById(String photoCode); + + /** + * 查询题库图片列表 + * + * @param examBankPicture 题库图片 + * @return é¢˜åº“å›¾ç‰‡é›†åˆ + */ + public List selectExamBankPictureList(ExamBankPicture examBankPicture); + + /** + * 新增题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + public int insertExamBankPicture(ExamBankPicture examBankPicture); + + /** + * 修改题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + public int updateExamBankPicture(ExamBankPicture examBankPicture); + + /** + * 删除题库图片 + * + * @param photoCode 题库图片ID + * @return 结果 + */ + public int deleteExamBankPictureById(String photoCode); + + /** + * 批é‡åˆ é™¤é¢˜åº“图片 + * + * @param photoCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamBankPictureByIds(String[] photoCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsAnswerMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsAnswerMapper.java new file mode 100644 index 0000000..3e8e78b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsAnswerMapper.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; + +/** + * 考试题目答案MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-29 + */ +public interface ExamQuestionsAnswerMapper +{ + /** + * 查询考试题目答案 + * + * @param questionsCode 考试题目答案ID + * @return 考试题目答案 + */ + public ExamQuestionsAnswer selectExamQuestionsAnswerById(String questionsCode); + + /** + * 查询考试题目答案列表 + * + * @param examQuestionsAnswer 考试题目答案 + * @return è€ƒè¯•é¢˜ç›®ç­”æ¡ˆé›†åˆ + */ + public List selectExamQuestionsAnswerList(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 查询考试题目答案选项 + * + * @param questionsCode é¢˜ç›®ä»£ç  + * @return è€ƒè¯•é¢˜ç›®ç­”æ¡ˆé›†åˆ + */ + public List selectExamQuestionsOptionList(String questionsCode); + + /** + * 新增考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + public int insertExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 修改考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + public int updateExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 删除考试题目答案 + * + * @param questionsCode 考试题目答案ID + * @return 结果 + */ + public int deleteExamQuestionsAnswerById(String questionsCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目答案 + * + * @param questionsCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamQuestionsAnswerByIds(String[] questionsCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsBankMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsBankMapper.java new file mode 100644 index 0000000..3435ede --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsBankMapper.java @@ -0,0 +1,77 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsBank; + +/** + * 题库管ç†MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-19 + */ +public interface ExamQuestionsBankMapper +{ + /** + * æŸ¥è¯¢é¢˜åº“ç®¡ç† + * + * @param bankCode 题库管ç†ID + * @return é¢˜åº“ç®¡ç† + */ + public ExamQuestionsBank selectExamQuestionsBankById(String bankCode); + + /** + * æ ¹æ®é¢˜åº“åç§°æŸ¥è¯¢é¢˜åº“ç®¡ç† + * + * @param bankName 题库åç§° + * @return é¢˜åº“ç®¡ç† + */ + public ExamQuestionsBank selectExamQuestionsBankByName(String bankName); + + /** + * 查询题库管ç†åˆ—表 + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 题库管ç†é›†åˆ + */ + public List selectExamQuestionsBankList(ExamQuestionsBank examQuestionsBank); + + /** + * 查询题库管ç†åˆ—表 + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 题库管ç†é›†åˆ + */ + public List selectExamQuestionsBankListByCode(String[] bankCodes); + + /** + * æ–°å¢žé¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + public int insertExamQuestionsBank(ExamQuestionsBank examQuestionsBank); + + /** + * ä¿®æ”¹é¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + public int updateExamQuestionsBank(ExamQuestionsBank examQuestionsBank); + + /** + * åˆ é™¤é¢˜åº“ç®¡ç† + * + * @param bankCode 题库管ç†ID + * @return 结果 + */ + public int deleteExamQuestionsBankById(String bankCode); + + /** + * 批é‡åˆ é™¤é¢˜åº“ç®¡ç† + * + * @param bankCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamQuestionsBankByIds(String[] bankCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsContentMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsContentMapper.java new file mode 100644 index 0000000..f84ba23 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsContentMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; + +/** + * 题目内容表MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface ExamQuestionsContentMapper +{ + /** + * 查询题目内容表 + * + * @param questionsCode 题目内容表ID + * @return 题目内容表 + */ + public ExamQuestionsContent selectExamQuestionsContentById(String questionsCode); + + /** + * 查询题目内容表列表 + * + * @param examQuestionsContent 题目内容表 + * @return é¢˜ç›®å†…å®¹è¡¨é›†åˆ + */ + public List selectExamQuestionsContentList(ExamQuestionsContent examQuestionsContent); + + /** + * 新增题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + public int insertExamQuestionsContent(ExamQuestionsContent examQuestionsContent); + + /** + * 修改题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + public int updateExamQuestionsContent(ExamQuestionsContent examQuestionsContent); + + /** + * 删除题目内容表 + * + * @param questionsCode 题目内容表ID + * @return 结果 + */ + public int deleteExamQuestionsContentById(String questionsCode); + + /** + * 批é‡åˆ é™¤é¢˜ç›®å†…容表 + * + * @param questionsCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamQuestionsContentByIds(String[] questionsCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsListMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsListMapper.java new file mode 100644 index 0000000..f927bd7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsListMapper.java @@ -0,0 +1,25 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; + +/** + * 题目属性MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface ExamQuestionsListMapper +{ + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return é¢˜ç›®å±žæ€§é›†åˆ + */ + public List selectExamQuestionsList(String[] bankCodes); + + public List selectChoiceExamQuestionsList(String examCode); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsMapper.java new file mode 100644 index 0000000..10ab96a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsMapper.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestions; + +/** + * 考试题目MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface ExamQuestionsMapper +{ + /** + * 查询考试题目 + * + * @param questionsCode 考试题目ID + * @return 考试题目 + */ + public ExamQuestions selectExamQuestionsById(String questionsCode); + + /** + * æ ¹æ®é¢˜ç›®æ ‡é¢˜æŸ¥è¯¢è€ƒè¯•题目 + * + * @param questionsTitle 题目标题 + * @return 考试题目 + */ + public ExamQuestions selectExamQuestionsByTitle(String questionsTitle); + + /** + * 查询考试题目列表 + * + * @param examQuestions 考试题目 + * @return è€ƒè¯•é¢˜ç›®é›†åˆ + */ + public List selectExamQuestionsList(ExamQuestions examQuestions); + + /** + * 新增考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + public int insertExamQuestions(ExamQuestions examQuestions); + + /** + * 修改考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + public int updateExamQuestions(ExamQuestions examQuestions); + + /** + * 删除考试题目 + * + * @param questionsCode 考试题目ID + * @return 结果 + */ + public int deleteExamQuestionsById(String questionsCode); + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目 + * + * @param questionsCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamQuestionsByIds(String[] questionsCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsPropertyMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsPropertyMapper.java new file mode 100644 index 0000000..ba66484 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamQuestionsPropertyMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; + +/** + * 题目属性MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface ExamQuestionsPropertyMapper +{ + /** + * 查询题目属性 + * + * @param questionsCode 题目属性ID + * @return 题目属性 + */ + public ExamQuestionsProperty selectExamQuestionsPropertyById(String questionsCode); + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return é¢˜ç›®å±žæ€§é›†åˆ + */ + public List selectExamQuestionsPropertyList(ExamQuestionsProperty examQuestionsProperty); + + /** + * 新增题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + public int insertExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty); + + /** + * 修改题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + public int updateExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty); + + /** + * 删除题目属性 + * + * @param questionsCode 题目属性ID + * @return 结果 + */ + public int deleteExamQuestionsPropertyById(String questionsCode); + + /** + * 批é‡åˆ é™¤é¢˜ç›®å±žæ€§ + * + * @param questionsCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamQuestionsPropertyByIds(String[] questionsCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamTypeMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamTypeMapper.java new file mode 100644 index 0000000..8655654 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/mapper/ExamTypeMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.mapper; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamType; + +/** + * 考试分类MapperæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-14 + */ +public interface ExamTypeMapper +{ + /** + * 查询考试分类 + * + * @param typeId 考试分类ID + * @return 考试分类 + */ + public ExamType selectExamTypeById(Long typeId); + + /** + * 查询考试分类列表 + * + * @param examType 考试分类 + * @return è€ƒè¯•åˆ†ç±»é›†åˆ + */ + public List selectExamTypeList(ExamType examType); + + /** + * 新增考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + public int insertExamType(ExamType examType); + + /** + * 修改考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + public int updateExamType(ExamType examType); + + /** + * 删除考试分类 + * + * @param typeId 考试分类ID + * @return 结果 + */ + public int deleteExamTypeById(Long typeId); + + /** + * 批é‡åˆ é™¤è€ƒè¯•分类 + * + * @param typeIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteExamTypeByIds(Long[] typeIds); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamBankPictureService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamBankPictureService.java new file mode 100644 index 0000000..98d4fe3 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamBankPictureService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamBankPicture; + +/** + * 题库图片ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-22 + */ +public interface IExamBankPictureService +{ + /** + * 查询题库图片 + * + * @param photoCode 题库图片ID + * @return 题库图片 + */ + public ExamBankPicture selectExamBankPictureById(String photoCode); + + /** + * 查询题库图片列表 + * + * @param examBankPicture 题库图片 + * @return é¢˜åº“å›¾ç‰‡é›†åˆ + */ + public List selectExamBankPictureList(ExamBankPicture examBankPicture); + + /** + * 新增题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + public int insertExamBankPicture(ExamBankPicture examBankPicture); + + /** + * 修改题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + public int updateExamBankPicture(ExamBankPicture examBankPicture); + + /** + * 批é‡åˆ é™¤é¢˜åº“图片 + * + * @param photoCodes 需è¦åˆ é™¤çš„题库图片ID + * @return 结果 + */ + public int deleteExamBankPictureByIds(String[] photoCodes); + + /** + * åˆ é™¤é¢˜åº“å›¾ç‰‡ä¿¡æ¯ + * + * @param photoCode 题库图片ID + * @return 结果 + */ + public int deleteExamBankPictureById(String photoCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsAnswerService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsAnswerService.java new file mode 100644 index 0000000..6b84e3a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsAnswerService.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; + +/** + * 考试题目答案ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-29 + */ +public interface IExamQuestionsAnswerService +{ + /** + * 查询考试题目答案 + * + * @param questionsCode 考试题目答案ID + * @return 考试题目答案 + */ + public ExamQuestionsAnswer selectExamQuestionsAnswerById(String questionsCode); + + /** + * 查询考试题目答案列表 + * + * @param examQuestionsAnswer 考试题目答案 + * @return è€ƒè¯•é¢˜ç›®ç­”æ¡ˆé›†åˆ + */ + public List selectExamQuestionsAnswerList(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 查询考试题目答案选项 + * + * @param questionsCode é¢˜ç›®ä»£ç  + * @return è€ƒè¯•é¢˜ç›®ç­”æ¡ˆé›†åˆ + */ + public List selectExamQuestionsOptionList(String questionsCode); + + /** + * 新增考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + public int insertExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 修改考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + public int updateExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer); + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目答案 + * + * @param questionsCodes 需è¦åˆ é™¤çš„考试题目答案ID + * @return 结果 + */ + public int deleteExamQuestionsAnswerByIds(String[] questionsCodes); + + /** + * åˆ é™¤è€ƒè¯•é¢˜ç›®ç­”æ¡ˆä¿¡æ¯ + * + * @param questionsCode 考试题目答案ID + * @return 结果 + */ + public int deleteExamQuestionsAnswerById(String questionsCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsBankService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsBankService.java new file mode 100644 index 0000000..af9d287 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsBankService.java @@ -0,0 +1,82 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsBank; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * 题库管ç†ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-19 + */ +public interface IExamQuestionsBankService +{ + /** + * æŸ¥è¯¢é¢˜åº“ç®¡ç† + * + * @param bankCode 题库管ç†ID + * @return é¢˜åº“ç®¡ç† + */ + public ExamQuestionsBank selectExamQuestionsBankById(String bankCode); + + /** + * 查询题库管ç†åˆ—表 + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 题库管ç†é›†åˆ + */ + public List selectExamQuestionsBankList(ExamQuestionsBank examQuestionsBank); + + + /** + * 查询题库管ç†åˆ—表 + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 题库管ç†é›†åˆ + */ + public List selectExamQuestionsBankListByCode(String[] bankCodes); + + /** + * æ–°å¢žé¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + public int insertExamQuestionsBank(ExamQuestionsBank examQuestionsBank); + + /** + * ä¿®æ”¹é¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + public int updateExamQuestionsBank(ExamQuestionsBank examQuestionsBank); + + /** + * 批é‡åˆ é™¤é¢˜åº“ç®¡ç† + * + * @param bankCodes 需è¦åˆ é™¤çš„题库管ç†ID + * @return 结果 + */ + public int deleteExamQuestionsBankByIds(String[] bankCodes); + + /** + * 删除题库管ç†ä¿¡æ¯ + * + * @param bankCode 题库管ç†ID + * @return 结果 + */ + public int deleteExamQuestionsBankById(String bankCode); + + /** + * å¯¼å…¥é¢˜åº“æ•°æ® + * + * @param examQuestionsBankList 题库数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + public String importExamQuestionsBank(List examQuestionsBankList, Boolean isUpdateSupport, String operName); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsContentService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsContentService.java new file mode 100644 index 0000000..834a089 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsContentService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; + +/** + * 题目内容表ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface IExamQuestionsContentService +{ + /** + * 查询题目内容表 + * + * @param questionsCode 题目内容表ID + * @return 题目内容表 + */ + public ExamQuestionsContent selectExamQuestionsContentById(String questionsCode); + + /** + * 查询题目内容表列表 + * + * @param examQuestionsContent 题目内容表 + * @return é¢˜ç›®å†…å®¹è¡¨é›†åˆ + */ + public List selectExamQuestionsContentList(ExamQuestionsContent examQuestionsContent); + + /** + * 新增题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + public int insertExamQuestionsContent(ExamQuestionsContent examQuestionsContent); + + /** + * 修改题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + public int updateExamQuestionsContent(ExamQuestionsContent examQuestionsContent); + + /** + * 批é‡åˆ é™¤é¢˜ç›®å†…容表 + * + * @param questionsCodes 需è¦åˆ é™¤çš„题目内容表ID + * @return 结果 + */ + public int deleteExamQuestionsContentByIds(String[] questionsCodes); + + /** + * åˆ é™¤é¢˜ç›®å†…å®¹è¡¨ä¿¡æ¯ + * + * @param questionsCode 题目内容表ID + * @return 结果 + */ + public int deleteExamQuestionsContentById(String questionsCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsListService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsListService.java new file mode 100644 index 0000000..aaaf086 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsListService.java @@ -0,0 +1,26 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; + +/** + * 题目属性ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface IExamQuestionsListService +{ + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return é¢˜ç›®å±žæ€§é›†åˆ + */ + public List selectExamQuestionsList(String[] bankCodes); + + public List selectChoiceExamQuestionsList(String examCode); + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsPropertyService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsPropertyService.java new file mode 100644 index 0000000..4d511d6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsPropertyService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; + +/** + * 题目属性ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface IExamQuestionsPropertyService +{ + /** + * 查询题目属性 + * + * @param questionsCode 题目属性ID + * @return 题目属性 + */ + public ExamQuestionsProperty selectExamQuestionsPropertyById(String questionsCode); + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return é¢˜ç›®å±žæ€§é›†åˆ + */ + public List selectExamQuestionsPropertyList(ExamQuestionsProperty examQuestionsProperty); + + /** + * 新增题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + public int insertExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty); + + /** + * 修改题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + public int updateExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty); + + /** + * 批é‡åˆ é™¤é¢˜ç›®å±žæ€§ + * + * @param questionsCodes 需è¦åˆ é™¤çš„题目属性ID + * @return 结果 + */ + public int deleteExamQuestionsPropertyByIds(String[] questionsCodes); + + /** + * åˆ é™¤é¢˜ç›®å±žæ€§ä¿¡æ¯ + * + * @param questionsCode 题目属性ID + * @return 结果 + */ + public int deleteExamQuestionsPropertyById(String questionsCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsService.java new file mode 100644 index 0000000..2d947b6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamQuestionsService.java @@ -0,0 +1,79 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamQuestions; + +/** + * 考试题目ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-28 + */ +public interface IExamQuestionsService +{ + /** + * 查询考试题目 + * + * @param questionsCode 考试题目ID + * @return 考试题目 + */ + public ExamQuestions selectExamQuestionsById(String questionsCode); + + /** + * 查询考试题目列表 + * + * @param examQuestions 考试题目 + * @return è€ƒè¯•é¢˜ç›®é›†åˆ + */ + public List selectExamQuestionsList(ExamQuestions examQuestions); + + /** + * 新增考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + public int insertExamQuestions(ExamQuestions examQuestions); + + /** + * 修改考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + public int updateExamQuestions(ExamQuestions examQuestions); + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目 + * + * @param questionsCodes 需è¦åˆ é™¤çš„考试题目ID + * @return 结果 + */ + public int deleteExamQuestionsByIds(String[] questionsCodes); + + /** + * åˆ é™¤è€ƒè¯•é¢˜ç›®ä¿¡æ¯ + * + * @param questionsCode 考试题目ID + * @return 结果 + */ + public int deleteExamQuestionsById(String questionsCode); + + /** + * å¯¼å…¥è€ƒè¯•é¢˜ç›®æ•°æ® + * + * @param examQuestionsList 考试题目数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + public String importExamQuestions(List examQuestionsList, Boolean isUpdateSupport, String operName); + + /** + * æ ¹æ®é¢˜ç›®æ ‡é¢˜æŸ¥è¯¢è€ƒè¯•题目 + * + * @param questionsTitle 题目标题 + * @return 考试题目 + */ + public ExamQuestions selectExamQuestionsByTitle(String questionsTitle); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamTypeService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamTypeService.java new file mode 100644 index 0000000..0de6c89 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/IExamTypeService.java @@ -0,0 +1,79 @@ +package com.yanzhu.exam.questions.service; + +import java.util.List; +import com.yanzhu.exam.questions.domain.ExamType; +import com.yanzhu.exam.questions.domain.TypeTreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * 考试分类ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2022-12-14 + */ +public interface IExamTypeService +{ + /** + * 查询考试分类 + * + * @param typeId 考试分类ID + * @return 考试分类 + */ + public ExamType selectExamTypeById(Long typeId); + + /** + * 查询考试分类列表 + * + * @param examType 考试分类 + * @return è€ƒè¯•åˆ†ç±»é›†åˆ + */ + public List selectExamTypeList(ExamType examType); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦æ ‘结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + public List buildTypeTree(List examTypeList); + + /** + * 构建å‰ç«¯æ‰€éœ€è¦ä¸‹æ‹‰æ ‘结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + public List buildTypeTreeSelect(List examTypeList); + + /** + * 新增考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + public int insertExamType(ExamType examType); + + /** + * 修改考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + public int updateExamType(ExamType examType); + + /** + * 批é‡åˆ é™¤è€ƒè¯•分类 + * + * @param typeIds 需è¦åˆ é™¤çš„考试分类ID + * @return 结果 + */ + public int deleteExamTypeByIds(Long[] typeIds); + + /** + * åˆ é™¤è€ƒè¯•åˆ†ç±»ä¿¡æ¯ + * + * @param typeId 考试分类ID + * @return 结果 + */ + public int deleteExamTypeById(Long typeId); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamBankPictureServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamBankPictureServiceImpl.java new file mode 100644 index 0000000..e78062c --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamBankPictureServiceImpl.java @@ -0,0 +1,95 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamBankPictureMapper; +import com.yanzhu.exam.questions.domain.ExamBankPicture; +import com.yanzhu.exam.questions.service.IExamBankPictureService; + +/** + * 题库图片Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-22 + */ +@Service +public class ExamBankPictureServiceImpl implements IExamBankPictureService +{ + @Autowired + private ExamBankPictureMapper examBankPictureMapper; + + /** + * 查询题库图片 + * + * @param photoCode 题库图片ID + * @return 题库图片 + */ + @Override + public ExamBankPicture selectExamBankPictureById(String photoCode) + { + return examBankPictureMapper.selectExamBankPictureById(photoCode); + } + + /** + * 查询题库图片列表 + * + * @param examBankPicture 题库图片 + * @return 题库图片 + */ + @Override + public List selectExamBankPictureList(ExamBankPicture examBankPicture) + { + return examBankPictureMapper.selectExamBankPictureList(examBankPicture); + } + + /** + * 新增题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + @Override + public int insertExamBankPicture(ExamBankPicture examBankPicture) + { + examBankPicture.setCreateTime(DateUtils.getNowDate()); + return examBankPictureMapper.insertExamBankPicture(examBankPicture); + } + + /** + * 修改题库图片 + * + * @param examBankPicture 题库图片 + * @return 结果 + */ + @Override + public int updateExamBankPicture(ExamBankPicture examBankPicture) + { + return examBankPictureMapper.updateExamBankPicture(examBankPicture); + } + + /** + * 批é‡åˆ é™¤é¢˜åº“图片 + * + * @param photoCodes 需è¦åˆ é™¤çš„题库图片ID + * @return 结果 + */ + @Override + public int deleteExamBankPictureByIds(String[] photoCodes) + { + return examBankPictureMapper.deleteExamBankPictureByIds(photoCodes); + } + + /** + * åˆ é™¤é¢˜åº“å›¾ç‰‡ä¿¡æ¯ + * + * @param photoCode 题库图片ID + * @return 结果 + */ + @Override + public int deleteExamBankPictureById(String photoCode) + { + return examBankPictureMapper.deleteExamBankPictureById(photoCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsAnswerServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsAnswerServiceImpl.java new file mode 100644 index 0000000..5c65c68 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsAnswerServiceImpl.java @@ -0,0 +1,99 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamQuestionsAnswerMapper; +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; +import com.yanzhu.exam.questions.service.IExamQuestionsAnswerService; + +/** + * 考试题目答案Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-29 + */ +@Service +public class ExamQuestionsAnswerServiceImpl implements IExamQuestionsAnswerService +{ + @Autowired + private ExamQuestionsAnswerMapper examQuestionsAnswerMapper; + + /** + * 查询考试题目答案 + * + * @param questionsCode 考试题目答案ID + * @return 考试题目答案 + */ + @Override + public ExamQuestionsAnswer selectExamQuestionsAnswerById(String questionsCode) + { + return examQuestionsAnswerMapper.selectExamQuestionsAnswerById(questionsCode); + } + + /** + * 查询考试题目答案列表 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 考试题目答案 + */ + @Override + public List selectExamQuestionsAnswerList(ExamQuestionsAnswer examQuestionsAnswer) + { + return examQuestionsAnswerMapper.selectExamQuestionsAnswerList(examQuestionsAnswer); + } + + /** + * 新增考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + @Override + public int insertExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer) + { + return examQuestionsAnswerMapper.insertExamQuestionsAnswer(examQuestionsAnswer); + } + + /** + * 修改考试题目答案 + * + * @param examQuestionsAnswer 考试题目答案 + * @return 结果 + */ + @Override + public int updateExamQuestionsAnswer(ExamQuestionsAnswer examQuestionsAnswer) + { + return examQuestionsAnswerMapper.updateExamQuestionsAnswer(examQuestionsAnswer); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目答案 + * + * @param questionsCodes 需è¦åˆ é™¤çš„考试题目答案ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsAnswerByIds(String[] questionsCodes) + { + return examQuestionsAnswerMapper.deleteExamQuestionsAnswerByIds(questionsCodes); + } + + /** + * åˆ é™¤è€ƒè¯•é¢˜ç›®ç­”æ¡ˆä¿¡æ¯ + * + * @param questionsCode 考试题目答案ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsAnswerById(String questionsCode) + { + return examQuestionsAnswerMapper.deleteExamQuestionsAnswerById(questionsCode); + } + + @Override + public List selectExamQuestionsOptionList(String questionsCode) { + // TODO Auto-generated method stub + return examQuestionsAnswerMapper.selectExamQuestionsOptionList(questionsCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsBankServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsBankServiceImpl.java new file mode 100644 index 0000000..339b50f --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsBankServiceImpl.java @@ -0,0 +1,180 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import cn.hutool.core.lang.UUID; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.exception.CustomException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamQuestionsBankMapper; +import com.yanzhu.exam.questions.domain.ExamQuestionsBank; +import com.yanzhu.exam.questions.service.IExamQuestionsBankService; + +/** + * 题库管ç†Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-19 + */ +@Service +public class ExamQuestionsBankServiceImpl implements IExamQuestionsBankService +{ + @Autowired + private ExamQuestionsBankMapper examQuestionsBankMapper; + + /** + * æŸ¥è¯¢é¢˜åº“ç®¡ç† + * + * @param bankCode 题库管ç†ID + * @return é¢˜åº“ç®¡ç† + */ + @Override + public ExamQuestionsBank selectExamQuestionsBankById(String bankCode) + { + return examQuestionsBankMapper.selectExamQuestionsBankById(bankCode); + } + + /** + * 查询题库管ç†åˆ—表 + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return é¢˜åº“ç®¡ç† + */ + @Override + public List selectExamQuestionsBankList(ExamQuestionsBank examQuestionsBank) + { + return examQuestionsBankMapper.selectExamQuestionsBankList(examQuestionsBank); + } + + /** + * æ–°å¢žé¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + @Override + public int insertExamQuestionsBank(ExamQuestionsBank examQuestionsBank) + { + examQuestionsBank.setCreateTime(DateUtils.getNowDate()); + return examQuestionsBankMapper.insertExamQuestionsBank(examQuestionsBank); + } + + /** + * ä¿®æ”¹é¢˜åº“ç®¡ç† + * + * @param examQuestionsBank é¢˜åº“ç®¡ç† + * @return 结果 + */ + @Override + public int updateExamQuestionsBank(ExamQuestionsBank examQuestionsBank) + { + return examQuestionsBankMapper.updateExamQuestionsBank(examQuestionsBank); + } + + /** + * 批é‡åˆ é™¤é¢˜åº“ç®¡ç† + * + * @param bankCodes 需è¦åˆ é™¤çš„题库管ç†ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsBankByIds(String[] bankCodes) + { + return examQuestionsBankMapper.deleteExamQuestionsBankByIds(bankCodes); + } + + /** + * 删除题库管ç†ä¿¡æ¯ + * + * @param bankCode 题库管ç†ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsBankById(String bankCode) + { + return examQuestionsBankMapper.deleteExamQuestionsBankById(bankCode); + } + + @Override + public List selectExamQuestionsBankListByCode(String[] bankCodes) { + // TODO Auto-generated method stub + return examQuestionsBankMapper.selectExamQuestionsBankListByCode(bankCodes); + } + + /** + * å¯¼å…¥é¢˜åº“æ•°æ® + * + * @param examQuestionsBankList 题库数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + @Override + public String importExamQuestionsBank(List examQuestionsBankList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(examQuestionsBankList) || examQuestionsBankList.size() == 0) + { + throw new CustomException("导入题库数æ®ä¸èƒ½ä¸ºç©ºï¼"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + for (ExamQuestionsBank examQuestionsBank : examQuestionsBankList) + { + try + { + // éªŒè¯æ˜¯å¦å­˜åœ¨è¿™ä¸ªé¢˜åº“ + ExamQuestionsBank b = examQuestionsBankMapper.selectExamQuestionsBankByName(examQuestionsBank.getBankName()); + if (StringUtils.isNull(b)) + { + examQuestionsBank.setBankCode(UUID.randomUUID().toString()); + examQuestionsBank.setCreateBy(operName); + examQuestionsBank.setCreateTime(DateUtils.getNowDate()); + this.insertExamQuestionsBank(examQuestionsBank); + successNum++; + successMsg.append("
" + successNum + "ã€é¢˜åº“ " + examQuestionsBank.getBankName() + " 导入æˆåŠŸ"); + } + else if (isUpdateSupport) + { + examQuestionsBank.setBankCode(b.getBankCode()); + examQuestionsBank.setUpdateBy(operName); + this.updateExamQuestionsBank(examQuestionsBank); + successNum++; + successMsg.append("
" + successNum + "ã€é¢˜åº“ " + examQuestionsBank.getBankName() + " æ›´æ–°æˆåŠŸ"); + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "ã€é¢˜åº“ " + examQuestionsBank.getBankName() + " 已存在"); + } + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "ã€é¢˜åº“ " + examQuestionsBank.getBankName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败ï¼å…± " + failureNum + " æ¡æ•°æ®æ ¼å¼ä¸æ­£ç¡®ï¼Œé”™è¯¯å¦‚下:"); + throw new CustomException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "æ­å–œæ‚¨ï¼Œæ•°æ®å·²å…¨éƒ¨å¯¼å…¥æˆåŠŸï¼å…± " + successNum + " æ¡ï¼Œæ•°æ®å¦‚下:"); + } + return successMsg.toString(); + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsContentServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsContentServiceImpl.java new file mode 100644 index 0000000..6a2f4c4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsContentServiceImpl.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamQuestionsContentMapper; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; +import com.yanzhu.exam.questions.service.IExamQuestionsContentService; + +/** + * 题目内容表Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-28 + */ +@Service +public class ExamQuestionsContentServiceImpl implements IExamQuestionsContentService +{ + @Autowired + private ExamQuestionsContentMapper examQuestionsContentMapper; + + /** + * 查询题目内容表 + * + * @param questionsCode 题目内容表ID + * @return 题目内容表 + */ + @Override + public ExamQuestionsContent selectExamQuestionsContentById(String questionsCode) + { + return examQuestionsContentMapper.selectExamQuestionsContentById(questionsCode); + } + + /** + * 查询题目内容表列表 + * + * @param examQuestionsContent 题目内容表 + * @return 题目内容表 + */ + @Override + public List selectExamQuestionsContentList(ExamQuestionsContent examQuestionsContent) + { + return examQuestionsContentMapper.selectExamQuestionsContentList(examQuestionsContent); + } + + /** + * 新增题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + @Override + public int insertExamQuestionsContent(ExamQuestionsContent examQuestionsContent) + { + return examQuestionsContentMapper.insertExamQuestionsContent(examQuestionsContent); + } + + /** + * 修改题目内容表 + * + * @param examQuestionsContent 题目内容表 + * @return 结果 + */ + @Override + public int updateExamQuestionsContent(ExamQuestionsContent examQuestionsContent) + { + return examQuestionsContentMapper.updateExamQuestionsContent(examQuestionsContent); + } + + /** + * 批é‡åˆ é™¤é¢˜ç›®å†…容表 + * + * @param questionsCodes 需è¦åˆ é™¤çš„题目内容表ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsContentByIds(String[] questionsCodes) + { + return examQuestionsContentMapper.deleteExamQuestionsContentByIds(questionsCodes); + } + + /** + * åˆ é™¤é¢˜ç›®å†…å®¹è¡¨ä¿¡æ¯ + * + * @param questionsCode 题目内容表ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsContentById(String questionsCode) + { + return examQuestionsContentMapper.deleteExamQuestionsContentById(questionsCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsListServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsListServiceImpl.java new file mode 100644 index 0000000..b231bb7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsListServiceImpl.java @@ -0,0 +1,49 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.questions.mapper.ExamQuestionsListMapper; +import com.yanzhu.exam.questions.mapper.ExamQuestionsPropertyMapper; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.service.IExamQuestionsListService; +import com.yanzhu.exam.questions.service.IExamQuestionsPropertyService; + +/** + * 题目属性Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-28 + */ +@Service +public class ExamQuestionsListServiceImpl implements IExamQuestionsListService +{ + @Autowired + private ExamQuestionsListMapper examQuestionsListMapper; + + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return 题目属性 + */ + @Override + public List selectExamQuestionsList(String[] bankCodes) + { + return examQuestionsListMapper.selectExamQuestionsList(bankCodes); + } + + + @Override + public List selectChoiceExamQuestionsList(String examCode) { + // TODO Auto-generated method stub + return examQuestionsListMapper.selectChoiceExamQuestionsList(examCode); + } + + + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsPropertyServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsPropertyServiceImpl.java new file mode 100644 index 0000000..e9a7ab7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsPropertyServiceImpl.java @@ -0,0 +1,95 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamQuestionsPropertyMapper; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.service.IExamQuestionsPropertyService; + +/** + * 题目属性Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-28 + */ +@Service +public class ExamQuestionsPropertyServiceImpl implements IExamQuestionsPropertyService +{ + @Autowired + private ExamQuestionsPropertyMapper examQuestionsPropertyMapper; + + /** + * 查询题目属性 + * + * @param questionsCode 题目属性ID + * @return 题目属性 + */ + @Override + public ExamQuestionsProperty selectExamQuestionsPropertyById(String questionsCode) + { + return examQuestionsPropertyMapper.selectExamQuestionsPropertyById(questionsCode); + } + + /** + * 查询题目属性列表 + * + * @param examQuestionsProperty 题目属性 + * @return 题目属性 + */ + @Override + public List selectExamQuestionsPropertyList(ExamQuestionsProperty examQuestionsProperty) + { + return examQuestionsPropertyMapper.selectExamQuestionsPropertyList(examQuestionsProperty); + } + + /** + * 新增题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + @Override + public int insertExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty) + { + examQuestionsProperty.setCreateTime(DateUtils.getNowDate()); + return examQuestionsPropertyMapper.insertExamQuestionsProperty(examQuestionsProperty); + } + + /** + * 修改题目属性 + * + * @param examQuestionsProperty 题目属性 + * @return 结果 + */ + @Override + public int updateExamQuestionsProperty(ExamQuestionsProperty examQuestionsProperty) + { + return examQuestionsPropertyMapper.updateExamQuestionsProperty(examQuestionsProperty); + } + + /** + * 批é‡åˆ é™¤é¢˜ç›®å±žæ€§ + * + * @param questionsCodes 需è¦åˆ é™¤çš„题目属性ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsPropertyByIds(String[] questionsCodes) + { + return examQuestionsPropertyMapper.deleteExamQuestionsPropertyByIds(questionsCodes); + } + + /** + * åˆ é™¤é¢˜ç›®å±žæ€§ä¿¡æ¯ + * + * @param questionsCode 题目属性ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsPropertyById(String questionsCode) + { + return examQuestionsPropertyMapper.deleteExamQuestionsPropertyById(questionsCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsServiceImpl.java new file mode 100644 index 0000000..c2655db --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamQuestionsServiceImpl.java @@ -0,0 +1,208 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.List; +import java.util.UUID; + +import com.yanzhu.exam.questions.domain.ExamQuestionsAnswer; +import com.yanzhu.exam.questions.domain.ExamQuestionsContent; +import com.yanzhu.exam.questions.domain.ExamQuestionsProperty; +import com.yanzhu.exam.questions.mapper.ExamQuestionsAnswerMapper; +import com.yanzhu.exam.questions.mapper.ExamQuestionsContentMapper; +import com.yanzhu.exam.questions.mapper.ExamQuestionsPropertyMapper; +import com.ruoyi.common.exception.CustomException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamQuestionsMapper; +import com.yanzhu.exam.questions.domain.ExamQuestions; +import com.yanzhu.exam.questions.service.IExamQuestionsService; + +/** + * 考试题目Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-28 + */ +@Service +public class ExamQuestionsServiceImpl implements IExamQuestionsService +{ + @Autowired + private ExamQuestionsMapper examQuestionsMapper; + + @Autowired + private ExamQuestionsPropertyMapper examQuestionsPropertyMapper; + + @Autowired + private ExamQuestionsContentMapper examQuestionsContentMapper; + + @Autowired + private ExamQuestionsAnswerMapper examQuestionsAnswerMapper; + /** + * 查询考试题目 + * + * @param questionsCode 考试题目ID + * @return 考试题目 + */ + @Override + public ExamQuestions selectExamQuestionsById(String questionsCode) + { + return examQuestionsMapper.selectExamQuestionsById(questionsCode); + } + + /** + * 查询考试题目列表 + * + * @param examQuestions 考试题目 + * @return 考试题目 + */ + @Override + public List selectExamQuestionsList(ExamQuestions examQuestions) + { + return examQuestionsMapper.selectExamQuestionsList(examQuestions); + } + + /** + * 新增考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + @Override + public int insertExamQuestions(ExamQuestions examQuestions) + { + examQuestions.setCreateTime(DateUtils.getNowDate()); + return examQuestionsMapper.insertExamQuestions(examQuestions); + } + + /** + * 修改考试题目 + * + * @param examQuestions 考试题目 + * @return 结果 + */ + @Override + public int updateExamQuestions(ExamQuestions examQuestions) + { + return examQuestionsMapper.updateExamQuestions(examQuestions); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•题目 + * + * @param questionsCodes 需è¦åˆ é™¤çš„考试题目ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsByIds(String[] questionsCodes) + { + return examQuestionsMapper.deleteExamQuestionsByIds(questionsCodes); + } + + /** + * åˆ é™¤è€ƒè¯•é¢˜ç›®ä¿¡æ¯ + * + * @param questionsCode 考试题目ID + * @return 结果 + */ + @Override + public int deleteExamQuestionsById(String questionsCode) + { + return examQuestionsMapper.deleteExamQuestionsById(questionsCode); + } + + /** + * æ ¹æ®é¢˜ç›®æ ‡é¢˜æŸ¥è¯¢è€ƒè¯•题目 + * + * @param questionsTitle 题目标题 + * @return 考试题目 + */ + @Override + public ExamQuestions selectExamQuestionsByTitle(String questionsTitle) + { + return examQuestionsMapper.selectExamQuestionsByTitle(questionsTitle); + } + + /** + * å¯¼å…¥è€ƒè¯•é¢˜ç›®æ•°æ® + * + * @param examQuestionsList 考试题目数æ®åˆ—表 + * @param isUpdateSupport æ˜¯å¦æ›´æ–°æ”¯æŒï¼Œå¦‚æžœå·²å­˜åœ¨ï¼Œåˆ™è¿›è¡Œæ›´æ–°æ•°æ® + * @param operName æ“作用户 + * @return 结果 + */ + @Override + public String importExamQuestions(List examQuestionsList, Boolean isUpdateSupport, String operName) { + if (StringUtils.isNull(examQuestionsList) || examQuestionsList.size() == 0) { + throw new CustomException("导入考试题目数æ®ä¸èƒ½ä¸ºç©ºï¼"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + for (ExamQuestions examQuestions : examQuestionsList) { + + try { + ExamQuestionsProperty examProperty = new ExamQuestionsProperty(); + examProperty.setBankCode(examQuestions.getBankCode()); + examProperty.setQuestionsCode(examQuestions.getQuestionsCode()); + examProperty.setQuestionsTitle(examQuestions.getQuestionsTitle()); + examProperty.setQuestionsScore(examQuestions.getQuestionsScore()); + examProperty.setQuestionsType(examQuestions.getQuestionsType()); + examProperty.setRateNumber(examQuestions.getRateNumber()); + examProperty.setAnswerAnalyse(examQuestions.getAnswerAnalyse()); + examProperty.setRightAnswer(examQuestions.getRightAnswer()); + examProperty.setStatus(0); + examProperty.setCreateTime(DateUtils.getNowDate()); + examProperty.setCreateBy(examQuestions.getCreateBy()); + examQuestionsPropertyMapper.insertExamQuestionsProperty(examProperty); + ExamQuestionsContent examContent = new ExamQuestionsContent( + examQuestions.getQuestionsCode(), examQuestions.getQuestionsContent() + ); + examQuestionsContentMapper.insertExamQuestionsContent(examContent); + + ExamQuestionsAnswer answer = new ExamQuestionsAnswer(); + answer.setQuestionsCode(examQuestions.getQuestionsCode()); + int idx = -1; + String opt = "ABCDEFGHIJKLMN"; + + String code = ""; + String rightAnswer = examQuestions.getRightAnswer(); + if (StringUtils.isEmpty(rightAnswer)) { + rightAnswer = ""; + } + String[] tmps = new String[]{ + examQuestions.getAnswerA(), + examQuestions.getAnswerB(), + examQuestions.getAnswerC(), + examQuestions.getAnswerD(), + examQuestions.getAnswerE(), + examQuestions.getAnswerF(), + examQuestions.getAnswerG(), + examQuestions.getAnswerH() + }; + for (String tmp : tmps) { + if (StringUtils.isNotEmpty(tmp)) { + idx++; + code = "" + opt.charAt(idx); + answer.setOptionCode(code); + answer.setOptionDescribe(tmp); + answer.setIsRight(rightAnswer.contains(code) ? 0 : 1); + examQuestionsAnswerMapper.insertExamQuestionsAnswer(answer); + } + } + successNum++; + }catch (Exception e){ + failureNum++; + } + + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败ï¼å…± " + failureNum + " æ¡æ•°æ®æ ¼å¼ä¸æ­£ç¡®ï¼Œé”™è¯¯å¦‚下:"); + throw new CustomException(failureMsg.toString()); + } else { + successMsg.insert(0, "æ­å–œæ‚¨ï¼Œæ•°æ®å·²å…¨éƒ¨å¯¼å…¥æˆåŠŸï¼å…± " + successNum + " æ¡ï¼Œæ•°æ®å¦‚下:"); + } + return successMsg.toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamTypeServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamTypeServiceImpl.java new file mode 100644 index 0000000..9ed14ae --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/questions/service/impl/ExamTypeServiceImpl.java @@ -0,0 +1,183 @@ +package com.yanzhu.exam.questions.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; + +import java.util.Iterator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.questions.mapper.ExamTypeMapper; +import com.yanzhu.exam.questions.domain.ExamType; +import com.yanzhu.exam.questions.domain.TypeTreeSelect; +import com.yanzhu.exam.questions.service.IExamTypeService; + +/** + * 考试分类Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2022-12-14 + */ +@Service +public class ExamTypeServiceImpl implements IExamTypeService +{ + @Autowired + private ExamTypeMapper examTypeMapper; + + /** + * 查询考试分类 + * + * @param typeId 考试分类ID + * @return 考试分类 + */ + @Override + public ExamType selectExamTypeById(Long typeId) + { + return examTypeMapper.selectExamTypeById(typeId); + } + + /** + * 查询考试分类列表 + * + * @param examType 考试分类 + * @return 考试分类 + */ + @Override + public List selectExamTypeList(ExamType examType) + { + return examTypeMapper.selectExamTypeList(examType); + } + + /** + * 新增考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + @Override + public int insertExamType(ExamType examType) + { + examType.setCreateTime(DateUtils.getNowDate()); + return examTypeMapper.insertExamType(examType); + } + + /** + * 修改考试分类 + * + * @param examType 考试分类 + * @return 结果 + */ + @Override + public int updateExamType(ExamType examType) + { + return examTypeMapper.updateExamType(examType); + } + + /** + * 批é‡åˆ é™¤è€ƒè¯•分类 + * + * @param typeIds 需è¦åˆ é™¤çš„考试分类ID + * @return 结果 + */ + @Override + public int deleteExamTypeByIds(Long[] typeIds) + { + return examTypeMapper.deleteExamTypeByIds(typeIds); + } + + /** + * åˆ é™¤è€ƒè¯•åˆ†ç±»ä¿¡æ¯ + * + * @param typeId 考试分类ID + * @return 结果 + */ + @Override + public int deleteExamTypeById(Long typeId) + { + return examTypeMapper.deleteExamTypeById(typeId); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, ExamType t) + { + // 得到å­èŠ‚ç‚¹åˆ—è¡¨ + List childList = getChildList(list, t); + t.setChildren(childList); + for (ExamType tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到å­èŠ‚ç‚¹åˆ—è¡¨ + */ + private List getChildList(List list, ExamType t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + ExamType n = (ExamType) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getTypeId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * åˆ¤æ–­æ˜¯å¦æœ‰å­èŠ‚ç‚¹ + */ + private boolean hasChild(List list, ExamType t) + { + return getChildList(list, t).size() > 0 ? true : false; + } + + + @Override + public List buildTypeTree(List examTypeList) { + // TODO Auto-generated method stub + List returnList = new ArrayList(); + List tempList = new ArrayList(); + for (ExamType examtype : examTypeList) + { + tempList.add(examtype.getTypeId()); + } + for (Iterator iterator = examTypeList.iterator(); iterator.hasNext();) + { + ExamType examtype = (ExamType) iterator.next(); + // 如果是顶级节点, é历该父节点的所有å­èŠ‚ç‚¹ + if (!tempList.contains(examtype.getParentId())) + { + recursionFn(examTypeList, examtype); + returnList.add(examtype); + } + } + if (returnList.isEmpty()) + { + returnList = examTypeList; + } + return returnList; + } + + @Override + public List buildTypeTreeSelect(List examTypeList) { + // TODO Auto-generated method stub + List typeTrees = buildTypeTree(examTypeList); + return typeTrees.stream().map(TypeTreeSelect::new).collect(Collectors.toList()); + } + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupController.java new file mode 100644 index 0000000..495caf0 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupController.java @@ -0,0 +1,122 @@ +package com.yanzhu.exam.system.controller; + +import java.util.List; +import java.util.UUID; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.system.domain.SysGroup; +import com.yanzhu.exam.system.service.ISysGroupService; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 人员分组Controller + * + * @author qnsdt + * @date 2023-01-28 + */ +@RestController +@RequestMapping("/system/group") +public class SysGroupController extends BaseController +{ + @Autowired + private ISysGroupService sysGroupService; + + @Autowired + private TokenService tokenService; + + /** + * 查询人员分组列表 + */ + @PreAuthorize("@ss.hasPermi('system:group:list')") + @GetMapping("/list") + public TableDataInfo list(SysGroup sysGroup) + { + startPage(); + List list = sysGroupService.selectSysGroupList(sysGroup); + return getDataTable(list); + } + + @GetMapping("/choicelist/{examCode}") + public TableDataInfo selectChoiceSysGroupList(@PathVariable String examCode) { + // TODO Auto-generated method stub + startPage(); + List list = sysGroupService.selectChoiceSysGroupList(examCode); + return getDataTable(list); + } + /** + * 导出人员分组列表 + */ + @PreAuthorize("@ss.hasPermi('system:group:export')") + @Log(title = "人员分组", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SysGroup sysGroup) + { + List list = sysGroupService.selectSysGroupList(sysGroup); + ExcelUtil util = new ExcelUtil(SysGroup.class); + return util.exportExcel(list, "人员分组数æ®"); + } + + /** + * 获å–äººå‘˜åˆ†ç»„è¯¦ç»†ä¿¡æ¯ + */ + @PreAuthorize("@ss.hasPermi('system:group:query')") + @GetMapping(value = "/{groupId}") + public AjaxResult getInfo(@PathVariable("groupId") Long groupId) + { + return AjaxResult.success(sysGroupService.selectSysGroupById(groupId)); + } + + /** + * 新增人员分组 + */ + @PreAuthorize("@ss.hasPermi('system:group:add')") + @Log(title = "人员分组", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysGroup sysGroup) + { + sysGroup.setGroupCode(UUID.randomUUID().toString()); + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + sysGroup.setCreateBy(loginUser.getUser().getUserName()); + + return toAjax(sysGroupService.insertSysGroup(sysGroup)); + } + + /** + * 修改人员分组 + */ + @PreAuthorize("@ss.hasPermi('system:group:edit')") + @Log(title = "人员分组", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysGroup sysGroup) + { + return toAjax(sysGroupService.updateSysGroup(sysGroup)); + } + + /** + * 删除人员分组 + */ + @PreAuthorize("@ss.hasPermi('system:group:remove')") + @Log(title = "人员分组", businessType = BusinessType.DELETE) + @DeleteMapping("/{groupIds}") + public AjaxResult remove(@PathVariable Long[] groupIds) + { + return toAjax(sysGroupService.deleteSysGroupByIds(groupIds)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupPersonController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupPersonController.java new file mode 100644 index 0000000..5546d95 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysGroupPersonController.java @@ -0,0 +1,93 @@ +package com.yanzhu.exam.system.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.system.domain.SysGroupPerson; +import com.yanzhu.exam.system.service.ISysGroupPersonService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 分组用户Controller + * + * @author qnsdt + * @date 2023-02-06 + */ +@RestController +@RequestMapping("/system/groupperson") +public class SysGroupPersonController extends BaseController +{ + @Autowired + private ISysGroupPersonService sysGroupPersonService; + + /** + * 查询分组用户列表 + */ + @GetMapping("/list") + public TableDataInfo list(SysGroupPerson sysGroupPerson) + { + startPage(); + List list = sysGroupPersonService.selectSysGroupPersonList(sysGroupPerson); + return getDataTable(list); + } + + /** + * 导出分组用户列表 + */ + @GetMapping("/export") + public AjaxResult export(SysGroupPerson sysGroupPerson) + { + List list = sysGroupPersonService.selectSysGroupPersonList(sysGroupPerson); + ExcelUtil util = new ExcelUtil(SysGroupPerson.class); + return util.exportExcel(list, "分组用户数æ®"); + } + + /** + * 获å–åˆ†ç»„ç”¨æˆ·è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{groupCode}") + public AjaxResult getInfo(@PathVariable("groupCode") String groupCode) + { + return AjaxResult.success(sysGroupPersonService.selectSysGroupPersonById(groupCode)); + } + + /** + * 新增分组用户 + */ + @PostMapping + public AjaxResult add(@RequestBody List sysGroupPersonList) + { + return toAjax(sysGroupPersonService.insertSysGroupPerson(sysGroupPersonList)); + } + + /** + * 修改分组用户 + */ + @PostMapping("/update") + public AjaxResult edit(@RequestBody SysGroupPerson sysGroupPerson) + { + return toAjax(sysGroupPersonService.updateSysGroupPerson(sysGroupPerson)); + } + + /** + * 删除分组用户 + */ + @GetMapping("/delete/{groupCodes}") + public AjaxResult remove(@PathVariable String[] groupCodes) + { + return toAjax(sysGroupPersonService.deleteSysGroupPersonByIds(groupCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserChoiceController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserChoiceController.java new file mode 100644 index 0000000..bc78b12 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserChoiceController.java @@ -0,0 +1,118 @@ +package com.yanzhu.exam.system.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.system.domain.SysUserChoice; +import com.yanzhu.exam.system.domain.dto.SysUserCopy; +import com.yanzhu.exam.system.domain.dto.SysUserData; +import com.yanzhu.exam.system.service.ISysUserChoiceService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 选择用户Controller + * + * @author qnsdt + * @date 2023-02-02 + */ +@RestController +@RequestMapping("/system/sysuserchoice") +public class SysUserChoiceController extends BaseController +{ + @Autowired + private ISysUserChoiceService sysUserChoiceService; + + /** + * 查询选择用户列表 + */ + @GetMapping("/list") + public TableDataInfo list(SysUserChoice sysUserChoice) + { + startPage(); + List list = sysUserChoiceService.selectSysUserChoiceList(sysUserChoice); + return getDataTable(list); + } + + @GetMapping("/choiceuserlist") + public AjaxResult selectGroupUserList(SysUserData sysUser) + { + System.out.println("SysUserData:" + sysUser.toString()); + List list = sysUserChoiceService.selectGroupUserList(sysUser); + return AjaxResult.success(list); + + } + + /** + * 导出选择用户列表 + */ + @GetMapping("/export") + public AjaxResult export(SysUserChoice sysUserChoice) + { + List list = sysUserChoiceService.selectSysUserChoiceList(sysUserChoice); + ExcelUtil util = new ExcelUtil(SysUserChoice.class); + return util.exportExcel(list, "选择用户数æ®"); + } + + /** + * 获å–é€‰æ‹©ç”¨æˆ·è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{choiceCode}") + public AjaxResult getInfo(@PathVariable("choiceCode") String choiceCode) + { + return AjaxResult.success(sysUserChoiceService.selectSysUserChoiceById(choiceCode)); + } + + /** + * 新增选择用户 + */ + @PostMapping("/copysysuser") + public AjaxResult copySysUser(@RequestBody SysUserCopy sysUserCopy) + { + return toAjax(sysUserChoiceService.copySysUser(sysUserCopy)); + } + + @PostMapping("/copytempuser") + public AjaxResult copyTempUser(@RequestBody SysUserCopy sysUserCopy) + { + return toAjax(sysUserChoiceService.copyTempUser(sysUserCopy)); + } + /** + * 新增选择用户 + */ + @PostMapping + public AjaxResult add(@RequestBody SysUserChoice sysUserChoice) + { + return toAjax(sysUserChoiceService.insertSysUserChoice(sysUserChoice)); + } + + /** + * 修改选择用户 + */ + @PostMapping("/update") + public AjaxResult edit(@RequestBody SysUserChoice sysUserChoice) + { + return toAjax(sysUserChoiceService.updateSysUserChoice(sysUserChoice)); + } + + /** + * 删除选择用户 + */ + @GetMapping("/delete/{choiceCodes}") + public AjaxResult remove(@PathVariable String[] choiceCodes) + { + return toAjax(sysUserChoiceService.deleteSysUserChoiceByIds(choiceCodes)); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserDataController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserDataController.java new file mode 100644 index 0000000..42bcdd4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/SysUserDataController.java @@ -0,0 +1,41 @@ +package com.yanzhu.exam.system.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.yanzhu.exam.system.domain.TempUserChoice; +import com.yanzhu.exam.system.domain.dto.SysUserData; +import com.yanzhu.exam.system.mapper.SysUserDataMapper; +import com.yanzhu.exam.system.service.ISysUserDataService; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.page.TableDataInfo; + +@RestController +@RequestMapping("/system/userdata") +public class SysUserDataController extends BaseController{ + @Autowired + ISysUserDataService sysUserDataService; + + /** + * 查询用户选择列表 + */ + @GetMapping("/list") + public TableDataInfo list(SysUserData sysUser) + { + startPage(); + List list = sysUserDataService.selectUserList(sysUser); + return getDataTable(list); + } + + @GetMapping("/choicelist") + public TableDataInfo choiceList(SysUserData sysUser) + { + startPage(); + List list = sysUserDataService.selectChoiceUserList(sysUser); + return getDataTable(list); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/TempUserChoiceController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/TempUserChoiceController.java new file mode 100644 index 0000000..e53a5f6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/controller/TempUserChoiceController.java @@ -0,0 +1,100 @@ +package com.yanzhu.exam.system.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.yanzhu.exam.system.domain.TempUserChoice; +import com.yanzhu.exam.system.service.ITempUserChoiceService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 用户选择Controller + * + * @author qnsdt + * @date 2023-01-31 + */ +@RestController +@RequestMapping("/system/userchoice") +public class TempUserChoiceController extends BaseController +{ + @Autowired + private ITempUserChoiceService tempUserChoiceService; + + /** + * 查询用户选择列表 + */ + @GetMapping("/list") + public TableDataInfo list(TempUserChoice tempUserChoice) + { + startPage(); + List list = tempUserChoiceService.selectTempUserChoiceList(tempUserChoice); + return getDataTable(list); + } + + /** + * 导出用户选择列表 + */ + @GetMapping("/export") + public AjaxResult export(TempUserChoice tempUserChoice) + { + List list = tempUserChoiceService.selectTempUserChoiceList(tempUserChoice); + ExcelUtil util = new ExcelUtil(TempUserChoice.class); + return util.exportExcel(list, "用户选择数æ®"); + } + + /** + * 获å–ç”¨æˆ·é€‰æ‹©è¯¦ç»†ä¿¡æ¯ + */ + @GetMapping(value = "/{choiceCode}") + public AjaxResult getInfo(@PathVariable("choiceCode") String choiceCode) + { + return AjaxResult.success(tempUserChoiceService.selectTempUserChoiceById(choiceCode)); + } + + /** + * 新增用户选择 + */ + @PostMapping + public AjaxResult add(@RequestBody TempUserChoice tempUserChoice) + { + return toAjax(tempUserChoiceService.insertTempUserChoice(tempUserChoice)); + } + + /** + * 新增用户选择 + */ + @PostMapping("/batch") + public AjaxResult batchAdd(@RequestBody List userList) + { + return toAjax(tempUserChoiceService.batchInsertTempUser(userList)); + } + + /** + * 修改用户选择 + */ + @PostMapping("/update") + public AjaxResult edit(@RequestBody TempUserChoice tempUserChoice) + { + return toAjax(tempUserChoiceService.updateTempUserChoice(tempUserChoice)); + } + + @PostMapping("/remove") + public AjaxResult remove(@RequestBody List userList) + { + return toAjax(tempUserChoiceService.deleteTempUserChoice(userList)); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroup.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroup.java new file mode 100644 index 0000000..c90622a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroup.java @@ -0,0 +1,106 @@ +package com.yanzhu.exam.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 人员分组对象 sys_group + * + * @author qnsdt + * @date 2023-01-28 + */ +public class SysGroup extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 分组åºå· */ + private Long groupId; + + /** åˆ†ç»„ä»£ç  */ + @Excel(name = "分组代ç ") + private String groupCode; + + /** 分组åç§° */ + @Excel(name = "分组åç§°") + private String groupName; + + private int personNumber; + + public int getPersonNumber() { + return personNumber; + } + + public void setPersonNumber(int personNumber) { + this.personNumber = personNumber; + } + + /** 分组æè¿° */ + @Excel(name = "分组æè¿°") + private String groupDescribe; + + /** çŠ¶æ€ */ + @Excel(name = "状æ€") + private String status; + + public void setGroupId(Long groupId) + { + this.groupId = groupId; + } + + public Long getGroupId() + { + return groupId; + } + public void setGroupCode(String groupCode) + { + this.groupCode = groupCode; + } + + public String getGroupCode() + { + return groupCode; + } + public void setGroupName(String groupName) + { + this.groupName = groupName; + } + + public String getGroupName() + { + return groupName; + } + public void setGroupDescribe(String groupDescribe) + { + this.groupDescribe = groupDescribe; + } + + public String getGroupDescribe() + { + return groupDescribe; + } + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("groupId", getGroupId()) + .append("groupCode", getGroupCode()) + .append("groupName", getGroupName()) + .append("personNumber",getPersonNumber()) + .append("groupDescribe", getGroupDescribe()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroupPerson.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroupPerson.java new file mode 100644 index 0000000..a7d6bf6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysGroupPerson.java @@ -0,0 +1,71 @@ +package com.yanzhu.exam.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 分组用户对象 sys_group_person + * + * @author qnsdt + * @date 2023-02-06 + */ +public class SysGroupPerson extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** åˆ†ç»„ä»£ç  */ + @Excel(name = "分组代ç ") + private String groupCode; + + /** äººå‘˜ä»£ç  */ + @Excel(name = "人员代ç ") + private String personCode; + + /** ç»„å†…æŽ’åº */ + @Excel(name = "组内排åº") + private Long orderId; + + public void setGroupCode(String groupCode) + { + this.groupCode = groupCode; + } + + public String getGroupCode() + { + return groupCode; + } + public void setPersonCode(String personCode) + { + this.personCode = personCode; + } + + public String getPersonCode() + { + return personCode; + } + public void setOrderId(Long orderId) + { + this.orderId = orderId; + } + + public Long getOrderId() + { + return orderId; + } + + + public SysGroupPerson() { + super(); + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("groupCode", getGroupCode()) + .append("personCode", getPersonCode()) + .append("orderId", getOrderId()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysUserChoice.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysUserChoice.java new file mode 100644 index 0000000..9b941c4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/SysUserChoice.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 选择用户对象 sys_user_choice + * + * @author qnsdt + * @date 2023-02-02 + */ +public class SysUserChoice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** é€‰æ‹©ä»£ç  */ + @Excel(name = "选择代ç ") + private String choiceCode; + + /** ç”¨æˆ·ä»£ç  */ + @Excel(name = "用户代ç ") + private String userCode; + + /** å†…éƒ¨æŽ’åº */ + @Excel(name = "内部排åº") + private Integer orderId; + + public void setChoiceCode(String choiceCode) + { + this.choiceCode = choiceCode; + } + + public String getChoiceCode() + { + return choiceCode; + } + public void setUserCode(String userCode) + { + this.userCode = userCode; + } + + public String getUserCode() + { + return userCode; + } + public void setOrderId(Integer orderId) + { + this.orderId = orderId; + } + + public Integer getOrderId() + { + return orderId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("choiceCode", getChoiceCode()) + .append("userCode", getUserCode()) + .append("orderId", getOrderId()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/TempUserChoice.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/TempUserChoice.java new file mode 100644 index 0000000..6f48816 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/TempUserChoice.java @@ -0,0 +1,66 @@ +package com.yanzhu.exam.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 用户选择对象 temp_user_choice + * + * @author qnsdt + * @date 2023-01-31 + */ +public class TempUserChoice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** é€‰æ‹©ä»£ç  */ + @Excel(name = "选择代ç ") + private String choiceCode; + + /** ç”¨æˆ·ä»£ç  */ + @Excel(name = "用户代ç ") + private String userCode; + + /** å†…éƒ¨æŽ’åº */ + @Excel(name = "内部排åº") + private Long orderId; + + public void setChoiceCode(String choiceCode) + { + this.choiceCode = choiceCode; + } + + public String getChoiceCode() + { + return choiceCode; + } + public void setUserCode(String userCode) + { + this.userCode = userCode; + } + + public String getUserCode() + { + return userCode; + } + public void setOrderId(Long orderId) + { + this.orderId = orderId; + } + + public Long getOrderId() + { + return orderId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("choiceCode", getChoiceCode()) + .append("userCode", getUserCode()) + .append("orderId", getOrderId()) + .toString(); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserCopy.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserCopy.java new file mode 100644 index 0000000..384c3b6 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserCopy.java @@ -0,0 +1,11 @@ +package com.yanzhu.exam.system.domain.dto; + +import lombok.Data; + +@Data +public class SysUserCopy { + + private String conditionCode; + private String choiceCode; + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserData.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserData.java new file mode 100644 index 0000000..646bd7f --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/domain/dto/SysUserData.java @@ -0,0 +1,23 @@ +package com.yanzhu.exam.system.domain.dto; + +import lombok.Data; + +@Data +public class SysUserData { + private int userId; + private String userCode; + private String userName; + private String nickName; + private int deptId; + private String deptName; + private String email; + private String phonenumber; + private String sex; + private String avatar; + private int status; + private String remark; + private String choiceCode; + private int orderId; + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupMapper.java new file mode 100644 index 0000000..53cf285 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupMapper.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.system.mapper; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysGroup; + +/** + * 人员分组MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-28 + */ +public interface SysGroupMapper +{ + /** + * 查询人员分组 + * + * @param groupId 人员分组ID + * @return 人员分组 + */ + public SysGroup selectSysGroupById(Long groupId); + + /** + * 查询人员分组列表 + * + * @param sysGroup 人员分组 + * @return äººå‘˜åˆ†ç»„é›†åˆ + */ + public List selectSysGroupList(SysGroup sysGroup); + + /** + * 查询人员分组列表 + * + * @param sysGroup 人员分组 + * @return äººå‘˜åˆ†ç»„é›†åˆ + */ + public List selectChoiceSysGroupList(String examCode); + + /** + * 新增人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + public int insertSysGroup(SysGroup sysGroup); + + /** + * 修改人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + public int updateSysGroup(SysGroup sysGroup); + + /** + * 删除人员分组 + * + * @param groupId 人员分组ID + * @return 结果 + */ + public int deleteSysGroupById(Long groupId); + + /** + * 批é‡åˆ é™¤äººå‘˜åˆ†ç»„ + * + * @param groupIds 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteSysGroupByIds(Long[] groupIds); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupPersonMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupPersonMapper.java new file mode 100644 index 0000000..248473a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysGroupPersonMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.system.mapper; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysGroupPerson; + +/** + * 分组用户MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-06 + */ +public interface SysGroupPersonMapper +{ + /** + * 查询分组用户 + * + * @param groupCode 分组用户ID + * @return 分组用户 + */ + public SysGroupPerson selectSysGroupPersonById(String groupCode); + + /** + * 查询分组用户列表 + * + * @param sysGroupPerson 分组用户 + * @return åˆ†ç»„ç”¨æˆ·é›†åˆ + */ + public List selectSysGroupPersonList(SysGroupPerson sysGroupPerson); + + /** + * 新增分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + public int insertSysGroupPerson(SysGroupPerson sysGroupPerson); + + /** + * 修改分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + public int updateSysGroupPerson(SysGroupPerson sysGroupPerson); + + /** + * 删除分组用户 + * + * @param groupCode 分组用户ID + * @return 结果 + */ + public int deleteSysGroupPersonById(String groupCode); + + /** + * 批é‡åˆ é™¤åˆ†ç»„用户 + * + * @param groupCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteSysGroupPersonByIds(String[] groupCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserChoiceMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserChoiceMapper.java new file mode 100644 index 0000000..a4c4650 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserChoiceMapper.java @@ -0,0 +1,75 @@ +package com.yanzhu.exam.system.mapper; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysUserChoice; +import com.yanzhu.exam.system.domain.dto.SysUserCopy; +import com.yanzhu.exam.system.domain.dto.SysUserData; + +/** + * 选择用户MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-02 + */ +public interface SysUserChoiceMapper +{ + /** + * 查询选择用户 + * + * @param choiceCode 选择用户ID + * @return 选择用户 + */ + public SysUserChoice selectSysUserChoiceById(String choiceCode); + + /** + * 查询选择用户列表 + * + * @param sysUserChoice 选择用户 + * @return é€‰æ‹©ç”¨æˆ·é›†åˆ + */ + public List selectSysUserChoiceList(SysUserChoice sysUserChoice); + + /** + * 查询选择用户列表 + * + * @param sysUserChoice 选择用户 + * @return é€‰æ‹©ç”¨æˆ·é›†åˆ + */ + public List selectGroupUserList(SysUserData sysUser); + + + public int copySysUser(SysUserCopy sysUserCopy); + + public int copyTempUser(SysUserCopy sysUserCopy); + /** + * 新增选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + public int insertSysUserChoice(SysUserChoice sysUserChoice); + + /** + * 修改选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + public int updateSysUserChoice(SysUserChoice sysUserChoice); + + /** + * 删除选择用户 + * + * @param choiceCode 选择用户ID + * @return 结果 + */ + public int deleteSysUserChoiceById(String choiceCode); + + /** + * 批é‡åˆ é™¤é€‰æ‹©ç”¨æˆ· + * + * @param choiceCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ + public int deleteSysUserChoiceByIds(String[] choiceCodes); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserDataMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserDataMapper.java new file mode 100644 index 0000000..50bae26 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/SysUserDataMapper.java @@ -0,0 +1,12 @@ +package com.yanzhu.exam.system.mapper; + +import java.util.List; + +import com.yanzhu.exam.system.domain.dto.SysUserData; + +public interface SysUserDataMapper { + public List selectUserList(SysUserData sysUser); + + public List selectChoiceUserList(SysUserData sysUser); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/TempUserChoiceMapper.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/TempUserChoiceMapper.java new file mode 100644 index 0000000..ee4e4f4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/mapper/TempUserChoiceMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.system.mapper; + +import java.util.List; +import com.yanzhu.exam.system.domain.TempUserChoice; + +/** + * 用户选择MapperæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-31 + */ +public interface TempUserChoiceMapper +{ + /** + * 查询用户选择 + * + * @param choiceCode 用户选择ID + * @return 用户选择 + */ + public TempUserChoice selectTempUserChoiceById(String choiceCode); + + /** + * 查询用户选择列表 + * + * @param tempUserChoice 用户选择 + * @return ç”¨æˆ·é€‰æ‹©é›†åˆ + */ + public List selectTempUserChoiceList(TempUserChoice tempUserChoice); + + /** + * 新增用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + public int insertTempUserChoice(TempUserChoice tempUserChoice); + + /** + * 修改用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + public int updateTempUserChoice(TempUserChoice tempUserChoice); + + /** + * 删除用户选择 + * + * @param choiceCode 用户选择ID + * @return 结果 + */ + + public int deleteTempUserChoice(TempUserChoice tempUserChoice); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·é€‰æ‹© + * + * @param choiceCodes 需è¦åˆ é™¤çš„æ•°æ®ID + * @return 结果 + */ +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupPersonService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupPersonService.java new file mode 100644 index 0000000..5385f76 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupPersonService.java @@ -0,0 +1,61 @@ +package com.yanzhu.exam.system.service; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysGroupPerson; + +/** + * 分组用户ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-06 + */ +public interface ISysGroupPersonService +{ + /** + * 查询分组用户 + * + * @param groupCode 分组用户ID + * @return 分组用户 + */ + public SysGroupPerson selectSysGroupPersonById(String groupCode); + + /** + * 查询分组用户列表 + * + * @param sysGroupPerson 分组用户 + * @return åˆ†ç»„ç”¨æˆ·é›†åˆ + */ + public List selectSysGroupPersonList(SysGroupPerson sysGroupPerson); + + /** + * 新增分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + public int insertSysGroupPerson(List sysGroupPersonList); + + /** + * 修改分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + public int updateSysGroupPerson(SysGroupPerson sysGroupPerson); + + /** + * 批é‡åˆ é™¤åˆ†ç»„用户 + * + * @param groupCodes 需è¦åˆ é™¤çš„分组用户ID + * @return 结果 + */ + public int deleteSysGroupPersonByIds(String[] groupCodes); + + /** + * åˆ é™¤åˆ†ç»„ç”¨æˆ·ä¿¡æ¯ + * + * @param groupCode 分组用户ID + * @return 结果 + */ + public int deleteSysGroupPersonById(String groupCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupService.java new file mode 100644 index 0000000..ee42d7b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysGroupService.java @@ -0,0 +1,69 @@ +package com.yanzhu.exam.system.service; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysGroup; + +/** + * 人员分组ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-28 + */ +public interface ISysGroupService +{ + /** + * 查询人员分组 + * + * @param groupId 人员分组ID + * @return 人员分组 + */ + public SysGroup selectSysGroupById(Long groupId); + + /** + * 查询人员分组列表 + * + * @param sysGroup 人员分组 + * @return äººå‘˜åˆ†ç»„é›†åˆ + */ + public List selectSysGroupList(SysGroup sysGroup); + + /** + * 查询人员分组列表 + * + * @param sysGroup 人员分组 + * @return äººå‘˜åˆ†ç»„é›†åˆ + */ + public List selectChoiceSysGroupList(String examCode); + + /** + * 新增人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + public int insertSysGroup(SysGroup sysGroup); + + /** + * 修改人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + public int updateSysGroup(SysGroup sysGroup); + + /** + * 批é‡åˆ é™¤äººå‘˜åˆ†ç»„ + * + * @param groupIds 需è¦åˆ é™¤çš„人员分组ID + * @return 结果 + */ + public int deleteSysGroupByIds(Long[] groupIds); + + /** + * åˆ é™¤äººå‘˜åˆ†ç»„ä¿¡æ¯ + * + * @param groupId 人员分组ID + * @return 结果 + */ + public int deleteSysGroupById(Long groupId); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserChoiceService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserChoiceService.java new file mode 100644 index 0000000..e6bf2b7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserChoiceService.java @@ -0,0 +1,75 @@ +package com.yanzhu.exam.system.service; + +import java.util.List; +import com.yanzhu.exam.system.domain.SysUserChoice; +import com.yanzhu.exam.system.domain.dto.SysUserCopy; +import com.yanzhu.exam.system.domain.dto.SysUserData; + +/** + * 选择用户ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-02-02 + */ +public interface ISysUserChoiceService +{ + /** + * 查询选择用户 + * + * @param choiceCode 选择用户ID + * @return 选择用户 + */ + public SysUserChoice selectSysUserChoiceById(String choiceCode); + + /** + * 查询选择用户列表 + * + * @param sysUserChoice 选择用户 + * @return é€‰æ‹©ç”¨æˆ·é›†åˆ + */ + public List selectSysUserChoiceList(SysUserChoice sysUserChoice); + + /** + * 查询选择用户列表 + * + * @param sysUserChoice 选择用户 + * @return é€‰æ‹©ç”¨æˆ·é›†åˆ + */ + public List selectGroupUserList(SysUserData sysUser); + + /** + * 新增选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + public int insertSysUserChoice(SysUserChoice sysUserChoice); + + public int copySysUser(SysUserCopy sysUserCopy); + + public int copyTempUser(SysUserCopy sysUserCopy); + + /** + * 修改选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + public int updateSysUserChoice(SysUserChoice sysUserChoice); + + /** + * 批é‡åˆ é™¤é€‰æ‹©ç”¨æˆ· + * + * @param choiceCodes 需è¦åˆ é™¤çš„选择用户ID + * @return 结果 + */ + public int deleteSysUserChoiceByIds(String[] choiceCodes); + + /** + * åˆ é™¤é€‰æ‹©ç”¨æˆ·ä¿¡æ¯ + * + * @param choiceCode 选择用户ID + * @return 结果 + */ + public int deleteSysUserChoiceById(String choiceCode); +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserDataService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserDataService.java new file mode 100644 index 0000000..99cb19b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ISysUserDataService.java @@ -0,0 +1,13 @@ +package com.yanzhu.exam.system.service; + +import java.util.List; + +import com.yanzhu.exam.system.domain.dto.SysUserData; + +public interface ISysUserDataService { + public List selectUserList(SysUserData sysUser); + + public List selectChoiceUserList(SysUserData sysUser); + + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ITempUserChoiceService.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ITempUserChoiceService.java new file mode 100644 index 0000000..5cf4fa1 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/ITempUserChoiceService.java @@ -0,0 +1,56 @@ +package com.yanzhu.exam.system.service; + +import java.util.List; +import com.yanzhu.exam.system.domain.TempUserChoice; + +/** + * 用户选择ServiceæŽ¥å£ + * + * @author qnsdt + * @date 2023-01-31 + */ +public interface ITempUserChoiceService +{ + /** + * 查询用户选择 + * + * @param choiceCode 用户选择ID + * @return 用户选择 + */ + public TempUserChoice selectTempUserChoiceById(String choiceCode); + + /** + * 查询用户选择列表 + * + * @param tempUserChoice 用户选择 + * @return ç”¨æˆ·é€‰æ‹©é›†åˆ + */ + public List selectTempUserChoiceList(TempUserChoice tempUserChoice); + + /** + * 新增用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + public int insertTempUserChoice(TempUserChoice tempUserChoice); + + public int batchInsertTempUser(List userList); + + /** + * 修改用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + public int updateTempUserChoice(TempUserChoice tempUserChoice); + + /** + * 批é‡åˆ é™¤ç”¨æˆ·é€‰æ‹© + * + * @param choiceCodes 需è¦åˆ é™¤çš„用户选择ID + * @return 结果 + */ + public int deleteTempUserChoice(List userList); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupPersonServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupPersonServiceImpl.java new file mode 100644 index 0000000..08bab41 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupPersonServiceImpl.java @@ -0,0 +1,100 @@ +package com.yanzhu.exam.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.system.mapper.SysGroupPersonMapper; +import com.yanzhu.exam.system.domain.SysGroupPerson; +import com.yanzhu.exam.system.service.ISysGroupPersonService; + +/** + * 分组用户Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-06 + */ +@Service +public class SysGroupPersonServiceImpl implements ISysGroupPersonService +{ + @Autowired + private SysGroupPersonMapper sysGroupPersonMapper; + + /** + * 查询分组用户 + * + * @param groupCode 分组用户ID + * @return 分组用户 + */ + @Override + public SysGroupPerson selectSysGroupPersonById(String groupCode) + { + return sysGroupPersonMapper.selectSysGroupPersonById(groupCode); + } + + /** + * 查询分组用户列表 + * + * @param sysGroupPerson 分组用户 + * @return 分组用户 + */ + @Override + public List selectSysGroupPersonList(SysGroupPerson sysGroupPerson) + { + return sysGroupPersonMapper.selectSysGroupPersonList(sysGroupPerson); + } + + /** + * 新增分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + @Override + public int insertSysGroupPerson(List sysGroupPersonList) + { + sysGroupPersonMapper.deleteSysGroupPersonById(sysGroupPersonList.get(0).getGroupCode()); + int count = 0; + + for (SysGroupPerson sysGroupPerson: sysGroupPersonList) { + count += sysGroupPersonMapper.insertSysGroupPerson(sysGroupPerson); + } + + return count; + } + + /** + * 修改分组用户 + * + * @param sysGroupPerson 分组用户 + * @return 结果 + */ + @Override + public int updateSysGroupPerson(SysGroupPerson sysGroupPerson) + { + return sysGroupPersonMapper.updateSysGroupPerson(sysGroupPerson); + } + + /** + * 批é‡åˆ é™¤åˆ†ç»„用户 + * + * @param groupCodes 需è¦åˆ é™¤çš„分组用户ID + * @return 结果 + */ + @Override + public int deleteSysGroupPersonByIds(String[] groupCodes) + { + return sysGroupPersonMapper.deleteSysGroupPersonByIds(groupCodes); + } + + /** + * åˆ é™¤åˆ†ç»„ç”¨æˆ·ä¿¡æ¯ + * + * @param groupCode 分组用户ID + * @return 结果 + */ + @Override + public int deleteSysGroupPersonById(String groupCode) + { + return sysGroupPersonMapper.deleteSysGroupPersonById(groupCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupServiceImpl.java new file mode 100644 index 0000000..9b5e5fc --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysGroupServiceImpl.java @@ -0,0 +1,101 @@ +package com.yanzhu.exam.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.system.mapper.SysGroupMapper; +import com.yanzhu.exam.system.domain.SysGroup; +import com.yanzhu.exam.system.service.ISysGroupService; + +/** + * 人员分组Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-01-28 + */ +@Service +public class SysGroupServiceImpl implements ISysGroupService +{ + @Autowired + private SysGroupMapper sysGroupMapper; + + /** + * 查询人员分组 + * + * @param groupId 人员分组ID + * @return 人员分组 + */ + @Override + public SysGroup selectSysGroupById(Long groupId) + { + return sysGroupMapper.selectSysGroupById(groupId); + } + + /** + * 查询人员分组列表 + * + * @param sysGroup 人员分组 + * @return 人员分组 + */ + @Override + public List selectSysGroupList(SysGroup sysGroup) + { + return sysGroupMapper.selectSysGroupList(sysGroup); + } + + /** + * 新增人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + @Override + public int insertSysGroup(SysGroup sysGroup) + { + sysGroup.setCreateTime(DateUtils.getNowDate()); + return sysGroupMapper.insertSysGroup(sysGroup); + } + + /** + * 修改人员分组 + * + * @param sysGroup 人员分组 + * @return 结果 + */ + @Override + public int updateSysGroup(SysGroup sysGroup) + { + return sysGroupMapper.updateSysGroup(sysGroup); + } + + /** + * 批é‡åˆ é™¤äººå‘˜åˆ†ç»„ + * + * @param groupIds 需è¦åˆ é™¤çš„人员分组ID + * @return 结果 + */ + @Override + public int deleteSysGroupByIds(Long[] groupIds) + { + return sysGroupMapper.deleteSysGroupByIds(groupIds); + } + + /** + * åˆ é™¤äººå‘˜åˆ†ç»„ä¿¡æ¯ + * + * @param groupId 人员分组ID + * @return 结果 + */ + @Override + public int deleteSysGroupById(Long groupId) + { + return sysGroupMapper.deleteSysGroupById(groupId); + } + + @Override + public List selectChoiceSysGroupList(String examCode) { + // TODO Auto-generated method stub + return sysGroupMapper.selectChoiceSysGroupList(examCode); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserChoiceServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserChoiceServiceImpl.java new file mode 100644 index 0000000..3b62b93 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserChoiceServiceImpl.java @@ -0,0 +1,113 @@ +package com.yanzhu.exam.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.system.mapper.SysUserChoiceMapper; +import com.yanzhu.exam.system.domain.SysUserChoice; +import com.yanzhu.exam.system.domain.dto.SysUserCopy; +import com.yanzhu.exam.system.domain.dto.SysUserData; +import com.yanzhu.exam.system.service.ISysUserChoiceService; + +/** + * 选择用户Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-02-02 + */ +@Service +public class SysUserChoiceServiceImpl implements ISysUserChoiceService +{ + @Autowired + private SysUserChoiceMapper sysUserChoiceMapper; + + /** + * 查询选择用户 + * + * @param choiceCode 选择用户ID + * @return 选择用户 + */ + @Override + public SysUserChoice selectSysUserChoiceById(String choiceCode) + { + return sysUserChoiceMapper.selectSysUserChoiceById(choiceCode); + } + + /** + * 查询选择用户列表 + * + * @param sysUserChoice 选择用户 + * @return 选择用户 + */ + @Override + public List selectSysUserChoiceList(SysUserChoice sysUserChoice) + { + return sysUserChoiceMapper.selectSysUserChoiceList(sysUserChoice); + } + + /** + * 新增选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + @Override + public int insertSysUserChoice(SysUserChoice sysUserChoice) + { + return sysUserChoiceMapper.insertSysUserChoice(sysUserChoice); + } + + /** + * 修改选择用户 + * + * @param sysUserChoice 选择用户 + * @return 结果 + */ + @Override + public int updateSysUserChoice(SysUserChoice sysUserChoice) + { + return sysUserChoiceMapper.updateSysUserChoice(sysUserChoice); + } + + /** + * 批é‡åˆ é™¤é€‰æ‹©ç”¨æˆ· + * + * @param choiceCodes 需è¦åˆ é™¤çš„选择用户ID + * @return 结果 + */ + @Override + public int deleteSysUserChoiceByIds(String[] choiceCodes) + { + return sysUserChoiceMapper.deleteSysUserChoiceByIds(choiceCodes); + } + + /** + * åˆ é™¤é€‰æ‹©ç”¨æˆ·ä¿¡æ¯ + * + * @param choiceCode 选择用户ID + * @return 结果 + */ + @Override + public int deleteSysUserChoiceById(String choiceCode) + { + return sysUserChoiceMapper.deleteSysUserChoiceById(choiceCode); + } + + @Override + public int copySysUser(SysUserCopy sysUserCopy) { + // TODO Auto-generated method stub + return sysUserChoiceMapper.copySysUser(sysUserCopy); + } + + @Override + public int copyTempUser(SysUserCopy sysUserCopy) { + // TODO Auto-generated method stub + return sysUserChoiceMapper.copyTempUser(sysUserCopy); + } + + @Override + public List selectGroupUserList(SysUserData sysUser) { + // TODO Auto-generated method stub + return sysUserChoiceMapper.selectGroupUserList(sysUser); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserDataServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserDataServiceImpl.java new file mode 100644 index 0000000..909800b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/SysUserDataServiceImpl.java @@ -0,0 +1,29 @@ +package com.yanzhu.exam.system.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.yanzhu.exam.system.domain.dto.SysUserData; +import com.yanzhu.exam.system.mapper.SysUserDataMapper; +import com.yanzhu.exam.system.service.ISysUserDataService; + +@Service +public class SysUserDataServiceImpl implements ISysUserDataService { + @Autowired + SysUserDataMapper sysUserDataMapper; + + @Override + public List selectUserList(SysUserData sysUser) { + // TODO Auto-generated method stub + return sysUserDataMapper.selectUserList(sysUser); + } + + @Override + public List selectChoiceUserList(SysUserData sysUser) { + // TODO Auto-generated method stub + return sysUserDataMapper.selectChoiceUserList(sysUser); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/TempUserChoiceServiceImpl.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/TempUserChoiceServiceImpl.java new file mode 100644 index 0000000..cdfa62a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/system/service/impl/TempUserChoiceServiceImpl.java @@ -0,0 +1,90 @@ +package com.yanzhu.exam.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.exam.system.mapper.TempUserChoiceMapper; +import com.yanzhu.exam.system.domain.TempUserChoice; +import com.yanzhu.exam.system.service.ITempUserChoiceService; + +/** + * 用户选择Serviceä¸šåŠ¡å±‚å¤„ç† + * + * @author qnsdt + * @date 2023-01-31 + */ +@Service +public class TempUserChoiceServiceImpl implements ITempUserChoiceService +{ + @Autowired + private TempUserChoiceMapper tempUserChoiceMapper; + + /** + * 查询用户选择 + * + * @param choiceCode 用户选择ID + * @return 用户选择 + */ + @Override + public TempUserChoice selectTempUserChoiceById(String choiceCode) + { + return tempUserChoiceMapper.selectTempUserChoiceById(choiceCode); + } + + /** + * 查询用户选择列表 + * + * @param tempUserChoice 用户选择 + * @return 用户选择 + */ + @Override + public List selectTempUserChoiceList(TempUserChoice tempUserChoice) + { + return tempUserChoiceMapper.selectTempUserChoiceList(tempUserChoice); + } + + /** + * 新增用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + @Override + public int insertTempUserChoice(TempUserChoice tempUserChoice) + { + return tempUserChoiceMapper.insertTempUserChoice(tempUserChoice); + } + + /** + * 修改用户选择 + * + * @param tempUserChoice 用户选择 + * @return 结果 + */ + @Override + public int updateTempUserChoice(TempUserChoice tempUserChoice) + { + return tempUserChoiceMapper.updateTempUserChoice(tempUserChoice); + } + + @Override + public int deleteTempUserChoice(List userList) { + // TODO Auto-generated method stub + int count = 0; + for(TempUserChoice tempUser: userList) { + count += tempUserChoiceMapper.deleteTempUserChoice(tempUser); + } + return count; + } + + @Override + public int batchInsertTempUser(List userList) { + // TODO Auto-generated method stub + int count = 0; + for(TempUserChoice tempUser: userList) { + count += tempUserChoiceMapper.insertTempUserChoice(tempUser); + } + return count; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ActionEnter.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ActionEnter.java new file mode 100644 index 0000000..0e7c332 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ActionEnter.java @@ -0,0 +1,127 @@ +package com.yanzhu.exam.ueditor; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.yanzhu.exam.ueditor.define.ActionMap; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.State; +import com.yanzhu.exam.ueditor.hunter.FileManager; +import com.yanzhu.exam.ueditor.hunter.ImageHunter; +import com.yanzhu.exam.ueditor.upload.Uploader; + +public class ActionEnter { + + private HttpServletRequest request = null; + + private String rootPath = null; + private String contextPath = null; + + private String actionType = null; + + private ConfigManager configManager = null; + + public ActionEnter ( HttpServletRequest request, String rootPath ) { + + this.request = request; + this.rootPath = rootPath; + this.actionType = request.getParameter( "action" ); + this.contextPath = request.getContextPath(); + this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() ); + + } + + public String exec () { + + String callbackName = this.request.getParameter("callback"); + + if ( callbackName != null ) { + + if ( !validCallbackName( callbackName ) ) { + return new BaseState( false, AppInfo.ILLEGAL ).toJSONString(); + } + + return callbackName+"("+this.invoke()+");"; + + } else { + return this.invoke(); + } + + } + + public String invoke() { + + if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) { + return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString(); + } + + if ( this.configManager == null || !this.configManager.valid() ) { + return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString(); + } + + State state = null; + + int actionCode = ActionMap.getType( this.actionType ); + + Map conf = null; + + switch ( actionCode ) { + + case ActionMap.CONFIG: + return this.configManager.getAllConfig().toString(); + + case ActionMap.UPLOAD_IMAGE: + case ActionMap.UPLOAD_SCRAWL: + case ActionMap.UPLOAD_VIDEO: + case ActionMap.UPLOAD_FILE: + conf = this.configManager.getConfig( actionCode ); + state = new Uploader( request, conf ).doExec(); + break; + + case ActionMap.CATCH_IMAGE: + conf = configManager.getConfig( actionCode ); + String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) ); + state = new ImageHunter( conf ).capture( list ); + break; + + case ActionMap.LIST_IMAGE: + case ActionMap.LIST_FILE: + conf = configManager.getConfig( actionCode ); + int start = this.getStartIndex(); + state = new FileManager( conf ).listFile( start ); + break; + + } + + return state.toJSONString(); + + } + + public int getStartIndex () { + + String start = this.request.getParameter( "start" ); + + try { + return Integer.parseInt( start ); + } catch ( Exception e ) { + return 0; + } + + } + + /** + * callback傿•°éªŒè¯ + */ + public boolean validCallbackName ( String name ) { + + if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) { + return true; + } + + return false; + + } + +} \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ConfigManager.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ConfigManager.java new file mode 100644 index 0000000..61843ec --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/ConfigManager.java @@ -0,0 +1,233 @@ +package com.yanzhu.exam.ueditor; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.yanzhu.exam.ueditor.define.ActionMap; + +/** + * é…置管ç†å™¨ + * @author hancong03@baidu.com + * + */ +public final class ConfigManager { + + private final String rootPath; + private final String originalPath; + private final String contextPath; + private static final String configFileName = "config.json"; + private String parentPath = null; + private JSONObject jsonConfig = null; + // 涂鸦上传filename定义 + private final static String SCRAWL_FILE_NAME = "scrawl"; + // 远程图片抓å–filename定义 + private final static String REMOTE_FILE_NAME = "remote"; + + /* + * 通过一个给定的路径构建一个é…置管ç†å™¨ï¼Œ 该管ç†å™¨è¦æ±‚地å€è·¯å¾„所在目录下必须存在config.properties文件 + */ + private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException { + + rootPath = rootPath.replace( "\\", "/" ); + + this.rootPath = rootPath; + this.contextPath = contextPath; + + if ( contextPath.length() > 0 ) { + this.originalPath = this.rootPath + uri.substring( contextPath.length() ); + } else { + this.originalPath = this.rootPath + uri; + } + + this.initEnv(); + + } + + /** + * é…置管ç†å™¨æž„造工厂 + * @param rootPath æœåŠ¡å™¨æ ¹è·¯å¾„ + * @param contextPath æœåŠ¡å™¨æ‰€åœ¨é¡¹ç›®è·¯å¾„ + * @param uri 当å‰è®¿é—®çš„uri + * @return é…置管ç†å™¨å®žä¾‹æˆ–者null + */ + public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) { + + try { + return new ConfigManager(rootPath, contextPath, uri); + } catch ( Exception e ) { + return null; + } + + } + + // 验è¯é…ç½®æ–‡ä»¶åŠ è½½æ˜¯å¦æ­£ç¡® + public boolean valid () { + return this.jsonConfig != null; + } + + public JSONObject getAllConfig () { + + return this.jsonConfig; + + } + + public Map getConfig ( int type ) { + + Map conf = new HashMap(); + String savePath = null; + + switch ( type ) { + + case ActionMap.UPLOAD_FILE: + conf.put( "isBase64", "false" ); + conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) ); + savePath = this.jsonConfig.getString( "filePathFormat" ); + break; + + case ActionMap.UPLOAD_IMAGE: + conf.put( "isBase64", "false" ); + conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) ); + conf.put("basePath", this.jsonConfig.getString( "basePath" ) ); + savePath = this.jsonConfig.getString( "imagePathFormat" ); + break; + + case ActionMap.UPLOAD_VIDEO: + conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) ); + conf.put("basePath", this.jsonConfig.getString( "basePath" ) ); + savePath = this.jsonConfig.getString( "videoPathFormat" ); + break; + + case ActionMap.UPLOAD_SCRAWL: + conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME ); + conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) ); + conf.put( "isBase64", "true" ); + savePath = this.jsonConfig.getString( "scrawlPathFormat" ); + break; + + case ActionMap.CATCH_IMAGE: + conf.put( "filename", ConfigManager.REMOTE_FILE_NAME ); + conf.put( "filter", this.getArray( "catcherLocalDomain" ) ); + conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) ); + conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) ); + conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" ); + savePath = this.jsonConfig.getString( "catcherPathFormat" ); + break; + + case ActionMap.LIST_IMAGE: + conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) ); + conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) ); + conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) ); + break; + + case ActionMap.LIST_FILE: + conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) ); + conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) ); + conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) ); + break; + + } + + conf.put( "savePath", savePath ); + conf.put( "rootPath", this.rootPath ); + + return conf; + + } + + private void initEnv () throws FileNotFoundException, IOException { + + File file = new File( this.originalPath ); + + if ( !file.isAbsolute() ) { + file = new File( file.getAbsolutePath() ); + } + + this.parentPath = file.getParent(); + + String configContent = this.readFile( this.getConfigPath() ); + + try{ + JSONObject jsonConfig = new JSONObject( configContent ); + this.jsonConfig = jsonConfig; + } catch ( Exception e ) { + this.jsonConfig = null; + } + + } + + private String getConfigPath () { +// return this.parentPath + File.separator + ConfigManager.configFileName; + // 修改æºç  + try{ + return this.getClass().getClassLoader().getResource("config.json").toURI().getPath(); + } catch (URISyntaxException e) { + e.printStackTrace(); + return null; + } + } + + + private String[] getArray ( String key ) { + + JSONArray jsonArray = this.jsonConfig.getJSONArray( key ); + String[] result = new String[ jsonArray.length() ]; + + for ( int i = 0, len = jsonArray.length(); i < len; i++ ) { + result[i] = jsonArray.getString( i ); + } + + return result; + + } + + private String readFile ( String path ) throws IOException { + + StringBuilder builder = new StringBuilder(); + + try { + + InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" ); + BufferedReader bfReader = new BufferedReader( reader ); + + String tmpContent = null; + + while ( ( tmpContent = bfReader.readLine() ) != null ) { + builder.append( tmpContent ); + } + + bfReader.close(); + + } catch ( UnsupportedEncodingException e ) { + // 忽略 + } + + return this.filter( builder.toString() ); + + } + + // 过滤输入字符串, å‰”é™¤å¤šè¡Œæ³¨é‡Šä»¥åŠæ›¿æ¢æŽ‰åæ–œæ  + private String filter ( String input ) { + + return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" ); + + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/Encoder.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/Encoder.java new file mode 100644 index 0000000..f2f7520 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/Encoder.java @@ -0,0 +1,24 @@ +package com.yanzhu.exam.ueditor; + +public class Encoder { + + public static String toUnicode ( String input ) { + + StringBuilder builder = new StringBuilder(); + char[] chars = input.toCharArray(); + + for ( char ch : chars ) { + + if ( ch < 256 ) { + builder.append( ch ); + } else { + builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) ); + } + + } + + return builder.toString(); + + } + +} \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/PathFormat.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/PathFormat.java new file mode 100644 index 0000000..35218c7 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/PathFormat.java @@ -0,0 +1,157 @@ +package com.yanzhu.exam.ueditor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathFormat { + + private static final String TIME = "time"; + private static final String FULL_YEAR = "yyyy"; + private static final String YEAR = "yy"; + private static final String MONTH = "mm"; + private static final String DAY = "dd"; + private static final String HOUR = "hh"; + private static final String MINUTE = "ii"; + private static final String SECOND = "ss"; + private static final String RAND = "rand"; + + private static Date currentDate = null; + + public static String parse ( String input ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) ); + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + /** + * æ ¼å¼åŒ–路径, 把windowsè·¯å¾„æ›¿æ¢æˆæ ‡å‡†è·¯å¾„ + * @param input å¾…æ ¼å¼åŒ–的路径 + * @return æ ¼å¼åŒ–åŽçš„路径 + */ + public static String format ( String input ) { + + return input.replace( "\\", "/" ); + + } + + public static String parse ( String input, String filename ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + String matchStr = null; + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matchStr = matcher.group( 1 ); + if ( matchStr.indexOf( "filename" ) != -1 ) { + filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" ); + matcher.appendReplacement(sb, filename ); + } else { + matcher.appendReplacement(sb, PathFormat.getString( matchStr ) ); + } + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + private static String getString ( String pattern ) { + + pattern = pattern.toLowerCase(); + + // time å¤„ç† + if ( pattern.indexOf( PathFormat.TIME ) != -1 ) { + return PathFormat.getTimestamp(); + } else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) { + return PathFormat.getFullYear(); + } else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) { + return PathFormat.getYear(); + } else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) { + return PathFormat.getMonth(); + } else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) { + return PathFormat.getDay(); + } else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) { + return PathFormat.getHour(); + } else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) { + return PathFormat.getMinute(); + } else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) { + return PathFormat.getSecond(); + } else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) { + return PathFormat.getRandom( pattern ); + } + + return pattern; + + } + + private static String getTimestamp () { + return System.currentTimeMillis() + ""; + } + + private static String getFullYear () { + return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate ); + } + + private static String getYear () { + return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate ); + } + + private static String getMonth () { + return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate ); + } + + private static String getDay () { + return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate ); + } + + private static String getHour () { + return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate ); + } + + private static String getMinute () { + return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate ); + } + + private static String getSecond () { + return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate ); + } + + private static String getRandom ( String pattern ) { + + int length = 0; + pattern = pattern.split( ":" )[ 1 ].trim(); + + length = Integer.parseInt( pattern ); + + return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length ); + + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorFile.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorFile.java new file mode 100644 index 0000000..1750647 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorFile.java @@ -0,0 +1,32 @@ +package com.yanzhu.exam.ueditor.common; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class UEditorFile { + + private static final long serialVersionUID=1L; + + private String state; + + private String url; + + private String title; + + private String original; + + @Override + public String toString() { + return "{" + + "state='" + state + '\'' + + ", url='" + url + '\'' + + ", title='" + title + '\'' + + ", original='" + original + '\'' + + '}'; + } +} + diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorUpload.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorUpload.java new file mode 100644 index 0000000..fd15a76 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/common/UEditorUpload.java @@ -0,0 +1,137 @@ +package com.yanzhu.exam.ueditor.common; + +import com.yanzhu.exam.ueditor.PathFormat; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.FileType; +import com.yanzhu.exam.ueditor.define.State; +import com.yanzhu.exam.ueditor.upload.StorageManager; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +@Component +public class UEditorUpload { + public final State uploadImage(HttpServletRequest request, Map conf) throws IOException { + + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + + try { + + /*========== 添加的内容 ==========*/ + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString()); + if (multipartFile == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + // æ·»åŠ ç»“æŸ + + String savePath = (String) conf.get("savePath"); + String originFileName = multipartFile.getOriginalFilename(); // 修改的 + String suffix = FileType.getSuffixByFilename(originFileName); // æ­¤å¤„å–æ–‡ä»¶æ‰©å±•å + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, ""); + + savePath += suffix; + String physicalPath = (String) conf.get("basePath") + savePath; + InputStream is = multipartFile.getInputStream(); + State storageState = StorageManager.saveFileByInputStream(is, + physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + + return storageState; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + + } + + public final State uploadMovie(HttpServletRequest request, Map conf) throws IOException { + + + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + + try { + + /*========== 添加的内容 ==========*/ + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString()); + if (multipartFile == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + // æ·»åŠ ç»“æŸ + + String savePath = (String) conf.get("savePath"); + String originFileName = multipartFile.getOriginalFilename(); // 修改的 + String suffix = FileType.getSuffixByFilename(originFileName); // æ­¤å¤„å–æ–‡ä»¶æ‰©å±•å + + // è¿™é‡Œé‡æ–°ç”Ÿæˆæ–‡ä»¶å + + originFileName = "movie"; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, ""); + + savePath += suffix; + String physicalPath = (String) conf.get("basePath") + savePath; + InputStream is = multipartFile.getInputStream(); + State storageState = StorageManager.saveFileByInputStream(is, + physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + + return storageState; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/controller/UEditorController.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/controller/UEditorController.java new file mode 100644 index 0000000..aec0d43 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/controller/UEditorController.java @@ -0,0 +1,92 @@ +package com.yanzhu.exam.ueditor.controller; + + +import java.io.FileInputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.stream.FileImageInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.yanzhu.exam.ueditor.ActionEnter; +import com.yanzhu.exam.ueditor.ConfigManager; +import com.yanzhu.exam.ueditor.common.UEditorFile; +import com.yanzhu.exam.ueditor.common.UEditorUpload; +import com.yanzhu.exam.ueditor.define.ActionMap; +import com.yanzhu.exam.ueditor.define.State; + + +@RestController +@RequestMapping("/ueditor") +@CrossOrigin(allowCredentials = "true", originPatterns = "*") +public class UEditorController { + @Autowired + private UEditorUpload uEditorUpload; + + + @RequestMapping("/test") + public String getTest() { + return "ok"; + } + + + @RequestMapping("/config") + public String exec(HttpServletRequest request, + HttpServletResponse response, + @RequestParam(value = "action") String action, + @RequestParam(value = "upfile", required = false) MultipartFile upfile) throws Exception { + if (action.equals("config")) { + request.setCharacterEncoding("utf-8"); + response.setContentType("text/html"); + String rootPath = request.getSession().getServletContext().getRealPath("/"); + return new ActionEnter(request, rootPath).exec(); + } else if (action.equals("uploadimage")) { + request.setCharacterEncoding("utf-8"); + response.setContentType("text/html"); + String rootPath = request.getSession().getServletContext().getRealPath("/"); + String contextPath = request.getContextPath(); + ConfigManager configManager = ConfigManager.getInstance( rootPath, contextPath, request.getRequestURI() ); + Map conf = new HashMap(); + conf = configManager.getConfig(ActionMap.UPLOAD_IMAGE); + + + State uploadState = uEditorUpload.uploadImage(request, conf); + + return uploadState.toJSONString(); + } else if (action.equals("uploadvideo")) { + request.setCharacterEncoding("utf-8"); + response.setContentType("text/html"); + String rootPath = request.getSession().getServletContext().getRealPath("/"); + String contextPath = request.getContextPath(); + ConfigManager configManager = ConfigManager.getInstance( rootPath, contextPath, request.getRequestURI() ); + Map conf = new HashMap(); + conf = configManager.getConfig(ActionMap.UPLOAD_VIDEO); + + + State uploadState = uEditorUpload.uploadMovie(request, conf); + + return uploadState.toJSONString(); + + } else if (action.equals("configmanager")) { + + + return "Done|"; + } + + return "无效Action"; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionMap.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionMap.java new file mode 100644 index 0000000..0c5174a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionMap.java @@ -0,0 +1,42 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.Map; +import java.util.HashMap; + +/** + * 定义请求action类型 + * @author hancong03@baidu.com + * + */ +@SuppressWarnings("serial") +public final class ActionMap { + + public static final Map mapping; + // 获å–é…置请求 + public static final int CONFIG = 0; + public static final int UPLOAD_IMAGE = 1; + public static final int UPLOAD_SCRAWL = 2; + public static final int UPLOAD_VIDEO = 3; + public static final int UPLOAD_FILE = 4; + public static final int CATCH_IMAGE = 5; + public static final int LIST_FILE = 6; + public static final int LIST_IMAGE = 7; + + static { + mapping = new HashMap(){{ + put( "config", ActionMap.CONFIG ); + put( "uploadimage", ActionMap.UPLOAD_IMAGE ); + put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL ); + put( "uploadvideo", ActionMap.UPLOAD_VIDEO ); + put( "uploadfile", ActionMap.UPLOAD_FILE ); + put( "catchimage", ActionMap.CATCH_IMAGE ); + put( "listfile", ActionMap.LIST_FILE ); + put( "listimage", ActionMap.LIST_IMAGE ); + }}; + } + + public static int getType ( String key ) { + return ActionMap.mapping.get( key ); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionState.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionState.java new file mode 100644 index 0000000..763a1b2 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/ActionState.java @@ -0,0 +1,5 @@ +package com.yanzhu.exam.ueditor.define; + +public enum ActionState { + UNKNOW_ERROR +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/AppInfo.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/AppInfo.java new file mode 100644 index 0000000..3253128 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/AppInfo.java @@ -0,0 +1,77 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public final class AppInfo { + + public static final int SUCCESS = 0; + public static final int MAX_SIZE = 1; + public static final int PERMISSION_DENIED = 2; + public static final int FAILED_CREATE_FILE = 3; + public static final int IO_ERROR = 4; + public static final int NOT_MULTIPART_CONTENT = 5; + public static final int PARSE_REQUEST_ERROR = 6; + public static final int NOTFOUND_UPLOAD_DATA = 7; + public static final int NOT_ALLOW_FILE_TYPE = 8; + + public static final int INVALID_ACTION = 101; + public static final int CONFIG_ERROR = 102; + + public static final int PREVENT_HOST = 201; + public static final int CONNECTION_ERROR = 202; + public static final int REMOTE_FAIL = 203; + + public static final int NOT_DIRECTORY = 301; + public static final int NOT_EXIST = 302; + + public static final int ILLEGAL = 401; + + public static Map info = new HashMap(){{ + + put( AppInfo.SUCCESS, "SUCCESS" ); + + // 无效的Action + put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" ); + // é…置文件åˆå§‹åŒ–失败 + put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" ); + // 抓å–远程图片失败 + put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" ); + + // 被阻止的远程主机 + put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" ); + // 远程连接出错 + put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" ); + + // "文件大å°è¶…出é™åˆ¶" + put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" ); + // æƒé™ä¸è¶³ï¼Œ 多指写æƒé™ + put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" ); + // 创建文件失败 + put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" ); + // IO错误 + put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" ); + // 上传表å•䏿˜¯multipart/form-data类型 + put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" ); + // è§£æžä¸Šä¼ è¡¨å•错误 + put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" ); + // æœªæ‰¾åˆ°ä¸Šä¼ æ•°æ® + put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" ); + // ä¸å…许的文件类型 + put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" ); + + // æŒ‡å®šè·¯å¾„ä¸æ˜¯ç›®å½• + put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" ); + // 指定路径并ä¸å­˜åœ¨ + put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" ); + + // callback傿•°åä¸åˆæ³• + put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" ); + + }}; + + public static String getStateInfo ( int key ) { + return AppInfo.info.get( key ); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/BaseState.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/BaseState.java new file mode 100644 index 0000000..81c7789 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/BaseState.java @@ -0,0 +1,92 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.yanzhu.exam.ueditor.Encoder; + +public class BaseState implements State { + + private boolean state = false; + private String info = null; + + private Map infoMap = new HashMap(); + + public BaseState () { + this.state = true; + } + + public BaseState ( boolean state ) { + this.setState( state ); + } + + public BaseState ( boolean state, String info ) { + this.setState( state ); + this.info = info; + } + + public BaseState ( boolean state, int infoCode ) { + this.setState( state ); + this.info = AppInfo.getStateInfo( infoCode ); + } + + public boolean isSuccess () { + return this.state; + } + + public void setState ( boolean state ) { + this.state = state; + } + + public void setInfo ( String info ) { + this.info = info; + } + + public void setInfo ( int infoCode ) { + this.info = AppInfo.getStateInfo( infoCode ); + } + + @Override + public String toJSONString() { + return this.toString(); + } + + public String toString () { + + String key = null; + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + Iterator iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + key = iterator.next(); + + builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" ); + + } + + builder.append( "}" ); + + // return Encoder.toUnicode( builder.toString() ); + + return builder.toString(); + + } + + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public void putInfo(String name, long val) { + this.putInfo(name, val+""); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/FileType.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/FileType.java new file mode 100644 index 0000000..34c8295 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/FileType.java @@ -0,0 +1,31 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class FileType { + + public static final String JPG = "JPG"; + + private static final Map types = new HashMap(){{ + + put( FileType.JPG, ".jpg" ); + + }}; + + public static String getSuffix ( String key ) { + return FileType.types.get( key ); + } + + /** + * æ ¹æ®ç»™å®šçš„æ–‡ä»¶å,获å–å…¶åŽç¼€ä¿¡æ¯ + * @param filename + * @return + */ + public static String getSuffixByFilename ( String filename ) { + + return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase(); + + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MIMEType.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MIMEType.java new file mode 100644 index 0000000..e4ee486 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MIMEType.java @@ -0,0 +1,20 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class MIMEType { + + public static final Map types = new HashMap(){{ + put( "image/gif", ".gif" ); + put( "image/jpeg", ".jpg" ); + put( "image/jpg", ".jpg" ); + put( "image/png", ".png" ); + put( "image/bmp", ".bmp" ); + }}; + + public static String getSuffix ( String mime ) { + return MIMEType.types.get( mime ); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MultiState.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MultiState.java new file mode 100644 index 0000000..db339c8 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/MultiState.java @@ -0,0 +1,112 @@ +package com.yanzhu.exam.ueditor.define; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.yanzhu.exam.ueditor.Encoder; + +/** + * 多状æ€é›†åˆçŠ¶æ€ + * 其包å«äº†å¤šä¸ªçжæ€çš„集åˆ, å…¶æœ¬èº«è‡ªå·±ä¹Ÿæ˜¯ä¸€ä¸ªçŠ¶æ€ + * @author hancong03@baidu.com + * + */ +public class MultiState implements State { + + private boolean state = false; + private String info = null; + private Map intMap = new HashMap(); + private Map infoMap = new HashMap(); + private List stateList = new ArrayList(); + + public MultiState ( boolean state ) { + this.state = state; + } + + public MultiState ( boolean state, String info ) { + this.state = state; + this.info = info; + } + + public MultiState ( boolean state, int infoKey ) { + this.state = state; + this.info = AppInfo.getStateInfo( infoKey ); + } + + @Override + public boolean isSuccess() { + return this.state; + } + + public void addState ( State state ) { + stateList.add( state.toJSONString() ); + } + + /** + * 该方法调用无效果 + */ + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public String toJSONString() { + + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + // æ•°å­—è½¬æ¢ + Iterator iterator = this.intMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) ); + + } + + iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" ); + + } + + builder.append( ", list: [" ); + + + iterator = this.stateList.iterator(); + + while ( iterator.hasNext() ) { + + builder.append( iterator.next() + "," ); + + } + + if ( this.stateList.size() > 0 ) { + builder.deleteCharAt( builder.length() - 1 ); + } + + builder.append( " ]}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, long val) { + this.intMap.put( name, val ); + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/State.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/State.java new file mode 100644 index 0000000..d011ad4 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/define/State.java @@ -0,0 +1,18 @@ +package com.yanzhu.exam.ueditor.define; + +/** + * 处ç†çŠ¶æ€æŽ¥å£ + * @author hancong03@baidu.com + * + */ +public interface State { + + public boolean isSuccess (); + + public void putInfo( String name, String val ); + + public void putInfo ( String name, long val ); + + public String toJSONString (); + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/FileManager.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/FileManager.java new file mode 100644 index 0000000..e0a9483 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/FileManager.java @@ -0,0 +1,112 @@ +package com.yanzhu.exam.ueditor.hunter; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.apache.commons.io.FileUtils; + +import com.yanzhu.exam.ueditor.PathFormat; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.MultiState; +import com.yanzhu.exam.ueditor.define.State; + +public class FileManager { + + private String dir = null; + private String rootPath = null; + private String[] allowFiles = null; + private int count = 0; + + public FileManager ( Map conf ) { + + this.rootPath = (String)conf.get( "rootPath" ); + this.dir = this.rootPath + (String)conf.get( "dir" ); + this.allowFiles = this.getAllowFiles( conf.get("allowFiles") ); + this.count = (Integer)conf.get( "count" ); + + } + + public State listFile ( int index ) { + + File dir = new File( this.dir ); + State state = null; + + if ( !dir.exists() ) { + return new BaseState( false, AppInfo.NOT_EXIST ); + } + + if ( !dir.isDirectory() ) { + return new BaseState( false, AppInfo.NOT_DIRECTORY ); + } + + Collection list = FileUtils.listFiles( dir, this.allowFiles, true ); + + if ( index < 0 || index > list.size() ) { + state = new MultiState( true ); + } else { + Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count ); + state = this.getState( fileList ); + } + + state.putInfo( "start", index ); + state.putInfo( "total", list.size() ); + + return state; + + } + + private State getState ( Object[] files ) { + + MultiState state = new MultiState( true ); + BaseState fileState = null; + + File file = null; + + for ( Object obj : files ) { + if ( obj == null ) { + break; + } + file = (File)obj; + fileState = new BaseState( true ); + fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) ); + state.addState( fileState ); + } + + return state; + + } + + private String getPath ( File file ) { + + String path = file.getAbsolutePath(); + + return path.replace( this.rootPath, "/" ); + + } + + private String[] getAllowFiles ( Object fileExt ) { + + String[] exts = null; + String ext = null; + + if ( fileExt == null ) { + return new String[ 0 ]; + } + + exts = (String[])fileExt; + + for ( int i = 0, len = exts.length; i < len; i++ ) { + + ext = exts[ i ]; + exts[ i ] = ext.replace( ".", "" ); + + } + + return exts; + + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/ImageHunter.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/ImageHunter.java new file mode 100644 index 0000000..049d5cd --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/hunter/ImageHunter.java @@ -0,0 +1,144 @@ +package com.yanzhu.exam.ueditor.hunter; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.yanzhu.exam.ueditor.PathFormat; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.MIMEType; +import com.yanzhu.exam.ueditor.define.MultiState; +import com.yanzhu.exam.ueditor.define.State; +import com.yanzhu.exam.ueditor.upload.StorageManager; + +/** + * 图片抓å–器 + * @author hancong03@baidu.com + * + */ +public class ImageHunter { + + private String filename = null; + private String savePath = null; + private String rootPath = null; + private List allowTypes = null; + private long maxSize = -1; + + private List filters = null; + + public ImageHunter ( Map conf ) { + + this.filename = (String)conf.get( "filename" ); + this.savePath = (String)conf.get( "savePath" ); + this.rootPath = (String)conf.get( "rootPath" ); + this.maxSize = (Long)conf.get( "maxSize" ); + this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) ); + this.filters = Arrays.asList( (String[])conf.get( "filter" ) ); + + } + + public State capture ( String[] list ) { + + MultiState state = new MultiState( true ); + + for ( String source : list ) { + state.addState( captureRemoteData( source ) ); + } + + return state; + + } + + public State captureRemoteData ( String urlStr ) { + + HttpURLConnection connection = null; + URL url = null; + String suffix = null; + + try { + url = new URL( urlStr ); + + if ( !validHost( url.getHost() ) ) { + return new BaseState( false, AppInfo.PREVENT_HOST ); + } + + connection = (HttpURLConnection) url.openConnection(); + + connection.setInstanceFollowRedirects( true ); + connection.setUseCaches( true ); + + if ( !validContentState( connection.getResponseCode() ) ) { + return new BaseState( false, AppInfo.CONNECTION_ERROR ); + } + + suffix = MIMEType.getSuffix( connection.getContentType() ); + + if ( !validFileType( suffix ) ) { + return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE ); + } + + if ( !validFileSize( connection.getContentLength() ) ) { + return new BaseState( false, AppInfo.MAX_SIZE ); + } + + String savePath = this.getPath( this.savePath, this.filename, suffix ); + String physicalPath = this.rootPath + savePath; + + State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath ); + + if ( state.isSuccess() ) { + state.putInfo( "url", PathFormat.format( savePath ) ); + state.putInfo( "source", urlStr ); + } + + return state; + + } catch ( Exception e ) { + return new BaseState( false, AppInfo.REMOTE_FAIL ); + } + + } + + private String getPath ( String savePath, String filename, String suffix ) { + + return PathFormat.parse( savePath + suffix, filename ); + + } + + private boolean validHost ( String hostname ) { + try { + InetAddress ip = InetAddress.getByName(hostname); + + if (ip.isSiteLocalAddress()) { + return false; + } + } catch (UnknownHostException e) { + return false; + } + + return !filters.contains( hostname ); + + } + + private boolean validContentState ( int code ) { + + return HttpURLConnection.HTTP_OK == code; + + } + + private boolean validFileType ( String type ) { + + return this.allowTypes.contains( type ); + + } + + private boolean validFileSize ( int size ) { + return size < this.maxSize; + } + +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Base64Uploader.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Base64Uploader.java new file mode 100644 index 0000000..f6e6c47 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Base64Uploader.java @@ -0,0 +1,52 @@ +package com.yanzhu.exam.ueditor.upload; + +import com.yanzhu.exam.ueditor.PathFormat; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.FileType; +import com.yanzhu.exam.ueditor.define.State; + +import java.util.Map; + +import org.apache.commons.codec.binary.Base64; + +public final class Base64Uploader { + + public static State save(String content, Map conf) { + + byte[] data = decode(content); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validSize(data, maxSize)) { + return new BaseState(false, AppInfo.MAX_SIZE); + } + + String suffix = FileType.getSuffix("JPG"); + + String savePath = PathFormat.parse((String) conf.get("savePath"), + (String) conf.get("filename")); + + savePath = savePath + suffix; + String physicalPath = (String) conf.get("rootPath") + savePath; + + State storageState = StorageManager.saveBinaryFile(data, physicalPath); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", ""); + } + + return storageState; + } + + private static byte[] decode(String content) { + return Base64.decodeBase64(content); + } + + private static boolean validSize(byte[] data, long length) { + return data.length <= length; + } + +} \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/BinaryUploader.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/BinaryUploader.java new file mode 100644 index 0000000..88b16ea --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/BinaryUploader.java @@ -0,0 +1,98 @@ +package com.yanzhu.exam.ueditor.upload; + +import com.yanzhu.exam.ueditor.PathFormat; +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.FileType; +import com.yanzhu.exam.ueditor.define.State; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +public class BinaryUploader { + + public static final State save(HttpServletRequest request, + Map conf) { + FileItemStream fileStream = null; + boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null; + + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + ServletFileUpload upload = new ServletFileUpload( + new DiskFileItemFactory()); + + if ( isAjaxUpload ) { + upload.setHeaderEncoding( "UTF-8" ); + } + + try { + FileItemIterator iterator = upload.getItemIterator(request); + + while (iterator.hasNext()) { + fileStream = iterator.next(); + + if (!fileStream.isFormField()) + break; + fileStream = null; + } + + if (fileStream == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + + String savePath = (String) conf.get("savePath"); + String originFileName = fileStream.getName(); + String suffix = FileType.getSuffixByFilename(originFileName); + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + savePath = savePath + suffix; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, originFileName); + + String physicalPath = (String) conf.get("rootPath") + savePath; + + InputStream is = fileStream.openStream(); + State storageState = StorageManager.saveFileByInputStream(is, + physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + + return storageState; + } catch (FileUploadException e) { + return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR); + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/StorageManager.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/StorageManager.java new file mode 100644 index 0000000..13a8821 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/StorageManager.java @@ -0,0 +1,158 @@ +package com.yanzhu.exam.ueditor.upload; + +import com.yanzhu.exam.ueditor.define.AppInfo; +import com.yanzhu.exam.ueditor.define.BaseState; +import com.yanzhu.exam.ueditor.define.State; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FileUtils; + +public class StorageManager { + public static final int BUFFER_SIZE = 8192; + + public StorageManager() { + } + + public static State saveBinaryFile(byte[] data, String path) { + File file = new File(path); + + State state = valid(file); + + if (!state.isSuccess()) { + return state; + } + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bos.write(data); + bos.flush(); + bos.close(); + } catch (IOException ioe) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true, file.getAbsolutePath()); + state.putInfo( "size", data.length ); + state.putInfo( "title", file.getName() ); + return state; + } + + public static State saveFileByInputStream(InputStream is, String path, + long maxSize) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[ 2048 ]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + if (tmpFile.length() > maxSize) { + tmpFile.delete(); + return new BaseState(false, AppInfo.MAX_SIZE); + } + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + public static State saveFileByInputStream(InputStream is, String path) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[ 2048 ]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static File getTmpFile() { + File tmpDir = FileUtils.getTempDirectory(); + String tmpFileName = (Math.random() * 10000 + "").replace(".", ""); + return new File(tmpDir, tmpFileName); + } + + private static State saveTmpFile(File tmpFile, String path) { + State state = null; + File targetFile = new File(path); + + if (targetFile.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + try { + FileUtils.moveFile(tmpFile, targetFile); + } catch (IOException e) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true); + state.putInfo( "size", targetFile.length() ); + /*System.out.println(targetFile.getName()); + String filename = targetFile.getName().toString(); + System.out.println(filename);*/ + state.putInfo( "title", targetFile.getName()); + + return state; + } + + private static State valid(File file) { + File parentPath = file.getParentFile(); + + if ((!parentPath.exists()) && (!parentPath.mkdirs())) { + return new BaseState(false, AppInfo.FAILED_CREATE_FILE); + } + + if (!parentPath.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + + return new BaseState(true); + } +} diff --git a/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Uploader.java b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Uploader.java new file mode 100644 index 0000000..1ab9c05 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/java/com/yanzhu/exam/ueditor/upload/Uploader.java @@ -0,0 +1,29 @@ +package com.yanzhu.exam.ueditor.upload; + +import com.yanzhu.exam.ueditor.define.State; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +public class Uploader { + private HttpServletRequest request = null; + private Map conf = null; + + public Uploader(HttpServletRequest request, Map conf) { + this.request = request; + this.conf = conf; + } + + public final State doExec() { + String filedName = (String) this.conf.get("fieldName"); + State state = null; + + if ("true".equals(this.conf.get("isBase64"))) { + state = Base64Uploader.save(this.request.getParameter(filedName), + this.conf); + } else { + state = BinaryUploader.save(this.request, this.conf); + } + + return state; + } +} diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskGroupMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskGroupMapper.xml new file mode 100644 index 0000000..7f80169 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskGroupMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + select exam_code, group_code, order_id from exam_task_group + + + + + + + + insert into exam_task_group + + exam_code, + group_code, + + + + #{examCode}, + #{groupCode}, + + + + + update exam_task_group + + group_code = #{groupCode}, + order_id = #{orderId}, + + where exam_code = #{examCode} + + + + delete from exam_task_group where exam_code = #{examCode} + + + + delete from exam_task_group where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskManagerMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskManagerMapper.xml new file mode 100644 index 0000000..b3e3dbd --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskManagerMapper.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + select exam_id, exam_code, exam_name,exam_type,exam_times, exam_describe, build_type, force_done, exam_bank, exam_bank_text, picture_url, start_time, end_time, exam_duration, status, create_by, create_dept, create_time from exam_task_manager + + + + + + + + insert into exam_task_manager + + exam_code, + exam_name, + exam_describe, + build_type, + exam_type, + exam_times, + force_done, + exam_bank, + exam_bank_text, + picture_url, + start_time, + end_time, + exam_duration, + status, + create_by, + create_dept, + create_time, + + + #{examCode}, + #{examName}, + #{examDescribe}, + #{buildType}, + #{examType}, + #{examTimes}, + #{forceDone}, + #{examBank}, + #{examBankText}, + #{pictureUrl}, + #{startTime}, + #{endTime}, + #{examDuration}, + 0, + #{createBy}, + #{createDept}, + now(), + + + + + update exam_task_manager + + exam_name = #{examName}, + exam_describe = #{examDescribe}, + build_type = #{buildType}, + exam_type = #{examType}, + exam_times = #{examTimes}, + force_done = #{forceDone}, + exam_bank = #{examBank}, + exam_bank_text = #{examBankText}, + picture_url = #{pictureUrl}, + start_time = #{startTime}, + end_time = #{endTime}, + exam_duration = #{examDuration}, + status = #{status}, + create_by = #{createBy}, + create_dept = #{createDept}, + create_time = #{createTime}, + + where exam_code = #{examCode} + + + + delete from exam_task_manager where exam_code = #{examCode} + + + + delete from exam_task_manager where exam_code in + + #{examCode} + + + + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPersonMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPersonMapper.xml new file mode 100644 index 0000000..df8c64b --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPersonMapper.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + select exam_code, user_code, task_code, start_time, end_time, status from exam_task_person + + + + + + + + + insert into exam_task_person + + exam_code, + user_code, + task_code, + start_time, + end_time, + status, + + + #{examCode}, + #{userCode}, + #{taskCode}, + #{startTime}, + #{endTime}, + #{status}, + + + + + INSERT INTO exam_task_person (exam_code, task_code, user_code, STATUS) + SELECT + #{examCode} AS exam_code, + UUID() AS task_code, + user_code, + 1 AS STATUS + FROM ( + SELECT DISTINCT person_code AS user_code + FROM sys_group_person + WHERE group_code IN ( + SELECT group_code + FROM exam_task_group + WHERE exam_code = #{examCode} + ) + ) AS subquery + + + + + + + update exam_task_person + + user_code = #{userCode}, + task_code = #{taskCode}, + start_time = #{startTime}, + end_time = #{endTime}, + status = #{status}, + + where exam_code = #{examCode} + + + + update exam_task_person set start_time = now() + where exam_code = #{examCode} and user_code = #{userCode} + + + + update exam_task_person set end_time = now(), status = 0 + where exam_code = #{examCode} and user_code = #{userCode} + + + + delete from exam_task_person where exam_code = #{examCode} + + + + delete from exam_task_person where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPictureMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPictureMapper.xml new file mode 100644 index 0000000..30192bf --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskPictureMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + select photo_id, photo_code, photo_path, photo_url, file_name, original_name, create_by, create_time, status from exam_task_picture + + + + + + + + insert into exam_task_picture + + + photo_path, + photo_code, + photo_url, + file_name, + original_name, + create_by, + create_time, + status, + + + #{photoPath}, + #{photoCode}, + #{photoUrl}, + #{fileName}, + #{originalName}, + #{createBy}, + now(), + 0, + + + + + update exam_task_picture + + photo_id = #{photoId}, + photo_path = #{photoPath}, + photo_url = #{photoUrl}, + file_name = #{fileName}, + original_name = #{originalName}, + create_by = #{createBy}, + create_time = #{createTime}, + status = #{status}, + + where photo_code = #{photoCode} + + + + delete from exam_task_picture where photo_code = #{photoCode} + + + + delete from exam_task_picture where photo_code in + + #{photoCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskQuestionsMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskQuestionsMapper.xml new file mode 100644 index 0000000..91994bc --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/exam/ExamTaskQuestionsMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + select exam_code, questions_code, questions_number from exam_task_questions + + + + + + + + insert into exam_task_questions + + exam_code, + questions_code, + questions_number, + + + #{examCode}, + #{questionsCode}, + #{questionsNumber}, + + + + + update exam_task_questions + + questions_code = #{questionsCode}, + questions_number = #{questionsNumber}, + + where exam_code = #{examCode} + + + + delete from exam_task_questions where exam_code = #{examCode} + + + + delete from exam_task_questions where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsFilesMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsFilesMapper.xml new file mode 100644 index 0000000..7066862 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsFilesMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + select file_id, file_title, file_describe, file_name, file_path, file_url, file_suffix, original_name, upload_name, upload_dept, upload_time, status from fms_files + + + + + + + + insert into fms_files + + file_title, + file_describe, + file_name, + file_path, + file_url, + file_suffix, + original_name, + upload_name, + upload_dept, + upload_time, + status, + + + #{fileTitle}, + #{fileDescribe}, + #{fileName}, + #{filePath}, + #{fileUrl}, + #{fileSuffix}, + #{originalName}, + #{uploadName}, + #{uploadDept}, + now(), + 0, + + + + + update fms_files + + file_title = #{fileTitle}, + file_describe = #{fileDescribe}, + upload_time = now(), + + where file_id = #{fileId} + + + + delete from fms_files where file_id = #{fileId} + + + + delete from fms_files where file_id in + + #{fileId} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsPhotoMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsPhotoMapper.xml new file mode 100644 index 0000000..6a71d1d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/fms/FmsPhotoMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + select photo_id, file_name, photo_path, photo_url, original_name, upload_name, upload_dept, upload_time, status from fms_photo + + + + + + + + insert into fms_photo + + file_name, + photo_path, + photo_url, + original_name, + upload_name, + upload_dept, + upload_time, + status, + + + #{fileName}, + #{photoPath}, + #{photoUrl}, + #{originalName}, + #{uploadName}, + #{uploadDept}, + now(), + 0, + + + + + update fms_photo + + file_name = #{fileName}, + photo_path = #{photoPath}, + photo_url = #{photoUrl}, + original_name = #{originalName}, + upload_name = #{uploadName}, + upload_dept = #{uploadDept}, + upload_time = #{uploadTime}, + status = #{status}, + + where photo_id = #{photoId} + + + + delete from fms_photo where photo_id = #{photoId} + + + + delete from fms_photo where photo_id in + + #{photoId} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamFinishAnswerMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamFinishAnswerMapper.xml new file mode 100644 index 0000000..6e2393a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamFinishAnswerMapper.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + select exam_code, user_code, questions_code, right_answer, exam_score, questions_answer, questions_score from exam_finish_answer + + + + + + + + insert into exam_finish_answer + + exam_code, + user_code, + questions_code, + right_answer, + exam_score, + questions_answer, + questions_score, + + + #{examCode}, + #{userCode}, + #{questionsCode}, + #{rightAnswer}, + #{examScore}, + #{questionsAnswer}, + #{questionsScore}, + + + + + insert into exam_finish_answer + select exam_code,user_code,questions_code,case when right_answer = questions_answer then questions_score else 0 end exam_score,right_answer,questions_answer,questions_score from + ( + select a.exam_code, a.user_code, a.questions_code, REPLACE(b.right_answer, ',', '') as right_answer,a.questions_answer,b.questions_score from exam_task_answer a + left join exam_questions_property b on b.questions_code = a.questions_code + where a.exam_code = #{examCode} and a.userCode = #{userCode} and a.questions_answer is not null + order by a.questions_number + ) + + + + update exam_finish_answer + + exam_code = #{examCode}, + user_code = #{userCode}, + questions_code = #{questionsCode}, + right_answer = #{rightAnswer}, + exam_score = #{examScore}, + questions_answer = #{questionsAnswer}, + questions_score = #{questionsScore}, + + where exam_code = #{examCode} + + + + delete from exam_finish_answer where exam_code = #{examCode} + + + + delete from exam_finish_answer where exam_code = #{examCode} and user_code = #{userCode} + + + + delete from exam_finish_answer where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsContentDataMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsContentDataMapper.xml new file mode 100644 index 0000000..d3c6b6d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsContentDataMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsListDataMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsListDataMapper.xml new file mode 100644 index 0000000..0d823eb --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamQuestionsListDataMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTaskAnswerMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTaskAnswerMapper.xml new file mode 100644 index 0000000..0700d45 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTaskAnswerMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + select exam_code, user_code,exam_times, questions_code, questions_number, questions_type, questions_answer, is_mark, is_current from exam_task_answer + + + + + + + + insert into exam_task_answer + + exam_code, + user_code, + exam_times, + questions_code, + questions_number, + questions_type, + questions_answer, + is_mark, + is_current, + + + #{examCode}, + #{userCode}, + #{examTimes}, + #{questionsCode}, + #{questionsNumber}, + #{questionsType}, + #{questionsAnswer}, + #{isMark}, + #{isCurrent}, + + + + + update exam_task_answer + + user_code = #{userCode}, + questions_code = #{questionsCode}, + questions_number = #{questionsNumber}, + questions_type = #{questionsType}, + questions_answer = #{questionsAnswer}, + is_mark = #{isMark}, + is_current = #{isCurrent}, + + where exam_code = #{examCode} + + + + delete from exam_task_answer where exam_code = #{examCode} and user_code = #{userCode} and questions_code = #{questionsCode} + + + + delete from exam_task_answer where exam_code = #{examCode} + + + + delete from exam_task_answer where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTitleDataMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTitleDataMapper.xml new file mode 100644 index 0000000..4b38300 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamTitleDataMapper.xml @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamUserScoreMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamUserScoreMapper.xml new file mode 100644 index 0000000..c3a39aa --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/onlineexam/ExamUserScoreMapper.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + select exam_code, user_code, start_time, end_time, exam_score, questions_score, exam_number, answered_number, not_answered, status from exam_user_score + + + + + + + + insert into exam_user_score + + exam_code, + user_code, + start_time, + end_time, + exam_score, + questions_score, + exam_number, + answered_number, + not_answered, + status, + + + #{examCode}, + #{userCode}, + #{startTime}, + #{endTime}, + #{examScore}, + #{questionsScore}, + #{examNumber}, + #{answeredNumber}, + #{notAnswered}, + #{status}, + + + + + insert into exam_user_score + select a.exam_code, a.user_code, b.start_time, now() as end_time, d.questions_score, a.exam_score,c.exam_number,a.answered_number,c.exam_number - a.answered_number as not_answered, 0 as status from + ( + select exam_code, user_code, sum(exam_score) as exam_score,count(questions_code) as answered_number from exam_finish_answer + where exam_code = #{examCode} and user_code = #{userCode} group by exam_code,user_code + ) a + left join exam_task_person b on b.exam_code = #{examCode} and b.user_code = #{userCode} + left join + ( + select count(questions_code) as exam_number from exam_task_questions where exam_code = #{examCode} + ) c on 1= 1 + left join + ( + select sum(questions_score) as questions_score from exam_questions_property where questions_code in + ( + select questions_code from exam_task_questions where exam_code = #{examCode} + ) + ) d on 1=1 + + + + update exam_user_score + + user_code = #{userCode}, + start_time = #{startTime}, + end_time = #{endTime}, + exam_score = #{examScore}, + questions_score = #{questionsScore}, + exam_number = #{examNumber}, + answered_number = #{answeredNumber}, + not_answered = #{notAnswered}, + status = #{status}, + + where exam_code = #{examCode} + + + + delete from exam_user_score where exam_code = #{examCode} and user_code = #{userCode} + + + + delete from exam_user_score where exam_code = #{examCode} + + + + delete from exam_user_score where exam_code in + + #{examCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamBankPictureMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamBankPictureMapper.xml new file mode 100644 index 0000000..13aa456 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamBankPictureMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + select photo_id, photo_code, photo_path, photo_url, file_name, original_name, create_by, create_time, status from exam_bank_picture + + + + + + + + insert into exam_bank_picture + + photo_code, + photo_path, + photo_url, + file_name, + original_name, + create_by, + create_time, + status, + + + #{photoCode}, + #{photoPath}, + #{photoUrl}, + #{fileName}, + #{originalName}, + #{createBy}, + now(), + 0, + + + + + update exam_bank_picture + + photo_id = #{photoId}, + photo_path = #{photoPath}, + photo_url = #{photoUrl}, + file_name = #{fileName}, + original_name = #{originalName}, + create_by = #{createBy}, + create_time = #{createTime}, + status = #{status}, + + where photo_code = #{photoCode} + + + + delete from exam_bank_picture where photo_code = #{photoCode} + + + + delete from exam_bank_picture where photo_code in + + #{photoCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsAnswerMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsAnswerMapper.xml new file mode 100644 index 0000000..f0ccf87 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsAnswerMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + select questions_code, option_code, option_describe, is_right, order_id from exam_questions_answer + + + + + + + + + + insert into exam_questions_answer + + questions_code, + option_code, + option_describe, + is_right, + order_id, + + + #{questionsCode}, + #{optionCode}, + #{optionDescribe}, + #{isRight}, + #{orderId}, + + + + + + + update exam_questions_answer + + option_code = #{optionCode}, + option_describe = #{optionDescribe}, + is_right = #{isRight}, + order_id = #{orderId}, + + where questions_code = #{questionsCode} + + + + delete from exam_questions_answer where questions_code = #{questionsCode} + + + + delete from exam_questions_answer where questions_code in + + #{questionsCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsBankMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsBankMapper.xml new file mode 100644 index 0000000..1900ac9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsBankMapper.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + select a.bank_id, a.bank_code, a.bank_name, a.bank_describe, a.bank_version, a.exam_type, b.type_name,a.online_date, a.picture_url, + ifnull(c.judge_number,0) as judge_number,ifnull(d.radio_number,0) as radio_number,ifnull(e.choice_number,0) as choice_number,a.radio_score, + a.choice_score, a.judge_score, a.status, a.create_by, a.create_dept, a.create_time + from exam_questions_bank a + left join exam_type b on b.type_id = a.exam_type + left join + ( + select bank_code,count(questions_type) as judge_number from exam_questions_property where questions_type = 1 group by bank_code + ) c on c.bank_code = a.bank_code + left join + ( + select bank_code,count(questions_type) as radio_number from exam_questions_property where questions_type = 2 group by bank_code + ) d on d.bank_code = a.bank_code + left join + ( + select bank_code,count(questions_type) as choice_number from exam_questions_property where questions_type = 3 group by bank_code + ) e on e.bank_code = a.bank_code + + + + + + + + + + + + insert into exam_questions_bank + + bank_code, + bank_name, + bank_describe, + bank_version, + exam_type, + online_date, + picture_url, + radio_score, + choice_score, + judge_score, + status, + create_by, + create_dept, + create_time, + + + #{bankCode}, + #{bankName}, + #{bankDescribe}, + #{bankVersion}, + #{examType}, + #{onlineDate}, + #{pictureUrl}, + #{radioScore}, + #{choiceScore}, + #{judgeScore}, + 0, + #{createBy}, + #{createDept}, + now(), + + + + + update exam_questions_bank + + bank_id = #{bankId}, + bank_name = #{bankName}, + bank_describe = #{bankDescribe}, + bank_version = #{bankVersion}, + exam_type = #{examType}, + online_date = #{onlineDate}, + picture_url = #{pictureUrl}, + radio_score = #{radioScore}, + choice_score = #{choiceScore}, + judge_score = #{judgeScore}, + status = #{status}, + create_by = #{createBy}, + create_dept = #{createDept}, + create_time = #{createTime}, + + where bank_code = #{bankCode} + + + + delete from exam_questions_bank where bank_code = #{bankCode} + + + + delete from exam_questions_bank where bank_code in + + #{bankCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsContentMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsContentMapper.xml new file mode 100644 index 0000000..a11aaf9 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsContentMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + select questions_code, questions_content from exam_questions_content + + + + + + + + insert into exam_questions_content + + questions_code, + questions_content, + + + #{questionsCode}, + #{questionsContent}, + + + + + update exam_questions_content + + questions_content = #{questionsContent}, + + where questions_code = #{questionsCode} + + + + delete from exam_questions_content where questions_code = #{questionsCode} + + + + delete from exam_questions_content where questions_code in + + #{questionsCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsListMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsListMapper.xml new file mode 100644 index 0000000..5fdc91e --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsListMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + select @rownum := @rownum + 1 as rownum, bank_code, bank_name, questions_id, questions_code, questions_title, questions_type, questions_score, rate_number, right_answer, answer_analyse, status, create_by, create_dept, create_time from + ( + select a.bank_code, b.bank_name, a.questions_id, a.questions_code, substring(a.questions_title,1,50) as questions_title, a.questions_type, a.questions_score, a.rate_number, a.right_answer, a.answer_analyse, a.status, a.create_by, a.create_dept, a.create_time from exam_questions_property a + left join exam_questions_bank b on b.bank_code = a.bank_code + order by a.questions_type, a.bank_code, a.questions_id + ) t, (select @rownum := 0) r + + + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsMapper.xml new file mode 100644 index 0000000..edf0053 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + select bank_code, questions_id, questions_code, questions_title, questions_content, questions_type, questions_score, rate_number, right_answer, answer_analyse, status, create_by, create_dept, create_time from exam_questions + + + + + + + + + + insert into exam_questions + + bank_code, + questions_code, + questions_title, + questions_content, + questions_type, + questions_score, + rate_number, + right_answer, + answer_analyse, + status, + create_by, + create_dept, + create_time, + + + #{bankCode}, + #{questionsCode}, + #{questionsTitle}, + #{questionsContent}, + #{questionsType}, + #{questionsScore}, + #{rateNumber}, + #{rightAnswer}, + #{answerAnalyse}, + 0, + #{createBy}, + #{createDept}, + now(), + + + + + update exam_questions + + bank_code = #{bankCode}, + questions_id = #{questionsId}, + questions_title = #{questionsTitle}, + questions_content = #{questionsContent}, + questions_type = #{questionsType}, + questions_score = #{questionsScore}, + rate_number = #{rateNumber}, + right_answer = #{rightAnswer}, + answer_analyse = #{answerAnalyse}, + status = #{status}, + create_by = #{createBy}, + create_dept = #{createDept}, + create_time = #{createTime}, + + where questions_code = #{questionsCode} + + + + delete from exam_questions where questions_code = #{questionsCode} + + + + delete from exam_questions where questions_code in + + #{questionsCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsPropertyMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsPropertyMapper.xml new file mode 100644 index 0000000..5709135 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamQuestionsPropertyMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + select @rownum := @rownum + 1 as rownum, bank_code, questions_id, questions_code, questions_title, questions_type, questions_score, rate_number, right_answer, answer_analyse, status, create_by, create_dept, create_time from + ( + select bank_code, questions_id, questions_code, substring(questions_title,1,50) as questions_title, questions_type, questions_score, rate_number, right_answer, answer_analyse, status, create_by, create_dept, create_time from exam_questions_property + ) t, (select @rownum := 0) r + + + + + + + + insert into exam_questions_property + + bank_code, + questions_code, + questions_title, + questions_type, + questions_score, + rate_number, + right_answer, + answer_analyse, + status, + create_by, + create_dept, + create_time, + + + #{bankCode}, + #{questionsCode}, + #{questionsTitle}, + #{questionsType}, + #{questionsScore}, + #{rateNumber}, + #{rightAnswer}, + #{answerAnalyse}, + 0, + #{createBy}, + #{createDept}, + now(), + + + + + update exam_questions_property + + bank_code = #{bankCode}, + questions_id = #{questionsId}, + questions_title = #{questionsTitle}, + questions_type = #{questionsType}, + questions_score = #{questionsScore}, + rate_number = #{rateNumber}, + right_answer = #{rightAnswer}, + answer_analyse = #{answerAnalyse}, + status = #{status}, + create_by = #{createBy}, + create_dept = #{createDept}, + create_time = #{createTime}, + + where questions_code = #{questionsCode} + + + + delete from exam_questions_property where questions_code = #{questionsCode} + + + + delete from exam_questions_property where questions_code in + + #{questionsCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamTypeMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamTypeMapper.xml new file mode 100644 index 0000000..7c45e9d --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/questions/ExamTypeMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + select type_id, parent_id, type_code, type_name, order_id, status, create_by, create_time from exam_type + + + + + + + + insert into exam_type + + parent_id, + type_code, + type_name, + order_id, + status, + create_by, + create_time, + + + #{parentId}, + #{typeCode}, + #{typeName}, + #{orderId}, + 0, + #{createBy}, + now(), + + + + + update exam_type + + parent_id = #{parentId}, + type_code = #{typeCode}, + type_name = #{typeName}, + order_id = #{orderId}, + status = #{status}, + create_by = #{createBy}, + create_time = #{createTime}, + + where type_id = #{typeId} + + + + delete from exam_type where type_id = #{typeId} + + + + delete from exam_type where type_id in + + #{typeId} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupMapper.xml new file mode 100644 index 0000000..d359b42 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupMapper.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + select a.group_id, a.group_code, a.group_name, b.person_number,a.group_describe, a.status, a.create_by, a.create_time from sys_group a + left join + inner join + ( + select group_code,count(group_code) as person_number from sys_group_person group by group_code + ) b on b.group_code = a.group_code + + + + + + + + + + insert into sys_group + + group_code, + group_name, + group_describe, + status, + create_by, + create_time, + + + #{groupCode}, + #{groupName}, + #{groupDescribe}, + 0, + #{createBy}, + now(), + + + + + update sys_group + + group_code = #{groupCode}, + group_name = #{groupName}, + group_describe = #{groupDescribe}, + status = #{status}, + create_by = #{createBy}, + create_time = #{createTime}, + + where group_id = #{groupId} + + + + delete from sys_group where group_id = #{groupId} + + + + delete from sys_group where group_id in + + #{groupId} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupPersonMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupPersonMapper.xml new file mode 100644 index 0000000..6b42873 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysGroupPersonMapper.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + select group_code, person_code, order_id from sys_group_person + + + + + + + + insert into sys_group_person + + group_code, + person_code, + + + #{groupCode}, + #{personCode}, + + + + + update sys_group_person + + person_code = #{personCode}, + order_id = #{orderId}, + + where group_code = #{groupCode} + + + + delete from sys_group_person where group_code = #{groupCode} + + + + delete from sys_group_person where group_code in + + #{groupCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserChoiceMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserChoiceMapper.xml new file mode 100644 index 0000000..737da02 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserChoiceMapper.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select choice_code, user_code, order_id from sys_user_choice + + + + + + select a.user_id,a.user_code,a.user_name,a.nick_name,a.dept_id,dept_name,a.email,a.phonenumber,a.sex,a.avatar,a.status,a.remark from sys_user a + left join sys_dept b on b.dept_id = a.dept_id + where a.user_code in + ( + select person_code from sys_group_person where group_code = #{choiceCode} + ) + + + + + + + + + + insert into sys_user_choice + + choice_code, + user_code, + order_id, + + + #{choiceCode}, + #{userCode}, + #{orderId}, + + + + + insert into sys_user_choice select #{choiceCode},user_code,order_id from temp_user_choice where choice_code = #{conditionCode} + + + + insert into temp_user_choice select #{choiceCode},user_code,order_id from sys_user_choice where choice_code = #{conditionCode} + + + + update sys_user_choice + + user_code = #{userCode}, + order_id = #{orderId}, + + where choice_code = #{choiceCode} + + + + delete from sys_user_choice where choice_code = #{choiceCode} + + + + delete from sys_user_choice where choice_code in + + #{choiceCode} + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserDataMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserDataMapper.xml new file mode 100644 index 0000000..4a77d22 --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/system/SysUserDataMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + select a.user_id,a.user_code,a.user_name,a.nick_name,a.dept_id,dept_name,a.email,a.phonenumber,a.sex,a.avatar,a.status,a.remark from sys_user a + left join sys_dept b on b.dept_id = a.dept_id + + + + + + select b.user_id,a.user_code,b.user_name,b.nick_name,b.dept_id,c.dept_name,b.email,b.phonenumber,b.sex,b.avatar,b.status,b.remark,a.order_id from temp_user_choice a + left join sys_user b on b.user_code = a.user_code + left join sys_dept c on c.dept_id = b.dept_id + where a.choice_code = #{choiceCode} + order by a.order_id desc + + + + + \ No newline at end of file diff --git a/examapi/yanzhu-exam/src/main/resources/mapper/system/TempUserChoiceMapper.xml b/examapi/yanzhu-exam/src/main/resources/mapper/system/TempUserChoiceMapper.xml new file mode 100644 index 0000000..befcd3a --- /dev/null +++ b/examapi/yanzhu-exam/src/main/resources/mapper/system/TempUserChoiceMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + select choice_code, user_code, order_id from temp_user_choice + + + + + + + + insert into temp_user_choice + + choice_code, + user_code, + + + #{choiceCode}, + #{userCode}, + + + + + update temp_user_choice + + user_code = #{userCode}, + order_id = #{orderId}, + + where choice_code = #{choiceCode} + + + + + + delete from temp_user_choice where choice_code = #{choiceCode} and user_code = #{userCode} + + + + + \ No newline at end of file