From 04b4df2964ed628468fb1dd4d33f6759b18224eb Mon Sep 17 00:00:00 2001 From: gy b Date: Thu, 4 Jan 2024 16:58:19 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=A7=A3=E7=B3=BB=E7=BB=9F=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 47 + LICENSE | 20 + pay/pom.xml | 59 + .../main/java/com/ruoyi/CallBackService.java | 32 + pay/src/main/java/com/ruoyi/ElegentPay.java | 66 + .../main/java/com/ruoyi/ali/AlipayConfig.java | 40 + .../java/com/ruoyi/ali/AlipayConstant.java | 30 + .../com/ruoyi/ali/AlipayElegentTrade.java | 461 ++ .../com/ruoyi/ali/AlipayElegentValid.java | 124 + .../com/ruoyi/annotation/TradePlatform.java | 20 + .../java/com/ruoyi/config/CallbackConfig.java | 23 + .../java/com/ruoyi/constant/PayConstant.java | 11 + .../java/com/ruoyi/constant/Platform.java | 16 + .../java/com/ruoyi/constant/TradeType.java | 33 + .../com/ruoyi/core/CallBackServiceImpl.java | 35 + .../com/ruoyi/core/CallbackController.java | 90 + .../java/com/ruoyi/core/CallbackWatch.java | 73 + .../java/com/ruoyi/core/ElegentConfig.java | 27 + .../java/com/ruoyi/core/ElegentLoader.java | 82 + .../java/com/ruoyi/core/ElegentPayImpl.java | 136 + .../java/com/ruoyi/core/ElegentTrade.java | 54 + .../java/com/ruoyi/core/ElegentValid.java | 48 + .../main/java/com/ruoyi/core/WatchList.java | 20 + .../main/java/com/ruoyi/dto/PayRequest.java | 20 + .../main/java/com/ruoyi/dto/PayResponse.java | 29 + .../com/ruoyi/dto/QueryRefundResponse.java | 24 + .../java/com/ruoyi/dto/QueryResponse.java | 25 + .../java/com/ruoyi/dto/RefundRequest.java | 16 + .../java/com/ruoyi/dto/ValidResponse.java | 15 + pay/src/main/java/com/ruoyi/dto/WatchDTO.java | 12 + .../com/ruoyi/exceptions/TradeException.java | 24 + .../main/java/com/ruoyi/key/KeyManager.java | 16 + .../com/ruoyi/key/impl/DefaultKeyManager.java | 19 + .../main/java/com/ruoyi/util/FileUtil.java | 37 + .../java/com/ruoyi/wx/WxPayElegentTrade.java | 459 ++ .../java/com/ruoyi/wx/WxPayElegentValid.java | 153 + .../main/java/com/ruoyi/wx/WxpayConfig.java | 20 + .../main/java/com/ruoyi/wx/WxpayConstant.java | 48 + .../main/resources/META-INF/spring.factories | 14 + pom.xml | 231 + ruoyi-admin/pom.xml | 100 + .../main/java/com/ruoyi/RuoYiApplication.java | 32 + .../com/ruoyi/RuoYiServletInitializer.java | 18 + .../bestsign/ArbitrSignatuController.java | 33 + .../bestsign/RegisterController.java | 31 + .../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 | 132 + .../system/SysDictDataController.java | 121 + .../system/SysDictTypeController.java | 131 + .../controller/system/SysIndexController.java | 29 + .../controller/system/SysLoginController.java | 100 + .../controller/system/SysMenuController.java | 142 + .../system/SysNoticeController.java | 91 + .../controller/system/SysPostController.java | 129 + .../system/SysProfileController.java | 136 + .../system/SysRegisterController.java | 38 + .../controller/system/SysRoleController.java | 262 ++ .../controller/system/SysUserController.java | 258 ++ .../web/controller/tool/TestController.java | 183 + .../AdjudicationController.java | 191 + .../wisdomarbitrate/ArbitratorController.java | 44 + .../CaseApplicationController.java | 588 +++ .../CaseApplicationLogController.java | 107 + .../CaseArbitrateController.java | 47 + .../CaseEvidenceController.java | 160 + .../CaseLogRecordController.java | 40 + .../CaseNumRuleController.java | 74 + .../CasePaymentController.java | 110 + .../DeptIdentifyController.java | 237 ++ .../IdentityAuthenticationController.java | 43 + .../SendMailRecordController.java | 48 + .../wisdomarbitrate/TemplateController.java | 59 + .../wisdomarbitrate/VideoController.java | 149 + .../wisdomarbitrate/WeChatUserController.java | 62 + .../ruoyi/web/core/config/SwaggerConfig.java | 125 + .../META-INF/spring-devtools.properties | 1 + .../src/main/resources/alipay_private.key | 1 + .../src/main/resources/alipay_public.key | 1 + .../src/main/resources/application-druid.yml | 61 + .../src/main/resources/application.yml | 197 + ruoyi-admin/src/main/resources/banner.txt | 24 + .../main/resources/i18n/messages.properties | 38 + ruoyi-admin/src/main/resources/logback.xml | 93 + .../main/resources/mybatis/mybatis-config.xml | 20 + .../src/main/resources/wxpay_private.key | 1 + ruoyi-common/pom.xml | 290 ++ .../ruoyi/common/annotation/Anonymous.java | 19 + .../ruoyi/common/annotation/DataScope.java | 33 + .../ruoyi/common/annotation/DataSource.java | 28 + .../com/ruoyi/common/annotation/Excel.java | 187 + .../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 + .../ruoyi/common/annotation/VoidFunction.java | 13 + .../ruoyi/common/config/EsignDemoConfig.java | 13 + .../com/ruoyi/common/config/RuoYiConfig.java | 148 + .../ruoyi/common/constant/CacheConstants.java | 45 + .../constant/CaseApplicationConstants.java | 58 + .../com/ruoyi/common/constant/Constants.java | 157 + .../common/constant/EsignEncryption.java | 371 ++ .../common/constant/EsignHeaderConstant.java | 26 + .../common/constant/EsignHttpCfgHelper.java | 486 +++ .../common/constant/FileTransformation.java | 286 ++ .../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 | 117 + .../java/com/ruoyi/common/core/domain/R.java | 115 + .../ruoyi/common/core/domain/TreeEntity.java | 79 + .../ruoyi/common/core/domain/TreeSelect.java | 79 + .../core/domain/entity/EsignCoreSdkInfo.java | 24 + .../core/domain/entity/EsignHttpResponse.java | 24 + .../common/core/domain/entity/SysDept.java | 214 + .../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 | 350 ++ .../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 + .../ruoyi/common/enums/EsignRequestType.java | 39 + .../com/ruoyi/common/enums/HttpMethod.java | 32 + .../com/ruoyi/common/enums/LimitType.java | 20 + .../com/ruoyi/common/enums/OperatorType.java | 24 + .../common/enums/UpdateSubmitStatus.java | 38 + .../com/ruoyi/common/enums/UserStatus.java | 30 + .../com/ruoyi/common/enums/YesOrNoEnum.java | 33 + .../common/exception/DemoModeException.java | 15 + .../common/exception/EsignDemoException.java | 36 + .../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/EmailOutUtil.java | 436 ++ .../com/ruoyi/common/utils/EmailUtil.java | 68 + .../common/utils/EsignApplicaConfig.java | 13 + .../ruoyi/common/utils/EsignHttpHelper.java | 178 + .../com/ruoyi/common/utils/ExceptionUtil.java | 39 + .../com/ruoyi/common/utils/IdCardUtils.java | 57 + .../com/ruoyi/common/utils/IdWorkerUtil.java | 48 + .../java/com/ruoyi/common/utils/LogUtils.java | 18 + .../com/ruoyi/common/utils/MessageUtils.java | 26 + .../ruoyi/common/utils/MoneyFormatUtils.java | 53 + .../ruoyi/common/utils/ObjectFieldUtils.java | 57 + .../com/ruoyi/common/utils/PageUtils.java | 35 + .../java/com/ruoyi/common/utils/PdfUtils.java | 147 + .../com/ruoyi/common/utils/ReadFileUtils.java | 86 + .../java/com/ruoyi/common/utils/SealUtil.java | 123 + .../com/ruoyi/common/utils/SecurityUtils.java | 120 + .../com/ruoyi/common/utils/ServletUtils.java | 218 + .../java/com/ruoyi/common/utils/SmsUtils.java | 78 + .../com/ruoyi/common/utils/SpringUtil.java | 34 + .../com/ruoyi/common/utils/StringUtils.java | 614 +++ .../java/com/ruoyi/common/utils/Threads.java | 99 + .../java/com/ruoyi/common/utils/WordUtil.java | 210 + .../common/utils/WxAppletNotifyUtils.java | 64 + .../ruoyi/common/utils/bean/BeanUtils.java | 110 + .../common/utils/bean/BeanValidators.java | 24 + .../common/utils/bean/EsignFileBean.java | 57 + .../common/utils/file/FileTypeUtils.java | 76 + .../common/utils/file/FileUploadUtils.java | 232 ++ .../ruoyi/common/utils/file/FileUtils.java | 305 ++ .../ruoyi/common/utils/file/ImageUtils.java | 98 + .../common/utils/file/MimeTypeUtils.java | 59 + .../common/utils/file/SaaSAPIFileUtils.java | 138 + .../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 | 24 + .../com/ruoyi/common/utils/poi/ExcelUtil.java | 1758 ++++++++ .../common/utils/reflect/ReflectUtils.java | 410 ++ .../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 | 70 + .../utils/thread/MultipleThreadListParam.java | 22 + .../thread/MultipleThreadStringParam.java | 21 + .../utils/thread/MultipleThreadWorkUtil.java | 592 +++ .../common/utils/thread/ThreadPoolUtil.java | 112 + .../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 +++ .../common/websocket/MyWebSocketHandler.java | 140 + .../common/websocket/WebSocketConfig.java | 26 + .../main/java/com/ruoyi/common/xss/Xss.java | 27 + .../com/ruoyi/common/xss/XssValidator.java | 34 + ruoyi-framework/pom.xml | 64 + .../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 | 31 + .../ruoyi/framework/config/CaptchaConfig.java | 83 + .../ruoyi/framework/config/DruidConfig.java | 126 + .../config/FastJson2JsonRedisSerializer.java | 52 + .../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 | 56 + .../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 | 138 + .../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 | 231 + .../web/service/UserDetailsServiceImpl.java | 66 + 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 + 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 + ruoyi-system/pom.xml | 39 + .../bestsign/domain/ArbitrSignatuVO.java | 51 + .../ruoyi/bestsign/domain/CredentialVO.java | 22 + .../bestsign/domain/PersonRegisterVO.java | 29 + .../service/ArbitrSignatuService.java | 12 + .../bestsign/service/SignRegisterService.java | 18 + .../impl/ArbitrSignatuServiceImpl.java | 29 + .../service/impl/RegisterServiceImpl.java | 63 + .../bestsign/utils/BestsignOpenApiClient.java | 286 ++ .../bestsign/utils/HttpClientSender.java | 390 ++ .../com/ruoyi/bestsign/utils/RSAUtils.java | 281 ++ .../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 | 127 + .../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 | 107 + .../system/mapper/SysRoleDeptMapper.java | 44 + .../ruoyi/system/mapper/SysRoleMapper.java | 115 + .../system/mapper/SysRoleMenuMapper.java | 44 + .../ruoyi/system/mapper/SysUserMapper.java | 174 + .../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 | 211 + .../service/impl/SysConfigServiceImpl.java | 232 ++ .../service/impl/SysDeptServiceImpl.java | 341 ++ .../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 +++ .../ruoyi/wisdomarbitrate/StringIdsReq.java | 22 + .../wisdomarbitrate/domain/Adjudication.java | 188 + .../domain/ArbitrateRecord.java | 76 + .../wisdomarbitrate/domain/Arbitrator.java | 123 + .../domain/BatchCaseApplication.java | 31 + .../wisdomarbitrate/domain/CaseAffiliate.java | 353 ++ .../domain/CaseApplication.java | 421 ++ .../domain/CaseApplicationPay.java | 23 + .../wisdomarbitrate/domain/CaseAttach.java | 58 + .../domain/CaseEvidenceDirectory.java | 60 + .../ruoyi/wisdomarbitrate/domain/CaseIds.java | 9 + .../wisdomarbitrate/domain/CaseLogRecord.java | 145 + .../wisdomarbitrate/domain/CaseNumRule.java | 28 + .../domain/CasePaymentRecord.java | 45 + .../wisdomarbitrate/domain/DeptIdentify.java | 61 + .../wisdomarbitrate/domain/FatchRule.java | 41 + .../domain/IdentityAuthentication.java | 148 + .../domain/ReservedConference.java | 63 + .../wisdomarbitrate/domain/SealManage.java | 48 + .../domain/SealSignRecord.java | 64 + .../domain/SendMailRecord.java | 115 + .../wisdomarbitrate/domain/SmsSendRecord.java | 45 + .../domain/TemplateManage.java | 57 + .../domain/TemplateManual.java | 33 + .../domain/dto/CaseApplicationLogDTO.java | 255 ++ .../domain/dto/CaseConfirmPayDTO.java | 29 + .../domain/dto/CaseEvidenceDTO.java | 49 + .../domain/dto/CasePayDTO.java | 42 + .../domain/vo/ArchivesDetailVO.java | 24 + .../wisdomarbitrate/domain/vo/BookSendVO.java | 26 + .../domain/vo/CaseDetailVO.java | 67 + .../domain/vo/CaseEvidenceDirectoryVO.java | 200 + .../domain/vo/CaseEvidenceVO.java | 40 + .../domain/vo/CasePayListVO.java | 26 + .../domain/vo/ColumnValue.java | 45 + .../domain/vo/CompareCaseVO.java | 37 + .../domain/vo/LogisticsInfoVO.java | 16 + .../domain/vo/ReservedConferenceVO.java | 47 + .../wisdomarbitrate/domain/vo/SealListVO.java | 35 + .../domain/vo/SendRoomNoMessageVO.java | 29 + .../domain/vo/TemplateFatchRule.java | 17 + .../wisdomarbitrate/domain/vo/ToDoCount.java | 34 + .../domain/vo/UpdateSubmitVO.java | 38 + .../domain/vo/WeChatUserVO.java | 63 + .../mapper/ArbitrateRecordMapper.java | 17 + .../mapper/ArbitratorMapper.java | 12 + .../mapper/CaseAffiliateLogMapper.java | 25 + .../mapper/CaseAffiliateMapper.java | 45 + .../mapper/CaseApplicationLogMapper.java | 56 + .../mapper/CaseApplicationMapper.java | 140 + .../mapper/CaseAttachLogMapper.java | 31 + .../mapper/CaseAttachMapper.java | 38 + .../mapper/CaseEvidenceDirectoryMapper.java | 29 + .../mapper/CaseEvidenceMapper.java | 16 + .../mapper/CaseLogRecordMapper.java | 19 + .../mapper/CaseNumRuleMapper.java | 20 + .../mapper/CasePaymentRecordMapper.java | 15 + .../mapper/ColumnValueLogMapper.java | 29 + .../mapper/ColumnValueMapper.java | 37 + .../mapper/DeptIdentifyMapper.java | 20 + .../mapper/FatchRuleMapper.java | 32 + .../mapper/IdentityAuthenticationMapper.java | 12 + .../mapper/ReservedConferenceMapper.java | 40 + .../mapper/SealManageMapper.java | 16 + .../mapper/SealSignRecordMapper.java | 32 + .../mapper/SendMailRecordMapper.java | 15 + .../mapper/SmsRecordMapper.java | 22 + .../mapper/TemplateFatchRuleMapper.java | 19 + .../mapper/TemplateManageMapper.java | 16 + .../mapper/TemplateManualMapper.java | 16 + .../mapper/WeChatUserMapper.java | 21 + .../service/CaseApplicationLogService.java | 58 + .../service/IAdjudicationService.java | 60 + .../service/IArbitratorService.java | 12 + .../service/ICaseApplicationService.java | 154 + .../service/ICaseArbitrateService.java | 17 + .../service/ICaseEvidenceService.java | 70 + .../service/ICaseLogRecordService.java | 17 + .../service/ICaseNumRuleService.java | 20 + .../service/ICasePaymentService.java | 36 + .../service/IDeptIdentifyService.java | 69 + .../service/ISendMailRecordService.java | 15 + .../service/ITemplateService.java | 16 + .../IdentityAuthenticationService.java | 34 + .../wisdomarbitrate/service/VideoService.java | 58 + .../service/WeChatUserService.java | 18 + .../service/impl/AdjudicationServiceImpl.java | 1513 +++++++ .../service/impl/ArbitratorServiceImpl.java | 28 + .../impl/CallBackHandleServiceImpl.java | 36 + .../impl/CaseApplicationLogServiceImpl.java | 512 +++ .../impl/CaseApplicationServiceImpl.java | 3703 +++++++++++++++++ .../impl/CaseArbitrateServiceImpl.java | 533 +++ .../service/impl/CaseEvidenceServiceImpl.java | 511 +++ .../service/impl/CaseImportValid.java | 328 ++ .../impl/CaseLogRecordServiceImpl.java | 51 + .../service/impl/CaseNumRuleServiceImpl.java | 72 + .../service/impl/CasePaymentServiceImpl.java | 491 +++ .../service/impl/CaseZipImportImpl.java | 1035 +++++ .../service/impl/DeptIdentifyServiceImpl.java | 652 +++ .../IdentityAuthenticationServiceImpl.java | 233 ++ .../impl/SendMailRecordServiceImpl.java | 26 + .../service/impl/TemplateServiceImpl.java | 54 + .../service/impl/VideoServiceImpl.java | 485 +++ .../service/impl/WeChatUserServiceImpl.java | 146 + .../task/CaseZipImportTask.java | 72 + .../wisdomarbitrate/utils/CaseLogUtils.java | 84 + .../utils/FixSelectFlowDetailUtils.java | 362 ++ .../utils/ImageToBase64Converter.java | 30 + .../ruoyi/wisdomarbitrate/utils/OCRUtils.java | 275 ++ .../wisdomarbitrate/utils/SignAward.java | 546 +++ .../com/ruoyi/wisdomarbitrate/utils/Tset.java | 130 + .../wisdomarbitrate/utils/UnZipFileUtils.java | 94 + .../wisdomarbitrate/utils/ZipFileUtils.java | 48 + .../mapper/system/SysConfigMapper.xml | 117 + .../resources/mapper/system/SysDeptMapper.xml | 200 + .../mapper/system/SysDictDataMapper.xml | 124 + .../mapper/system/SysDictTypeMapper.xml | 105 + .../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 | 127 + .../mapper/system/SysRoleDeptMapper.xml | 34 + .../resources/mapper/system/SysRoleMapper.xml | 155 + .../mapper/system/SysRoleMenuMapper.xml | 34 + .../resources/mapper/system/SysUserMapper.xml | 339 ++ .../mapper/system/SysUserPostMapper.xml | 34 + .../mapper/system/SysUserRoleMapper.xml | 44 + .../wisdomarbitrate/ArbitrateRecordMapper.xml | 109 + .../wisdomarbitrate/ArbitratorMapper.xml | 40 + .../CaseAffiliateLogMapper.xml | 137 + .../wisdomarbitrate/CaseAffiliateMapper.xml | 204 + .../CaseApplicationLogMapper.xml | 291 ++ .../wisdomarbitrate/CaseApplicationMapper.xml | 1377 ++++++ .../wisdomarbitrate/CaseAttachLogMapper.xml | 108 + .../wisdomarbitrate/CaseAttachMapper.xml | 124 + .../CaseEvidenceDirectoryMapper.xml | 79 + .../wisdomarbitrate/CaseEvidenceMapper.xml | 31 + .../wisdomarbitrate/CaseLogRecordMapper.xml | 66 + .../wisdomarbitrate/CaseNumRuleMapper.xml | 105 + .../CasePaymentRecordMapper.xml | 57 + .../wisdomarbitrate/ColumnValueLogMapper.xml | 50 + .../wisdomarbitrate/ColumnValueMapper.xml | 62 + .../wisdomarbitrate/DeptIdentifyMapper.xml | 133 + .../wisdomarbitrate/FatchRuleMapper.xml | 116 + .../IdentityAuthenticationMapper.xml | 90 + .../ReservedConferenceMapper.xml | 37 + .../wisdomarbitrate/SealManageMapper.xml | 65 + .../wisdomarbitrate/SealSignRecordMapper.xml | 95 + .../wisdomarbitrate/SendMailRecordMapper.xml | 61 + .../wisdomarbitrate/SmsRecordMapper.xml | 80 + .../TemplateFatchRuleMapper.xml | 49 + .../wisdomarbitrate/TemplateManageMapper.xml | 85 + .../wisdomarbitrate/TemplateManualMapper.xml | 62 + .../wisdomarbitrate/WeChatUserMapper.xml | 61 + sql/quartz.sql | 176 + sql/ry_20230706.sql | 699 ++++ 549 files changed, 69911 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 pay/pom.xml create mode 100644 pay/src/main/java/com/ruoyi/CallBackService.java create mode 100644 pay/src/main/java/com/ruoyi/ElegentPay.java create mode 100644 pay/src/main/java/com/ruoyi/ali/AlipayConfig.java create mode 100644 pay/src/main/java/com/ruoyi/ali/AlipayConstant.java create mode 100644 pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java create mode 100644 pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java create mode 100644 pay/src/main/java/com/ruoyi/annotation/TradePlatform.java create mode 100644 pay/src/main/java/com/ruoyi/config/CallbackConfig.java create mode 100644 pay/src/main/java/com/ruoyi/constant/PayConstant.java create mode 100644 pay/src/main/java/com/ruoyi/constant/Platform.java create mode 100644 pay/src/main/java/com/ruoyi/constant/TradeType.java create mode 100644 pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java create mode 100644 pay/src/main/java/com/ruoyi/core/CallbackController.java create mode 100644 pay/src/main/java/com/ruoyi/core/CallbackWatch.java create mode 100644 pay/src/main/java/com/ruoyi/core/ElegentConfig.java create mode 100644 pay/src/main/java/com/ruoyi/core/ElegentLoader.java create mode 100644 pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java create mode 100644 pay/src/main/java/com/ruoyi/core/ElegentTrade.java create mode 100644 pay/src/main/java/com/ruoyi/core/ElegentValid.java create mode 100644 pay/src/main/java/com/ruoyi/core/WatchList.java create mode 100644 pay/src/main/java/com/ruoyi/dto/PayRequest.java create mode 100644 pay/src/main/java/com/ruoyi/dto/PayResponse.java create mode 100644 pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java create mode 100644 pay/src/main/java/com/ruoyi/dto/QueryResponse.java create mode 100644 pay/src/main/java/com/ruoyi/dto/RefundRequest.java create mode 100644 pay/src/main/java/com/ruoyi/dto/ValidResponse.java create mode 100644 pay/src/main/java/com/ruoyi/dto/WatchDTO.java create mode 100644 pay/src/main/java/com/ruoyi/exceptions/TradeException.java create mode 100644 pay/src/main/java/com/ruoyi/key/KeyManager.java create mode 100644 pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java create mode 100644 pay/src/main/java/com/ruoyi/util/FileUtil.java create mode 100644 pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java create mode 100644 pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java create mode 100644 pay/src/main/java/com/ruoyi/wx/WxpayConfig.java create mode 100644 pay/src/main/java/com/ruoyi/wx/WxpayConstant.java create mode 100644 pay/src/main/resources/META-INF/spring.factories create mode 100644 pom.xml create mode 100644 ruoyi-admin/pom.xml create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/ArbitrSignatuController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/RegisterController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/AdjudicationController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationLogController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseLogRecordController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseNumRuleController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/DeptIdentifyController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/IdentityAuthenticationController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/SendMailRecordController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/TemplateController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/VideoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/WeChatUserController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java create mode 100644 ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties create mode 100644 ruoyi-admin/src/main/resources/alipay_private.key create mode 100644 ruoyi-admin/src/main/resources/alipay_public.key create mode 100644 ruoyi-admin/src/main/resources/application-druid.yml create mode 100644 ruoyi-admin/src/main/resources/application.yml create mode 100644 ruoyi-admin/src/main/resources/banner.txt create mode 100644 ruoyi-admin/src/main/resources/i18n/messages.properties create mode 100644 ruoyi-admin/src/main/resources/logback.xml create mode 100644 ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml create mode 100644 ruoyi-admin/src/main/resources/wxpay_private.key create mode 100644 ruoyi-common/pom.xml create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/VoidFunction.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/config/EsignDemoConfig.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/CaseApplicationConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignEncryption.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHeaderConstant.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHttpCfgHelper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/FileTransformation.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignCoreSdkInfo.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignHttpResponse.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/EsignRequestType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/UpdateSubmitStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/YesOrNoEnum.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/EsignDemoException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailOutUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignApplicaConfig.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignHttpHelper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/IdWorkerUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/MoneyFormatUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ObjectFieldUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/PdfUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ReadFileUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/SealUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletNotifyUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/EsignFileBean.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/SaaSAPIFileUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadListParam.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadStringParam.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadWorkUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/ThreadPoolUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/websocket/MyWebSocketHandler.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/websocket/WebSocketConfig.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java create mode 100644 ruoyi-framework/pom.xml create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java create mode 100644 ruoyi-generator/pom.xml create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java create mode 100644 ruoyi-generator/src/main/resources/generator.yml create mode 100644 ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml create mode 100644 ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml create mode 100644 ruoyi-generator/src/main/resources/vm/java/controller.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/domain.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/mapper.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/service.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/js/api.js.vm create mode 100644 ruoyi-generator/src/main/resources/vm/sql/sql.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/index.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt create mode 100644 ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm create mode 100644 ruoyi-quartz/pom.xml create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java create mode 100644 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml create mode 100644 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml create mode 100644 ruoyi-system/pom.xml create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/ArbitrSignatuVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/CredentialVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/PersonRegisterVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/service/ArbitrSignatuService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/service/SignRegisterService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/ArbitrSignatuServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/RegisterServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/BestsignOpenApiClient.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/HttpClientSender.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/RSAUtils.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/StringIdsReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Adjudication.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ArbitrateRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Arbitrator.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/BatchCaseApplication.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAffiliate.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplicationPay.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseEvidenceDirectory.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseIds.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseNumRule.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/DeptIdentify.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/FatchRule.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/IdentityAuthentication.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ReservedConference.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealManage.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealSignRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SendMailRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SmsSendRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManage.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManual.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseApplicationLogDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseConfirmPayDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseEvidenceDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ArchivesDetailVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/BookSendVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceDirectoryVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CasePayListVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ColumnValue.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CompareCaseVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/LogisticsInfoVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ReservedConferenceVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SealListVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SendRoomNoMessageVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/TemplateFatchRule.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ToDoCount.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/UpdateSubmitVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/WeChatUserVO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitrateRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitratorMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceDirectoryMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseLogRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseNumRuleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/DeptIdentifyMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/FatchRuleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/IdentityAuthenticationMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ReservedConferenceMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealManageMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealSignRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SendMailRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SmsRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateFatchRuleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManageMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManualMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/WeChatUserMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/CaseApplicationLogService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IAdjudicationService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IArbitratorService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseApplicationService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseLogRecordService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseNumRuleService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IDeptIdentifyService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ISendMailRecordService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ITemplateService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IdentityAuthenticationService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/VideoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/WeChatUserService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/AdjudicationServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/ArbitratorServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationLogServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseImportValid.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseNumRuleServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseZipImportImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/DeptIdentifyServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/SendMailRecordServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/TemplateServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/VideoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/WeChatUserServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/task/CaseZipImportTask.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/CaseLogUtils.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/FixSelectFlowDetailUtils.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ImageToBase64Converter.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/OCRUtils.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/SignAward.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/Tset.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/UnZipFileUtils.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ZipFileUtils.java create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitrateRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitratorMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceDirectoryMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseLogRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseNumRuleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/DeptIdentifyMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/FatchRuleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/IdentityAuthenticationMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ReservedConferenceMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealManageMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealSignRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SendMailRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SmsRecordMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateFatchRuleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManageMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManualMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/wisdomarbitrate/WeChatUserMapper.xml create mode 100644 sql/quartz.sql create mode 100644 sql/ry_20230706.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8368a --- /dev/null +++ b/.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/LICENSE b/LICENSE new file mode 100644 index 0000000..8564f29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2018 RuoYi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/pay/pom.xml b/pay/pom.xml new file mode 100644 index 0000000..0558d6f --- /dev/null +++ b/pay/pom.xml @@ -0,0 +1,59 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + pay + 1.0.0-SNAPSHOT + + + 8 + 8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-autoconfigure + 2.7.10 + true + + + + org.projectlombok + lombok + 1.18.22 + + + com.alibaba + fastjson + 1.2.72 + + + cn.hutool + hutool-all + 5.7.12 + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + 0.4.7 + + + com.alipay.sdk + alipay-sdk-java + 4.34.8.ALL + + + + + \ No newline at end of file diff --git a/pay/src/main/java/com/ruoyi/CallBackService.java b/pay/src/main/java/com/ruoyi/CallBackService.java new file mode 100644 index 0000000..29fb770 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/CallBackService.java @@ -0,0 +1,32 @@ +package com.ruoyi; + +/** + * 业务回调处理接口 + */ +public interface CallBackService { + + /** + * 成功支付--处理业务逻辑 + * @param orderSn 订单号 + */ + void successPay(String orderSn); + + /** + * 失败支付-处理业务逻辑 + * @param orderSn 订单号 + */ + void failPay(String orderSn); + + /** + * 退款成功-处理业务逻辑 + * @param orderSn 订单号 + */ + void successRefund(String orderSn); + + /** + * 退款失败-处理业务逻辑 + * @param orderSn 订单号 + */ + void failRefund(String orderSn); + +} diff --git a/pay/src/main/java/com/ruoyi/ElegentPay.java b/pay/src/main/java/com/ruoyi/ElegentPay.java new file mode 100644 index 0000000..e79ae0e --- /dev/null +++ b/pay/src/main/java/com/ruoyi/ElegentPay.java @@ -0,0 +1,66 @@ +package com.ruoyi; + + +import com.ruoyi.dto.*; +import com.ruoyi.exceptions.TradeException; + +public interface ElegentPay { + + + /** + * 统一下单接口 + * @param payRequest 支付请求 + * @param tradeType 交易类型 + * @param platform 平台 + * @return 支付响应 + * @throws TradeException + */ + PayResponse requestPay(PayRequest payRequest, String tradeType, String platform) throws TradeException; + + + /** + * 关闭订单 + * @param orderSn 订单号 + * @param platform 平台 + * @return 是否成功关闭订单 + * @throws TradeException + */ + Boolean closePay(String orderSn, String platform) throws TradeException; + + /** + * 退款 + * @param refundRequest 退款请求封装对象 + * @param platform 平台 + * @return 是否成功退款 + * @throws TradeException + */ + Boolean refund(RefundRequest refundRequest, String platform) throws TradeException; + + /** + * 根据订单号查询订单 + * @param orderSn 订单号 + * @param platform 平台 + * @return 查询响应对象 + * @throws TradeException + */ + QueryResponse queryTradingOrderNo(String orderSn , String platform) throws TradeException; + + + /** + * 查询单笔退款API + * @param orderSn 订单号 + * @param platform 平台 + * @return 查询退款响应对象 + * @throws TradeException + */ + QueryRefundResponse queryRefundTrading(String orderSn , String platform) throws TradeException; + + + /** + * 获得openID + * @param code + * @return + */ + public String getOpenid(String code, String platform); + +} diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java b/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java new file mode 100644 index 0000000..1648dde --- /dev/null +++ b/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java @@ -0,0 +1,40 @@ +package com.ruoyi.ali; + +import com.ruoyi.key.KeyManager; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 支付宝权限对接类 + */ +@Component +@ConfigurationProperties("elegent.pay.alipay") +@Data +public class AlipayConfig { + /** + * 应用识别码 + */ + private String appId; + + /** + * 密钥加密方式 RSA2 + */ + @Value("${elegent.pay.alipay.charset:RSA2}") + private String signType; + + @Autowired + private KeyManager keyManager; + + public String getPrivateKey(){ + return keyManager.getKey("alipay_private.key"); + } + + public String getPublicKey(){ + return keyManager.getKey("alipay_public.key"); + } + + +} \ No newline at end of file diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java b/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java new file mode 100644 index 0000000..db7417d --- /dev/null +++ b/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java @@ -0,0 +1,30 @@ +package com.ruoyi.ali; + +import java.util.HashMap; +import java.util.Map; + +/** + * ZFBConstant + * @description 支付宝相关的常量 +*/ +public class AlipayConstant { + + public static final String SUCCESS = "SUCCESS"; + + public static final String FAIL = "FAIL"; + + /** + * 交易状态(用于转换) + */ + public static final Map TRADE_STATE = new HashMap(){ + { + put("TRADE_SUCCESS", "SUCCESS"); + put("WAIT_BUYER_PAY", "NOTPAY"); + put("TRADE_CLOSED", "CLOSED"); + put("TRADE_FINISHED", "FINISHED"); + } + }; + + public static final String domain="https://openapi.alipay.com/gateway.do"; + +} diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java b/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java new file mode 100644 index 0000000..aefd560 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java @@ -0,0 +1,461 @@ +package com.ruoyi.ali; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.request.*; +import com.alipay.api.response.*; +import com.ruoyi.CallBackService; +import com.ruoyi.annotation.TradePlatform; +import com.ruoyi.config.CallbackConfig; +import com.ruoyi.constant.PayConstant; +import com.ruoyi.constant.Platform; +import com.ruoyi.constant.TradeType; +import com.ruoyi.core.ElegentTrade; +import com.ruoyi.dto.*; +import com.ruoyi.exceptions.TradeException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Map; + +/** + * 支付宝支付的策略类 + * @author wgl + */ +@Service +@TradePlatform(Platform.ALI) +@Slf4j +public class AlipayElegentTrade implements ElegentTrade { + + @Autowired + private AlipayConfig alipayConfig; + + @Autowired + private CallbackConfig callbackConfig; + + @Autowired + private CallBackService callBackService; + + + /** + * 获取回调地址 + * @return + */ + private String getPayNotifyUrl(){ + return callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH+ PayConstant.NOTIFY +"/"+ Platform.ALI; + } + + /** + * 获取退款回调 + * @return + */ + private String getRefundNotifyUrl(){ + return callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH+ PayConstant.REFUND_NOTIFY +"/"+ Platform.ALI; + } + + + + /** + * 创建支付订单 + * @param payRequest + * @return + * @throws TradeException + */ + @Override + public PayResponse requestPay(PayRequest payRequest, String tradeType) throws TradeException { + if(TradeType.NATIVE.equals( tradeType )){ + return createNativeOrder(payRequest); + } + if(TradeType.JSAPI.equals( tradeType )){ + return createJsApiOrder(payRequest); + } + if(TradeType.H5.equals( tradeType )){ + return createH5Order(payRequest); + } + if(TradeType.APP.equals( tradeType )){ + return createAPPOrder(payRequest); + } + return createNativeOrder(payRequest); + } + + + /** + * 本地支付(扫码) + * https://opendocs.alipay.com/open/194/106078?ref=api#预下单 + * @param payRequest + * @return + * @throws TradeException + */ + private PayResponse createNativeOrder(PayRequest payRequest) throws TradeException { + try { + AlipayClient alipayClient = getAliHttpClient(); + AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); + + request.setNotifyUrl(getPayNotifyUrl()); + + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", payRequest.getOrderSn()); + //转换 + //String totalFee= BigDecimal.valueOf(payRequest.getTotalFee()).divide(new BigDecimal(100) ).toString(); + bizContent.put("total_amount", fenToYuan(payRequest.getTotalFee())); + bizContent.put("subject", payRequest.getBody()); + request.setBizContent(bizContent.toString()); + AlipayTradePrecreateResponse response = alipayClient.execute(request); + + if (response.isSuccess()) { + PayResponse payResponse =new PayResponse(); + payResponse.setSuccess(true); + payResponse.setCode_url(response.getQrCode()); //本地支付二维码 + payResponse.setOrder_sn(payRequest.getOrderSn()); + return payResponse; + } else { + log.error("调用失败"); + return null; + } + }catch (Exception e){ + e.printStackTrace(); + throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn()); + } + } + + + /** + * 小程序 + * https://opendocs.alipay.com/mini/03l5wn + * @param payRequest + * @return + * @throws TradeException + */ + private PayResponse createJsApiOrder(PayRequest payRequest) throws TradeException { + AlipayClient alipayClient = getAliHttpClient(); + try { + AlipayTradeCreateRequest request = new AlipayTradeCreateRequest(); + request.setNotifyUrl(getPayNotifyUrl()); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", payRequest.getOrderSn()); + bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() )); + bizContent.put("subject", payRequest.getBody()); + bizContent.put("buyer_id", payRequest.getOpenid()); + bizContent.put("timeout_express", "10m"); + request.setBizContent(bizContent.toString()); + AlipayTradeCreateResponse response = alipayClient.sdkExecute(request); + if (response.isSuccess()) { + PayResponse payResponse =new PayResponse(); + payResponse.setSuccess(true); + payResponse.setPrepay_id(response.getTradeNo()); + payResponse.setOrder_sn(response.getOutTradeNo()); + return payResponse; + } else { + log.error("调用失败"); + return null; + } + }catch (Exception e){ + throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn()); + } + } + + + /** + * H5 + * https://opendocs.alipay.com/mini/03l5wn + * @param payRequest + * @return + * @throws TradeException + */ + private PayResponse createH5Order(PayRequest payRequest) throws TradeException { + AlipayClient alipayClient = getAliHttpClient(); + try { + AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); + request.setNotifyUrl(getPayNotifyUrl()); + request.setReturnUrl(""); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", payRequest.getOrderSn()); + bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() )); + bizContent.put("subject", payRequest.getBody()); + bizContent.put("product_code", "QUICK_WAP_WAY"); + + request.setBizContent(bizContent.toString()); + AlipayTradeWapPayResponse response = alipayClient.pageExecute(request); + if (response.isSuccess()) { + PayResponse payResponse =new PayResponse(); + payResponse.setSuccess(true); + payResponse.setPrepay_id(response.getTradeNo()); + payResponse.setOrder_sn(response.getOutTradeNo()); + return payResponse; + } else { + log.error("调用失败"); + return null; + } + }catch (Exception e){ + throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn()); + } + } + + + /** + * APP + * https://opendocs.alipay.com/open/02e7gq?ref=api&scene=20 + * @param payRequest + * @return + * @throws TradeException + */ + private PayResponse createAPPOrder(PayRequest payRequest) throws TradeException { + AlipayClient alipayClient = getAliHttpClient(); + try { + AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); + request.setNotifyUrl(getPayNotifyUrl()); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", payRequest.getOrderSn()); + bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() )); + bizContent.put("subject", payRequest.getBody()); + bizContent.put("product_code", "QUICK_MSECURITY_PAY"); + + request.setBizContent(bizContent.toString()); + AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); + if (response.isSuccess()) { + PayResponse payResponse =new PayResponse(); + payResponse.setSuccess(true); + payResponse.setPrepay_id(response.getTradeNo()); + payResponse.setOrder_sn(response.getOutTradeNo()); + return payResponse; + } else { + log.error("调用失败"); + return null; + } + }catch (Exception e){ + throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn()); + } + } + + + + /** + * 关闭订单 + * @param orderSn + * @return + * @throws TradeException + */ + @Override + public Boolean closePay(String orderSn) throws TradeException { + try { + AlipayClient alipayClient = getAliHttpClient(); + AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); + JSONObject bizContent = new JSONObject(); + bizContent.put("trade_no", orderSn); + request.setBizContent(bizContent.toString()); + AlipayTradeCloseResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + log.info("调用成功"); + return true; + } else { + log.error("调用失败"); + return false; + } + }catch (Exception e){ + throw new TradeException("订单关闭失败,订单号:"+orderSn); + } + } + + /** + * 退款接口 + * alipay.trade.refund(统一收单交易退款接口) + * https://opendocs.alipay.com/open/02ekfk + * @param refundRequest + * @return + * @throws TradeException + */ + @Override + public Boolean refund(RefundRequest refundRequest) throws TradeException { + try { + AlipayClient alipayClient = getAliHttpClient(); + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + request.setNotifyUrl(getRefundNotifyUrl()); //退款回调 + JSONObject bizContent = new JSONObject(); + bizContent.put("refund_amount", fenToYuan(refundRequest.getRefundAmount() )); + bizContent.put("out_trade_no", refundRequest.getOrderSn()); + //退款请求号,做幂等性校验 + if(refundRequest.getRequestNo()!=null){ + bizContent.put("out_request_no", refundRequest.getRequestNo()); + }else{ + bizContent.put("out_request_no", refundRequest.getOrderSn()); + } + request.setBizContent(bizContent.toString()); + AlipayTradeRefundResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + if("Y".equals(response.getFundChange())) { + log.info("退款成功{}",refundRequest.getOrderSn()); + callBackService.successRefund(refundRequest.getOrderSn()); + return true; + }else{ + //退款失败 + log.error("退款失败{}",refundRequest.getOrderSn()); + callBackService.failRefund(refundRequest.getOrderSn()); + return false; + } + } else { + log.error("退款调用失败{}",refundRequest.getOrderSn()); + return false; + } + }catch (Exception e){ + e.printStackTrace(); + throw new TradeException("订单退款失败,订单号:"+ refundRequest.getOrderSn()); + } + } + + /** + * 查询单笔交易订单 + * 参考官网: https://opendocs.alipay.com/open/02e7gm?ref=api#请求示例 + * + * @param orderSn + * @return + * @throws TradeException + */ + @Override + public QueryResponse queryTradingOrderNo(String orderSn) throws TradeException { + AlipayClient alipayClient = getAliHttpClient(); + try { + AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", orderSn); + request.setBizContent(bizContent.toString()); + AlipayTradeQueryResponse response = alipayClient.execute(request); + QueryResponse queryResponse=new QueryResponse(); + queryResponse.setOrder_sn(orderSn ); + if (response.isSuccess()) { + queryResponse.setTransaction_id( response.getTradeNo() ); + queryResponse.setTrade_state(AlipayConstant.TRADE_STATE.get( response.getTradeStatus()) );//交易状态 + + //int total = BigDecimal.valueOf(Double.valueOf(response.getTotalAmount())).multiply(new BigDecimal(100)).intValue(); + queryResponse.setTotal( yuanToFen(response.getTotalAmount()) ); //总金额 + + //int buyer_pay_amount = BigDecimal.valueOf(Double.valueOf(response.getBuyerPayAmount())).multiply(new BigDecimal(100)).intValue(); + //queryResponse.setPayer_total( yuanToFen(response.getBuyerPayAmount()) );//支付金额 + + queryResponse.setOpenid( response.getBuyerUserId()); + Map map = JSON.parseObject(response.getBody(), Map.class ) ; + queryResponse.setExpand(map);//全部数据 + return queryResponse; + } else { + queryResponse.setTrade_state("NOTPAY"); + return queryResponse; + } + }catch (Exception e){ + e.printStackTrace(); + //throw new TradeException("订单查询失败,订单号:"+orderSn); + return null; + } + } + + /** + * 查询退款订单 + * @param orderSn + * @return + * @throws TradeException + */ + @Override + public QueryRefundResponse queryRefundTrading(String orderSn) throws TradeException { + try { + AlipayClient alipayClient = getAliHttpClient(); + AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest(); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_request_no", orderSn); + request.setBizContent(bizContent.toString()); + AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + log.info("调用成功"); + Map map = JSON.parseObject(response.getBody(), Map.class ); + + QueryRefundResponse queryRefundResponse=new QueryRefundResponse(); + + queryRefundResponse.setOrder_sn( (String) map.get("out_trade_no") ); + queryRefundResponse.setTransaction_id( (String) map.get("trade_no") ); + queryRefundResponse.setTotal( (Integer) map.get("total_amount") ); //总金额 + //queryRefundResponse.setPayer_total( (Integer) map.get("total_amount") );//支付金额 + queryRefundResponse.setRefund((Integer) map.get("refund_amount") ); //退款金额 + queryRefundResponse.setRefund_id((String) map.get("trade_no") ); //退款单号 + queryRefundResponse.setOut_refund_no( (String) map.get("out_request_no") );//退款订单号 + //queryRefundResponse.setChannel( (String) map.get("channel") ); //通道 + //queryRefundResponse.setUser_received_account( (String) map.get("user_received_account") ); //账号 + queryRefundResponse.setStatus( (String) map.get("refund_status") ); //状态 + queryRefundResponse.setSuccess_time( (String) map.get("gmt_refund_pay") ); + //queryRefundResponse.setCreate_time( (String) map.get("gmt_refund_pay") ); + + queryRefundResponse.setExpand(map); + return queryRefundResponse; + + } else { + log.error("调用失败"); + return null; + } + }catch (Exception e){ + e.printStackTrace(); + //throw new TradeException("退款订单查询失败,订单号:"+ orderSn); + return null; + } + } + + @Override + public String getOpenid(String code) { + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", + alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "utf-8", alipayConfig.getPublicKey(), alipayConfig.getSignType()); + AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest(); + request.setCode(code); + request.setGrantType("authorization_code"); + try { + AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request); + return oauthTokenResponse.getUserId(); + } catch (AlipayApiException e) { + //处理异常 + e.printStackTrace(); + return ""; + } + } + + + /** + * 获取支付宝连接 + * 参考官网:https://opendocs.alipay.com/open/01csp3?ref=api#公钥模式加签 + * 公钥模式加签 + * @return + */ + private AlipayClient getAliHttpClient(){ + try { + com.alipay.api.AlipayConfig alipayConfig = new com.alipay.api.AlipayConfig(); + alipayConfig.setServerUrl(AlipayConstant.domain); + alipayConfig.setAppId(this.alipayConfig.getAppId()); + alipayConfig.setPrivateKey(this.alipayConfig.getPrivateKey()); + alipayConfig.setFormat("json"); + alipayConfig.setCharset("utf-8"); + alipayConfig.setAlipayPublicKey(this.alipayConfig.getPublicKey()); + alipayConfig.setSignType(this.alipayConfig.getSignType()); + //构造client + AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig); + return alipayClient; + }catch (Exception e){ + e.printStackTrace(); + throw new TradeException("支付宝支付--初始化,校验系统参数失败"); + } + + } + + /** + * 分转换为元 + * @param fen + * @return + */ + private String fenToYuan(int fen){ + //转换为元 + return BigDecimal.valueOf(fen).divide(new BigDecimal(100) ).toString(); + } + + private int yuanToFen(String yuan){ + return BigDecimal.valueOf(Double.valueOf(yuan)).multiply(new BigDecimal(100)).intValue(); + } + + +} \ No newline at end of file diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java b/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java new file mode 100644 index 0000000..0052a4f --- /dev/null +++ b/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java @@ -0,0 +1,124 @@ +package com.ruoyi.ali; + + +import com.alipay.api.internal.util.AlipaySignature; +import com.ruoyi.annotation.TradePlatform; +import com.ruoyi.constant.Platform; +import com.ruoyi.core.ElegentValid; +import com.ruoyi.dto.ValidResponse; +import com.ruoyi.exceptions.TradeException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@Service +@TradePlatform(Platform.ALI) +@Slf4j +public class AlipayElegentValid implements ElegentValid { + + + @Autowired + private AlipayConfig alipayConfig; + + + /** + * 订单回调结果通知验签 + * 参考代码: https://opendocs.alipay.com/open/194/103296?ref=api 异步返回结果的验签 + * @param httpEntity + * @param httpRequest + * @return + */ + @Override + public ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest httpRequest) throws TradeException { + ValidResponse validResponse=new ValidResponse(); + try { + Map params = getParams(httpRequest); + //获取支付宝POST过来反馈信息,将异步通知中收到的待验证所有参数都存放到map中 + //String body = httpEntity.getBody(); + //调用SDK验证签名 + //公钥验签示例代码 + boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getPublicKey(), "utf-8", alipayConfig.getSignType()); + if (signVerified) { + validResponse.setValid(true); + validResponse.setOrderSn((String) params.get("out_trade_no")); + return validResponse; + } else { + validResponse.setValid(false); + validResponse.setOrderSn( (String) params.get("out_trade_no") ); + return validResponse; + } + }catch (Exception e){ + e.printStackTrace(); + throw new TradeException("验签异常"); + } + } + + /** + * 退款结果通知验签 + * 参考官网 https://opendocs.alipay.com/support/01ravh + * @param httpEntity + * @param httpRequest + * @return + * @throws TradeException + */ + @Override + public ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest httpRequest) throws TradeException { + ValidResponse validResponse=new ValidResponse(); + + try { + //获取支付宝POST过来反馈信息,将异步通知中收到的待验证所有参数都存放到map中 + Map params = getParams(httpRequest); + //调用SDK验证签名 + //公钥验签示例代码 + boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getPublicKey(), "utf-8", alipayConfig.getSignType()); + if (signVerified) { + validResponse.setValid(true); + validResponse.setOrderSn( (String) params.get("out_trade_no") ); + return validResponse; + } else { + validResponse.setValid(false); + validResponse.setOrderSn( (String) params.get("out_trade_no") ); + return validResponse; + } + }catch (Exception e){ + e.printStackTrace(); + validResponse.setValid(false); + return validResponse; + } + } + + private Map getParams(HttpServletRequest httpServletRequest){ + Map params = new HashMap< String , String >(); + Map requestParams = httpServletRequest.getParameterMap(); + + for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){ + String name = (String)iter.next(); + String[] values = (String [])requestParams.get(name); + String valueStr = ""; + for(int i = 0;i < values.length;i ++ ){ + valueStr = (i==values.length-1)?valueStr + values [i]:valueStr + values[i] + ","; + } + //乱码解决,这段代码在出现乱码时使用。 + //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); + params.put (name,valueStr); + } + log.info("params:{}",params); + return params; + } + + @Override + public String successResult() { + return AlipayConstant.SUCCESS; + } + + @Override + public String failResult() { + return AlipayConstant.FAIL; + } +} diff --git a/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java b/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java new file mode 100644 index 0000000..3cb71be --- /dev/null +++ b/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java @@ -0,0 +1,20 @@ +package com.ruoyi.annotation; + +import java.lang.annotation.*; + +/** + * create by: wgl + * desc: 自定义支付平台注解,支付平台 微信:wx 支付宝:zfb + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface TradePlatform { + + /** + * 平台的id + * Platform.WX + * @return + */ + String value(); +} diff --git a/pay/src/main/java/com/ruoyi/config/CallbackConfig.java b/pay/src/main/java/com/ruoyi/config/CallbackConfig.java new file mode 100644 index 0000000..2c656ee --- /dev/null +++ b/pay/src/main/java/com/ruoyi/config/CallbackConfig.java @@ -0,0 +1,23 @@ +package com.ruoyi.config; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 微信权限对接类 + */ +@Component +@ConfigurationProperties("elegent.pay.callback") +@Data +public class CallbackConfig { + + private String domain; //回调域名 + + @Value("${elegent.pay.callback.watch:false}") + private boolean watch; //是否开启监听 + + @Value("${elegent.pay.callback.cycle:10}") + private int cycle;//检查周期 + +} \ No newline at end of file diff --git a/pay/src/main/java/com/ruoyi/constant/PayConstant.java b/pay/src/main/java/com/ruoyi/constant/PayConstant.java new file mode 100644 index 0000000..77695ce --- /dev/null +++ b/pay/src/main/java/com/ruoyi/constant/PayConstant.java @@ -0,0 +1,11 @@ +package com.ruoyi.constant; + +public class PayConstant { + + public final static String CALLBACK_PATH = "/payCallBack"; + + public final static String NOTIFY = "/notify"; + + public final static String REFUND_NOTIFY = "/refund_notify"; + +} diff --git a/pay/src/main/java/com/ruoyi/constant/Platform.java b/pay/src/main/java/com/ruoyi/constant/Platform.java new file mode 100644 index 0000000..fd9a8d9 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/constant/Platform.java @@ -0,0 +1,16 @@ +package com.ruoyi.constant; + +/** + * Platform + * 支付方式 +*/ +public class Platform { + /** + * 微信 + */ + public final static String WX = "wxpay"; + /** + * 支付宝 + */ + public final static String ALI = "alipay"; +} diff --git a/pay/src/main/java/com/ruoyi/constant/TradeType.java b/pay/src/main/java/com/ruoyi/constant/TradeType.java new file mode 100644 index 0000000..c0a7ace --- /dev/null +++ b/pay/src/main/java/com/ruoyi/constant/TradeType.java @@ -0,0 +1,33 @@ +package com.ruoyi.constant; + +import lombok.Data; + +/** + * 交易类型 + */ +@Data +public class TradeType { + + /** + * native(扫码) + */ + public final static String NATIVE = "native"; + + /** + * jsapi(小程序) + */ + public final static String JSAPI = "jsapi"; + + + /** + * app + */ + public final static String APP = "app"; + + + /** + * h5 + */ + public final static String H5 = "h5"; + +} diff --git a/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java b/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java new file mode 100644 index 0000000..ea0148d --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java @@ -0,0 +1,35 @@ +package com.ruoyi.core; + +import com.ruoyi.CallBackService; +import lombok.extern.slf4j.Slf4j; + +/** + * 回调类 + */ +@Slf4j +public class CallBackServiceImpl implements CallBackService { + + + @Override + public void successPay(String orderSn) { + log.info("支付成功回调!"+orderSn); + } + + @Override + public void failPay(String orderSn) { + log.info("支付失败回调!"+orderSn); + } + + + @Override + public void successRefund(String orderSn) { + log.info("退款成功回调!"+orderSn); + } + + @Override + public void failRefund(String orderSn) { + log.info("退款失败回调!"+orderSn); + } + + +} diff --git a/pay/src/main/java/com/ruoyi/core/CallbackController.java b/pay/src/main/java/com/ruoyi/core/CallbackController.java new file mode 100644 index 0000000..8b7170f --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/CallbackController.java @@ -0,0 +1,90 @@ +package com.ruoyi.core; + +import com.ruoyi.CallBackService; +import com.ruoyi.constant.PayConstant; +import com.ruoyi.dto.ValidResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * CallbackController + * @description 系统默认提供的微信回调的Controller +*/ +@RestController +@Slf4j +@RequestMapping(PayConstant.CALLBACK_PATH) +public class CallbackController { + + @Autowired + private CallBackService callBackService; + + /** + * 系统提供的默认的微信回调的接口(支付回调) + * @param httpEntity + * @param response + * @return + */ + @RequestMapping( PayConstant.NOTIFY + "/{platform}") + public String notify(HttpEntity httpEntity, HttpServletRequest request, HttpServletResponse response, @PathVariable("platform") String platform){ + + ElegentValid elegentValid = ElegentLoader.getElegentValid(platform); //获取验证器 + try { + ValidResponse validResponse = elegentValid.validPay(httpEntity, request);//验证支付通知 + String orderSn =validResponse.getOrderSn(); //订单号 + if(validResponse.isValid()){ //返回码成功 + callBackService.successPay(orderSn); + //返回成功消费 + return elegentValid.successResult(); + }else{ + callBackService.failPay(orderSn); + return elegentValid.failResult(); + } + }catch (Exception e){ + log.error("支付回调处理失败",e); + //微信返回的状态非正常 + return elegentValid.failResult(); + } + } + + + /** + * 系统提供的默认的微信回调的接口(退款通知) + * + * @param httpEntity + * @param response + * @return + */ + @RequestMapping( PayConstant.REFUND_NOTIFY + "/{platform}") + public String refundNotify(HttpEntity httpEntity, HttpServletRequest request, HttpServletResponse response,@PathVariable("platform") String platform) { + + ElegentValid elegentValid = ElegentLoader.getElegentValid(platform); //获取验证器 + + try { + ValidResponse validResponse = elegentValid.validRefund(httpEntity, request); + String orderSn = validResponse.getOrderSn(); + //订单号 + if (validResponse.isValid()) { //返回码成功 + callBackService.successRefund(orderSn); + //返回成功消费 + return elegentValid.successResult(); + } else { + callBackService.failRefund(orderSn); + return elegentValid.failResult(); + } + } catch (Exception e) { + log.error("退款回调处理失败", e); + //微信返回的状态非正常 + return elegentValid.failResult(); + } + + } + + +} diff --git a/pay/src/main/java/com/ruoyi/core/CallbackWatch.java b/pay/src/main/java/com/ruoyi/core/CallbackWatch.java new file mode 100644 index 0000000..5bfe85e --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/CallbackWatch.java @@ -0,0 +1,73 @@ +package com.ruoyi.core; + + + +import com.ruoyi.CallBackService; +import com.ruoyi.ElegentPay; +import com.ruoyi.config.CallbackConfig; +import com.ruoyi.dto.QueryRefundResponse; +import com.ruoyi.dto.QueryResponse; +import com.ruoyi.dto.WatchDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; +import java.util.Timer; +import java.util.TimerTask; + +@Component +@ConditionalOnProperty(prefix = "elegent.pay.callback",name = "watch",havingValue = "true") +@Slf4j +public class CallbackWatch { + + @Autowired + private CallBackService callBackService; + + @Autowired + private CallbackConfig callbackConfig; + + @Autowired + private ElegentPay elegentPay; + + @PostConstruct + public void queryWatch(){ + if(callbackConfig.getCycle()<=0){ + return; + } + //log.info("开启支付结果定期巡检"); + Timer timer = new Timer(); + // 2、创建 TimerTask 任务线程 + TimerTask task=new TimerTask() { + @Override + public void run() { + try{ + //查询支付状态 + //log.info("支付状态定期巡检,{}",WatchList.payList); + for( WatchDTO watchDTO: WatchList.payList ){ + //查询订单是否支付成功 + QueryResponse queryResponse = elegentPay.queryTradingOrderNo(watchDTO.getOrderSn(),watchDTO.getPlatform()); + if("SUCCESS".equals(queryResponse.getTrade_state())){ + callBackService.successPay(queryResponse.getOrder_sn()); + WatchList.payList.remove(watchDTO ); + } + } + //log.info("退款状态定期巡检,{}",WatchList.refundList); + //查询退款状态 + for( WatchDTO watchDTO: WatchList.refundList ){ + //查询退款中订单 + QueryRefundResponse queryResponse = elegentPay.queryRefundTrading( watchDTO.getOrderSn(),watchDTO.getPlatform()); + if("SUCCESS".equals(queryResponse.getStatus())){ + callBackService.successRefund(queryResponse.getOrder_sn()); + WatchList.refundList.remove(watchDTO); + } + } + }catch (Exception ex){ + } + } + }; + // 4、启动定时任务 + timer.schedule(task, callbackConfig.getCycle()*1000, callbackConfig.getCycle()*1000); + } + +} diff --git a/pay/src/main/java/com/ruoyi/core/ElegentConfig.java b/pay/src/main/java/com/ruoyi/core/ElegentConfig.java new file mode 100644 index 0000000..34cde57 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/ElegentConfig.java @@ -0,0 +1,27 @@ +package com.ruoyi.core; + + +import com.ruoyi.CallBackService; +import com.ruoyi.key.KeyManager; +import com.ruoyi.key.impl.DefaultKeyManager; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ElegentConfig { + + @Bean + @ConditionalOnMissingBean + public CallBackService callBackService(){ + return new CallBackServiceImpl(); + } + + + @Bean + @ConditionalOnMissingBean + public KeyManager keyManager(){ + return new DefaultKeyManager(); + } + +} diff --git a/pay/src/main/java/com/ruoyi/core/ElegentLoader.java b/pay/src/main/java/com/ruoyi/core/ElegentLoader.java new file mode 100644 index 0000000..36dcb8b --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/ElegentLoader.java @@ -0,0 +1,82 @@ +package com.ruoyi.core; + +import com.ruoyi.annotation.TradePlatform; +import com.ruoyi.exceptions.TradeException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * PlatformLoader + * @description 第三方支付平台类加载器 + * 服务启动的时候自动加载第三方支付组件 +*/ +@Component +@Slf4j +public class ElegentLoader implements ApplicationContextAware { + + private static Map elegentTradeMap = new HashMap<>(); + + private static Map elegentValidMap = new HashMap<>(); + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + + //加载所有的交易实现类 + Collection elegentTrades = applicationContext.getBeansOfType(ElegentTrade.class).values(); + elegentTrades.stream().forEach(e->{ + //通过反射拿到类上的平台注解 + TradePlatform annotation = e.getClass().getAnnotation(TradePlatform.class); + if (annotation != null) { + elegentTradeMap.put(annotation.value(), e); + } + }); + + //加载所有的验证实现类 + Collection elegentValids = applicationContext.getBeansOfType(ElegentValid.class).values(); + elegentValids.stream().forEach(e->{ + //通过反射拿到类上的平台注解 + TradePlatform annotation = e.getClass().getAnnotation(TradePlatform.class); + if (annotation != null) { + elegentValidMap.put(annotation.value(), e); + } + }); + + } + + /** + * 根据平台id获取具体的第三方平台 + * @param platform 平台id + * @return + */ + public static ElegentTrade getElegentTrade(String platform){ + ElegentTrade elegentPayTemplate = elegentTradeMap.get(platform); + if(elegentPayTemplate!=null){ + return elegentPayTemplate; + }else{ + throw new TradeException("未找到适配的交易类型,交易平台id:"+platform); + } + } + + + /** + * 根据平台id获取具体的验证类 + * @param platform 平台id + * @return + */ + public static ElegentValid getElegentValid(String platform){ + ElegentValid elegentValidTemplate = elegentValidMap.get(platform); + if(elegentValidTemplate!=null){ + return elegentValidTemplate; + }else{ + throw new TradeException("未找到适配的交易类型,交易平台id:"+platform); + } + } + +} diff --git a/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java b/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java new file mode 100644 index 0000000..97f84d2 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java @@ -0,0 +1,136 @@ +package com.ruoyi.core; +import com.ruoyi.ElegentPay; +import com.ruoyi.config.CallbackConfig; +import com.ruoyi.dto.*; +import com.ruoyi.exceptions.TradeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * ElegentPayTemplate + * @description 统一模板 在模板层进行第三方平台的选择 +*/ +@Component +public class ElegentPayImpl implements ElegentPay { + + @Autowired + private CallbackConfig callbackConfig; + + /** + * 统一下单接口 + * @param payRequest + * @return + */ + @Override + public PayResponse requestPay(PayRequest payRequest, String tradeType, String platform) throws TradeException { + //获取交易策略 + PayResponse payResponse = getPlatFormService(platform).requestPay(payRequest, tradeType); + + //加入监听列表 + if(callbackConfig.isWatch()){ + WatchDTO watchDTO=new WatchDTO(); + watchDTO.setOrderSn(payRequest.getOrderSn()); + watchDTO.setPlatform(platform); + WatchList.payList.add( watchDTO ); + } + return payResponse; + } + + + /** + * 关闭订单 + * @param orderSn + * @param platform + * @return + * @throws Exception + */ + @Override + public Boolean closePay(String orderSn, String platform) throws TradeException { + //调用对应第三方的创建订单接口 + Boolean aBoolean = getPlatFormService(platform).closePay(orderSn); + //加入监听列表 + if(callbackConfig.isWatch()){ + WatchDTO watchDTO=new WatchDTO(); + watchDTO.setOrderSn(orderSn); + watchDTO.setPlatform(platform); + WatchList.payList.remove( watchDTO ); + } + + return aBoolean; + } + + /** + * 退款方法 + * @param refundRequest + * @return + * @throws Exception + */ + @Override + public Boolean refund(RefundRequest refundRequest, String platform) throws TradeException { + Boolean refund = getPlatFormService(platform).refund(refundRequest); + //加入监听列表 + if(callbackConfig.isWatch() && refund){ + WatchDTO watchDTO=new WatchDTO(); + watchDTO.setOrderSn(refundRequest.getRequestNo()); + watchDTO.setPlatform(platform); + WatchList.refundList.add( watchDTO ); + } + return refund; + } + + + /** + * 手动查询订单的方法 + * 商户订单号查询 根据订单号查询订单 + * 该接口基于生成的订单号来进行订单的查询 + * 可以基于查询的结果判断用户订单是否支付成功 + * @param orderSn + * @param Platform + * @return + * @throws Exception + */ + @Override + public QueryResponse queryTradingOrderNo(String orderSn , String Platform) throws TradeException { + //调用具体第三方的退款接口 + return getPlatFormService(Platform).queryTradingOrderNo(orderSn); + } + + + /** + * 查询退款单号 + * + * @return + * @throws Exception + */ + @Override + public QueryRefundResponse queryRefundTrading(String orderSn , String platform) throws TradeException { + //获取请求参数 + return getPlatFormService(platform).queryRefundTrading(orderSn); + } + + /** + * 获得openId + * @param code + * @param platform + * @return + */ + @Override + public String getOpenid(String code, String platform) { + return getPlatFormService(platform).getOpenid(code); + } + +/** + * ====================================提供的模板类需要使用的方法===================================== + */ + + + /** + * 跟进具体内容获取实现类的方法 + * @param platForm + * @return + */ + private ElegentTrade getPlatFormService(String platForm) { + return ElegentLoader.getElegentTrade(platForm); + } + +} diff --git a/pay/src/main/java/com/ruoyi/core/ElegentTrade.java b/pay/src/main/java/com/ruoyi/core/ElegentTrade.java new file mode 100644 index 0000000..4474da3 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/ElegentTrade.java @@ -0,0 +1,54 @@ +package com.ruoyi.core; + + +import com.ruoyi.dto.*; +import com.ruoyi.exceptions.TradeException; + +public interface ElegentTrade { + + + /** + * 单独的创建本地支付订单接口 + * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk + * 业务编写人员仅仅只需要准备好请求参数调用该方法即可完成下单请求 + * @return 交易数据对象 包含有native支付的二维码+jsApi支付的支付组件 + */ + PayResponse requestPay(PayRequest payRequest, String tradeType) throws TradeException; + + /** + * 关闭订单 + * 该结构基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk + * 业务编写人员在处理超时订单的时候需要 通知微信 由于是超时订单需要进行远程关闭 + */ + Boolean closePay(String orderSn) throws TradeException; + + /** + * 退款s申请 + * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk + * 业务编写人员在处理业务执行失败时需要进行退款 + */ + Boolean refund(RefundRequest refundRequest) throws TradeException; + + /** + * 商户订单号查询 根据订单号查询订单 + * 该接口基于生成的订单号来进行订单的查询 + * 可以基于查询的结果判断用户订单是否支付成功 + */ + QueryResponse queryTradingOrderNo(String orderSn) throws TradeException; + + + /** + * 查询单笔退款API + * + */ + QueryRefundResponse queryRefundTrading(String orderSn) throws TradeException; + + + /** + * 获得openId + * @param code + * @return + */ + String getOpenid(String code); + +} diff --git a/pay/src/main/java/com/ruoyi/core/ElegentValid.java b/pay/src/main/java/com/ruoyi/core/ElegentValid.java new file mode 100644 index 0000000..fdb7cd5 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/ElegentValid.java @@ -0,0 +1,48 @@ +package com.ruoyi.core; + + +import com.ruoyi.dto.ValidResponse; +import com.ruoyi.exceptions.TradeException; +import org.springframework.http.HttpEntity; + +import javax.servlet.http.HttpServletRequest; + +/** + * 验证器接口 + * + */ +public interface ElegentValid { + + + /** + * 支付结果通知校验 + * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk + * 业务编写人员在接收到微信或支付宝回调的时候可以使用该方法验证回调是否成功,是否是伪回调 + * @return 交易数据对象 + */ + ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest request) throws TradeException; + + + + /** + * 退款结果通知校验 + * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk + * 业务编写人员在接收到微信或支付宝回调的时候可以使用该方法验证回调是否成功,是否是伪回调 + */ + ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest request) throws TradeException; + + + /** + * 成功返回结构 + * @return + */ + String successResult(); + + + /** + * 失败返回内容 + * @return + */ + String failResult(); + +} diff --git a/pay/src/main/java/com/ruoyi/core/WatchList.java b/pay/src/main/java/com/ruoyi/core/WatchList.java new file mode 100644 index 0000000..a610939 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/core/WatchList.java @@ -0,0 +1,20 @@ +package com.ruoyi.core; + + + +import com.ruoyi.dto.WatchDTO; + +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * 监听列表 + */ +public class WatchList { + + + + public static CopyOnWriteArraySet payList=new CopyOnWriteArraySet<>(); //支付中列表 + + public static CopyOnWriteArraySet refundList=new CopyOnWriteArraySet<>(); //退款中列表 + +} diff --git a/pay/src/main/java/com/ruoyi/dto/PayRequest.java b/pay/src/main/java/com/ruoyi/dto/PayRequest.java new file mode 100644 index 0000000..5d747da --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/PayRequest.java @@ -0,0 +1,20 @@ +package com.ruoyi.dto; + + +import lombok.Data; + +/** + * PayRequest + * 支付请求外观类 +*/ +@Data +public class PayRequest { + + private String body;//商品描述 + + private String orderSn; //订单号 + + private int totalFee; //订单金额 + + private String openid;//openId +} diff --git a/pay/src/main/java/com/ruoyi/dto/PayResponse.java b/pay/src/main/java/com/ruoyi/dto/PayResponse.java new file mode 100644 index 0000000..db4aafb --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/PayResponse.java @@ -0,0 +1,29 @@ +package com.ruoyi.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * 结果统一封装类 + */ +@Data +public class PayResponse { + + private boolean success; //是否成功 + + private String message;//信息 + + private String order_sn;//订单编号 + + private Map expand;//扩展属性 + + private String code_url;//二维码连接(native返回) + + private String prepay_id;//预支付Id(小程序返回) + + private String h5_url;//支付跳转链接 + + private Map jsapiData;//小程序返回 + +} diff --git a/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java b/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java new file mode 100644 index 0000000..d938f63 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java @@ -0,0 +1,24 @@ +package com.ruoyi.dto; + +import lombok.Data; + +@Data +public class QueryRefundResponse extends QueryResponse{ + + + private String refund_id; //微信支付退款单号 + + private String out_refund_no;//商户退款单号 + + private String channel;//退款渠道 + + private String user_received_account;//退款账号 + + private String success_time;//退款成功时间 + + private String status;//退款状态 + + private int refund;//退款金额 + + +} diff --git a/pay/src/main/java/com/ruoyi/dto/QueryResponse.java b/pay/src/main/java/com/ruoyi/dto/QueryResponse.java new file mode 100644 index 0000000..04ddb70 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/QueryResponse.java @@ -0,0 +1,25 @@ +package com.ruoyi.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * 查询响应对象 + */ +@Data +public class QueryResponse { + + private String openid;//用户id + + private String trade_state;//交易状态 + + private String order_sn;//订单号 + + private String transaction_id;//交易单号 + + private int total;//金额 + + private Map expand;//扩展(全部的返回数据) + +} diff --git a/pay/src/main/java/com/ruoyi/dto/RefundRequest.java b/pay/src/main/java/com/ruoyi/dto/RefundRequest.java new file mode 100644 index 0000000..3f17046 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/RefundRequest.java @@ -0,0 +1,16 @@ +package com.ruoyi.dto; + +import lombok.Data; + +@Data +public class RefundRequest { + + private int totalFee; //订单金额 + + private int refundAmount; //退款金额 + + private String orderSn; //订单号 + + private String requestNo; //退款请求号,做退款幂等性校验,当部分退款时必须给出 + +} diff --git a/pay/src/main/java/com/ruoyi/dto/ValidResponse.java b/pay/src/main/java/com/ruoyi/dto/ValidResponse.java new file mode 100644 index 0000000..f8e3973 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/ValidResponse.java @@ -0,0 +1,15 @@ +package com.ruoyi.dto; + +import lombok.Data; + +/** + * 验证签名 + */ +@Data +public class ValidResponse { + + private boolean isValid;// 是否通过验签 + + private String orderSn;// 订单号 + +} diff --git a/pay/src/main/java/com/ruoyi/dto/WatchDTO.java b/pay/src/main/java/com/ruoyi/dto/WatchDTO.java new file mode 100644 index 0000000..7411b91 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/dto/WatchDTO.java @@ -0,0 +1,12 @@ +package com.ruoyi.dto; + +import lombok.Data; + +@Data +public class WatchDTO { + + private String orderSn; //订单号 + + private String platform;//平台 + +} diff --git a/pay/src/main/java/com/ruoyi/exceptions/TradeException.java b/pay/src/main/java/com/ruoyi/exceptions/TradeException.java new file mode 100644 index 0000000..3a82860 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/exceptions/TradeException.java @@ -0,0 +1,24 @@ +package com.ruoyi.exceptions; + +import lombok.Getter; +import lombok.Setter; + +/** + * 交易SDK提供的总的异常 + */ +@Getter +@Setter +public class TradeException extends RuntimeException{ + private String code; + private String msg; + + public TradeException(String code, String msg) { + super(msg); + this.code = code; + this.msg = msg; + } + + public TradeException(String msg) { + super(msg); + } +} diff --git a/pay/src/main/java/com/ruoyi/key/KeyManager.java b/pay/src/main/java/com/ruoyi/key/KeyManager.java new file mode 100644 index 0000000..aacfee5 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/key/KeyManager.java @@ -0,0 +1,16 @@ +package com.ruoyi.key; + +/** + * 密钥管理器接口 + */ +public interface KeyManager { + + + /** + * 根据名字获取key字符串 + * @param name + * @return + */ + String getKey(String name); + +} diff --git a/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java b/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java new file mode 100644 index 0000000..0d48c66 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java @@ -0,0 +1,19 @@ +package com.ruoyi.key.impl; + + +import com.ruoyi.key.KeyManager; +import com.ruoyi.util.FileUtil; + +/** + * 默认的key管理器-文件管理器 + */ +public class DefaultKeyManager implements KeyManager { + + + @Override + public String getKey(String name) { + return FileUtil.readToStr(name); + } + + +} diff --git a/pay/src/main/java/com/ruoyi/util/FileUtil.java b/pay/src/main/java/com/ruoyi/util/FileUtil.java new file mode 100644 index 0000000..13d0e9f --- /dev/null +++ b/pay/src/main/java/com/ruoyi/util/FileUtil.java @@ -0,0 +1,37 @@ +package com.ruoyi.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * 文件读取类 + */ +public class FileUtil { + + + /** + * 获取文件内容 + * @param fileName + * @return + */ + public static String readToStr(String fileName){ + InputStream is = FileUtil.class.getClassLoader().getResourceAsStream(fileName); + ByteArrayOutputStream os = new ByteArrayOutputStream(2048); + byte[] buffer = new byte[1024]; + + String str; + try { + int length; + while((length = is.read(buffer)) != -1) { + os.write(buffer, 0, length); + } + + str = os.toString("UTF-8"); + } catch (IOException var5) { + throw new IllegalArgumentException("无效的密钥", var5); + } + return str; + } + +} diff --git a/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java b/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java new file mode 100644 index 0000000..d1dfc8c --- /dev/null +++ b/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java @@ -0,0 +1,459 @@ +package com.ruoyi.wx; + + +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.ruoyi.annotation.TradePlatform; +import com.ruoyi.config.CallbackConfig; +import com.ruoyi.constant.PayConstant; +import com.ruoyi.constant.Platform; +import com.ruoyi.core.ElegentTrade; +import com.ruoyi.dto.*; +import com.ruoyi.exceptions.TradeException; +import com.ruoyi.util.FileUtil; +import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; +import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.PrivateKey; +import java.security.Signature; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +@Component +@Slf4j +@TradePlatform(Platform.WX) +public class WxPayElegentTrade implements ElegentTrade { + + @Autowired + private WxpayConfig wxpayConfig; + + @Autowired + private CallbackConfig callbackConfig; + + /** + * 创建微信支付订单方法 + * 这里参考官网代码: + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml Native下单 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml JSAPI 下单 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml H5下单 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml APP下单 + * @param payRequest 支付请求 + * @return 支付响应 + * @throws IOException + */ + @Override + public PayResponse requestPay(PayRequest payRequest, String tradeType)throws TradeException { + PayResponse payResponse = new PayResponse(); //返回结果 + try { + // 请求body参数构建 + Map params = new HashMap() { + { + put("mchid", wxpayConfig.getMchId()); + put("appid", wxpayConfig.getAppId()); + put("notify_url", callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH + PayConstant.NOTIFY +"/"+ Platform.WX ); + put("out_trade_no", payRequest.getOrderSn()); + put("amount", new HashMap() { + { + put("total", payRequest.getTotalFee());//金额,单位:分 + put("currency", "CNY");//人民币 + } + }); + put("description", payRequest.getBody()); + } + }; + + if("h5".equals(tradeType)){ //h5 + params.put("scene_info", new HashMap() { + { + put("payer_client_ip", "127.0.0.1"); + put("h5_info", new HashMap() { + { + put("type", "Wap"); + } + }); + } + }); + } + if ("jsapi".equals(tradeType)) { //如果是小程序支付 + params.put("payer", new HashMap() { + { + put("openid", payRequest.getOpenid()); + } + }); + } + + + String url = WxpayConstant.createOrder + tradeType; //创建订单 + log.info("elegent-pay 请求参数{}",params); + Map map = postApiTemplate(url, params); + + if("SUCCESS".equals( map.get("code") )){ + payResponse.setOrder_sn(payRequest.getOrderSn()); + payResponse.setSuccess(true); + payResponse.setCode_url(map.get("code_url")); + payResponse.setMessage(map.get("message")); + + payResponse.setPrepay_id(map.get("prepay_id")); + payResponse.setH5_url( map.get("h5_url") ); + + payResponse.setExpand(map); //全部数据 + + if("jsapi".equals(tradeType)){//如果是小程序,需要封装到Expand + Map data=new HashMap<>(); + String timeStamp = String.valueOf(System.currentTimeMillis() / 1000); + String nonceStr = IdUtil.simpleUUID(); + String packages = "prepay_id=" + payResponse.getPrepay_id(); + String privateKey = FileUtil.readToStr("wxpay_private.key"); + String paySign = this.createPaySign(wxpayConfig.getAppId(), timeStamp, nonceStr, packages, privateKey); + data.put("appId", wxpayConfig.getAppId());// appid + data.put("timeStamp", timeStamp);// 时间戳 + data.put("nonceStr", nonceStr);// 随机字符串 + data.put("package","prepay_id="+payResponse.getPrepay_id()); + data.put("signType", "RSA");// 签名类型,默认为RSA,仅支持RSA + data.put("paySign", paySign);// 签名 + data.put("orderNo",payRequest.getOrderSn()); + payResponse.setJsapiData(data); + } + + + log.info("createOrder: {}", payResponse); + + }else{ + payResponse.setSuccess(false); + payResponse.setMessage( map.get("message") ); + } + return payResponse; + }catch (Exception e){ + e.printStackTrace(); + payResponse.setSuccess(false); + } + return payResponse; + } + + + /** + * 关闭订单 + * 参考官网代码 + * https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml 3.2.5. 【服务端】关闭订单 + * @return + */ + @Override + public Boolean closePay(String orderSn) throws TradeException { + // 请求body参数构建 + Map params = new HashMap(); + params.put("mchid", wxpayConfig.getMchId()); + String url = WxpayConstant.closeOrder.replaceAll("\\{out_trade_no\\}",orderSn); + Map map = postApiTemplate(url, params); + if("SUCCESS".equals( map.get("code"))){ + return true; + }else{ + return false; + } + } + + + /** + * 退款 + * 参考官网代码 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_9.shtml + * @param refundRequest + * @return + */ + @Override + public Boolean refund(RefundRequest refundRequest) { + // 请求body参数构建 + // 请求body参数构建 + Map params = new HashMap(); + params.put("notify_url", callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH +PayConstant.REFUND_NOTIFY +"/"+ Platform.WX ); //回调地址 + params.put("out_trade_no", refundRequest.getOrderSn());//订单编号 + //out_refund_no + params.put("out_refund_no", refundRequest.getRequestNo());//退款申请单编号 (多次退款需要不一样才行) + params.put("amount", new HashMap() { + { + put("refund",refundRequest.getRefundAmount());//退款金额 + put("total", refundRequest.getTotalFee());//原金额,单位:分 + put("currency", "CNY");//人民币 + } + }); + String url = WxpayConstant.refund; //创建订单 + Map map = postApiTemplate(url, params); + if("SUCCESS".equals( map.get("code"))){ + + return true; + }else{ + return false; + } + } + + + + /** + * 手动查询订单 + * 参考官网代码: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_2.shtml 3.2.4. 【服务端】查询订单 + * @param orderSn + * @return + */ + @Override + public QueryResponse queryTradingOrderNo(String orderSn) throws TradeException { + // 请求body参数构建 + Map params = new HashMap(); + params.put("mchid", wxpayConfig.getMchId()); + String url = WxpayConstant.queryOrderNo+orderSn;; + try { + Map map = getApiTemplate(url, params); + QueryResponse queryResponse=new QueryResponse(); + queryResponse.setOrder_sn((String)map.get("out_trade_no") ); //订单号 + queryResponse.setTransaction_id((String)map.get("transaction_id") ); //交易单类型 + queryResponse.setTrade_state( (String) map.get("trade_state") );//交易状态 + Map amount = (Map)map.get("amount"); + if(amount!=null){ + queryResponse.setTotal( (Integer) amount.get("total") ); //总金额 + } + Map payer= (Map)map.get("payer"); + if(payer!=null){ + queryResponse.setOpenid( (String)payer.get("openid") ); + } + queryResponse.setExpand(map);//全部数据 + return queryResponse; + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + + /** + * 查询退款订单 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_10.shtml + * @param out_refund_no + * @return + * @throws TradeException + */ + @Override + public QueryRefundResponse queryRefundTrading(String out_refund_no) throws TradeException { + + // 请求body参数构建 + Map params = new HashMap(); + String url = WxpayConstant.queryRufundOrderNo + out_refund_no; + try { + Map map = getApiTemplate(url, params); + QueryRefundResponse queryRefundResponse=new QueryRefundResponse(); + queryRefundResponse.setOrder_sn( (String) map.get("out_trade_no") ); + queryRefundResponse.setTransaction_id( (String) map.get("transaction_id") ); + Map amount = (Map)map.get("amount"); + queryRefundResponse.setTotal( (Integer) amount.get("total") ); //总金额 + queryRefundResponse.setRefund((Integer) amount.get("payer_refund") ); //退款金额 + queryRefundResponse.setRefund_id((String) map.get("refund_id") ); //退款单号 + queryRefundResponse.setOut_refund_no( (String) map.get("out_refund_no") );//退款订单号 + + queryRefundResponse.setChannel( (String) map.get("channel") ); //通道 + queryRefundResponse.setUser_received_account( (String) map.get("user_received_account") ); //账号 + queryRefundResponse.setStatus( (String) map.get("status") ); //状态 + queryRefundResponse.setSuccess_time( (String) map.get("success_time") ); + queryRefundResponse.setExpand(map); + return queryRefundResponse; + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String getOpenid(String code) { + String getOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?" + + "appid="+wxpayConfig.getAppId() + +"&secret="+wxpayConfig.getAppSecret() + +"&js_code="+code+"&grant_type=authorization_code"; + RestTemplate restTemplate = new RestTemplate(); + String respResult = restTemplate.getForObject(getOpenIdUrl,String.class); + log.info("获取openid的url:{},respResult:{}",getOpenIdUrl,respResult); + if( respResult==null || "".equals(respResult) ) return ""; + try{ + + Map map = JSON.parseObject(respResult, Map.class); + String errorCode = map.get("errcode") ; + if(errorCode!=null && !"".equals(errorCode)){ + int errorCodeInt = Integer.valueOf(errorCode).intValue(); + + log.info("获取openid的errorCode,{}",errorCodeInt); + if(errorCodeInt != 0) return ""; + } + return map.get("openid"); + }catch (Exception ex){ + ex.printStackTrace(); + return ""; + } + } + + + private Map getApiTemplate(String url, Map params) throws URISyntaxException, IOException { + URIBuilder uriBuilder = new URIBuilder(url); + //添加参数 + for (String key : params.keySet()) { + uriBuilder.addParameter(key, params.get(key)); + } + //完成签名并执行请求 + HttpGet httpGet = new HttpGet(uriBuilder.build()); + httpGet.addHeader("Accept", "application/json"); + CloseableHttpClient httpClient = getWxHttpClient(); + CloseableHttpResponse response = httpClient.execute(httpGet); + return responseTemplate(response); + } + + + private Map responseTemplate(CloseableHttpResponse response) { + Map result = null; + try { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == 200) { //处理成功 + // log.info("success,return body = " + EntityUtils.toString(response.getEntity())); + result = JSON.parseObject(EntityUtils.toString(response.getEntity()), Map.class); + result.put("code", "SUCCESS"); + } else if (statusCode == 204) { //处理成功,无返回Body + log.info("success"); + result = new HashMap() { + { + put("code", "SUCCESS"); + } + }; + } else { + String returnBody = EntityUtils.toString(response.getEntity()); + log.error("failed,resp code = " + statusCode + ",return body = " + returnBody); + //throw new TradeException("创建本地支付订单失败!"+payDTO.getOrderSn()); + Map map = JSON.parseObject(returnBody, Map.class); + result = new HashMap() { + { + put("code", "FAIL"); + put("message", map.get("message")); + } + }; + } + } catch (Exception e) { + result = new HashMap() { + { + put("code", "FAIL"); + put("message", e.getMessage()); + } + }; + } finally { + closeConnect(response); + return result; + } + } + + private Map postApiTemplate(String url, Map params) { + try { + HttpPost httpPost = new HttpPost(url); + StringEntity entity = new StringEntity(JSON.toJSONString(params)); + entity.setContentType("application/json"); + httpPost.setEntity(entity); + httpPost.setHeader("Accept", "application/json"); + //完成签名并执行请求 + CloseableHttpClient httpClient = getWxHttpClient(); + CloseableHttpResponse response = httpClient.execute(httpPost); + return responseTemplate( response ); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + + /** + * 获取微信HTTP连接 + * + * @return + */ + private CloseableHttpClient getWxHttpClient() { + try { + //这里对秘钥进行加密使用的完全是官网上的代码 + //TODO 参考官网代码 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_2.shtml + // 加载商户私钥(privateKey:私钥字符串) + String key = FileUtil.readToStr("wxpay_private.key"); + + PrivateKey merchantPrivateKey = PemUtil + .loadPrivateKey(new ByteArrayInputStream(key.getBytes("utf-8"))); + // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥) + //PrivateKey merchantPrivateKey = keyManager.getPrivateKey("wxpay_private.key");//读取私钥 + PrivateKeySigner privateKeySigner = new PrivateKeySigner(wxpayConfig.getMchSerialNo(), merchantPrivateKey); + WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials( + wxpayConfig.getMchId(), privateKeySigner); + // 向证书管理器增加需要自动更新平台证书的商户信息 + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + certificatesManager.putMerchant(wxpayConfig.getMchId(), wechatPay2Credentials, wxpayConfig.getApiV3Key().getBytes("utf-8")); + // 初始化httpClient + return WechatPayHttpClientBuilder.create() + .withMerchant(wxpayConfig.getMchId(), wxpayConfig.getMchSerialNo(), merchantPrivateKey) + .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(wxpayConfig.getMchId()))).build(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("微信支付--初始化,校验系统参数失败"); + } + + } + + + /** + * 关闭资源 + */ + private void closeConnect(CloseableHttpResponse response) { + try { + response.close(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("资源回收出错"); + } + } + + + /** + * 创建支付签名 + * @param appid + * @param timeStamp + * @param nonceStr + * @param packages + * @param privateKey + * @return + * @throws Exception + */ + private String createPaySign(String appid, String timeStamp, String nonceStr, String packages,String privateKey) throws Exception { + Signature sign = Signature.getInstance("SHA256withRSA"); + // 加载商户私钥 + PrivateKey key = PemUtil + .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes(CharsetUtil.CHARSET_UTF_8))); + sign.initSign(key); + String message = StrUtil.format("{}\n{}\n{}\n{}\n", + appid, + timeStamp, + nonceStr, + packages); + sign.update(message.getBytes()); + return Base64.getEncoder().encodeToString(sign.sign()); + } + + +} diff --git a/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java b/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java new file mode 100644 index 0000000..c570b6f --- /dev/null +++ b/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java @@ -0,0 +1,153 @@ +package com.ruoyi.wx; + + +import com.alibaba.fastjson.JSON; +import com.ruoyi.annotation.TradePlatform; +import com.ruoyi.constant.Platform; +import com.ruoyi.core.ElegentValid; +import com.ruoyi.dto.ValidResponse; +import com.ruoyi.exceptions.TradeException; +import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.notification.Notification; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +@Component +@Slf4j +@TradePlatform(Platform.WX) +public class WxPayElegentValid implements ElegentValid { + + + @Autowired + private WxpayConfig wxpayConfig; + + @Override + public ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest httpServletRequest) throws TradeException { + ValidResponse validResponse=new ValidResponse(); + + try { + //获取请求头 + HttpHeaders headers = httpEntity.getHeaders(); + //构建微信请求数据对象 + NotificationRequest request = new NotificationRequest.Builder() + .withSerialNumber(headers.getFirst("Wechatpay-Serial")) //证书序列号(微信平台) + .withNonce(headers.getFirst("Wechatpay-Nonce")) //随机串 + .withTimestamp(headers.getFirst("Wechatpay-Timestamp")) //时间戳 + .withSignature(headers.getFirst("Wechatpay-Signature")) //签名字符串 + .withBody(httpEntity.getBody()) + .build(); + + + //微信通知的业务处理 + //验证签名,确保请求来自微信 + Map jsonData = null; + try { + //确保在管理器中存在自动更新的商户证书 + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + Verifier verifier = certificatesManager.getVerifier(wxpayConfig.getMchId()); + + //验签和解析请求数据 + NotificationHandler notificationHandler = new NotificationHandler(verifier, wxpayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)); + Notification notification = notificationHandler.parse(request); + + if (!"TRANSACTION.SUCCESS".equals(notification.getEventType())) { + validResponse.setValid(false); + return validResponse; + } + //获取解密后的数据 + jsonData = JSON.parseObject(notification.getDecryptData(),Map.class ); + log.info("解密后的数据为:"+jsonData); + } catch (Exception e) { + throw new TradeException("验签失败"); + } + if (!"SUCCESS".equals(jsonData.get("trade_state"))) { + validResponse.setValid(false); + return validResponse; + } + validResponse.setValid(true); + validResponse.setOrderSn( (String) jsonData.get("out_trade_no") ); //订单号 + return validResponse; + } catch (Exception e) { + validResponse.setValid(false); + return validResponse; + } + } + + @Override + public ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest httpServletRequest) throws TradeException { + + ValidResponse validResponse=new ValidResponse(); + try { + //获取请求头 + HttpHeaders headers = httpEntity.getHeaders(); + + //构建微信请求数据对象 + NotificationRequest request = new NotificationRequest.Builder() + .withSerialNumber(headers.getFirst("Wechatpay-Serial")) //证书序列号(微信平台) + .withNonce(headers.getFirst("Wechatpay-Nonce")) //随机串 + .withTimestamp(headers.getFirst("Wechatpay-Timestamp")) //时间戳 + .withSignature(headers.getFirst("Wechatpay-Signature")) //签名字符串 + .withBody(httpEntity.getBody()) + .build(); + + //微信通知的业务处理 + Map jsonData = null; + //验证签名,确保请求来自微信 + try { + //确保在管理器中存在自动更新的商户证书 + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + Verifier verifier = certificatesManager.getVerifier(wxpayConfig.getMchId()); + + //验签和解析请求数据 + NotificationHandler notificationHandler = new NotificationHandler(verifier, wxpayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)); + Notification notification = notificationHandler.parse(request); + + if (!"REFUND.SUCCESS".equals(notification.getEventType())) { + //非成功请求直接返回,理论上都是成功的请求 + validResponse.setValid(false); + return validResponse; + } + //获取解密后的数据 + jsonData = JSON.parseObject( notification.getDecryptData(),Map.class ); + + + } catch (Exception e) { + throw new TradeException("验签失败"); + } + if (!"SUCCESS".equals(jsonData.get("refund_status"))) { + //非成功请求直接返回,理论上都是成功的请求 + validResponse.setValid(false); + return validResponse; + } + + //交易单号 + validResponse.setValid(true); + validResponse.setOrderSn( (String) jsonData.get("out_trade_no") ); //订单号 + return validResponse; + } catch (Exception e) { + //非成功请求直接返回,理论上都是成功的请求 + validResponse.setValid(false); + return validResponse; + } + } + + @Override + public String successResult() { + return JSON.toJSONString(WxpayConstant.SUCCESS ) ; + } + + @Override + public String failResult() { + return JSON.toJSONString( WxpayConstant.FAIL); + } +} diff --git a/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java b/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java new file mode 100644 index 0000000..c5f139c --- /dev/null +++ b/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java @@ -0,0 +1,20 @@ +package com.ruoyi.wx; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 微信权限对接类 + */ +@Component +@ConfigurationProperties("elegent.pay.wxpay") +@Data +public class WxpayConfig { + + private String mchId; //商户号 + private String appId; //APPID + private String appSecret;//app密钥 + private String mchSerialNo; //商户证书序列号 + private String apiV3Key; //V3密钥 + +} \ No newline at end of file diff --git a/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java b/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java new file mode 100644 index 0000000..01d3415 --- /dev/null +++ b/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java @@ -0,0 +1,48 @@ +package com.ruoyi.wx; + +import java.util.HashMap; +import java.util.Map; + +public class WxpayConstant { + + public static final Map SUCCESS = new HashMap(){ + { + put("code", "SUCCESS"); + } + }; + + public static final Map FAIL = new HashMap(){ + { + put("code", "FAIL"); + put("message","微信回调错误结果"); + } + }; + + + public final static String domain ="https://api.mch.weixin.qq.com/v3"; + + /** + * 创建订单 + */ + public final static String createOrder = domain +"/pay/transactions/"; + + /** + * 关闭订单 + */ + public final static String closeOrder = domain+"/pay/transactions/out-trade-no/{out_trade_no}/close"; + + /** + * 查询订单编号 + */ + public static String queryOrderNo = domain+"/pay/transactions/out-trade-no/"; + + /** + * 查询退款订单 + */ + public static String queryRufundOrderNo =domain+ "/refund/domestic/refunds/"; + + /** + * 退款接口 + */ + public static String refund = domain+"/refund/domestic/refunds"; +} diff --git a/pay/src/main/resources/META-INF/spring.factories b/pay/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..da04c71 --- /dev/null +++ b/pay/src/main/resources/META-INF/spring.factories @@ -0,0 +1,14 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.ruoyi.config.CallbackConfig,\ + com.ruoyi.core.CallbackWatch,\ + com.ruoyi.core.ElegentPayImpl,\ + com.ruoyi.core.ElegentLoader,\ + com.ruoyi.core.ElegentConfig,\ + com.ruoyi.key.impl.DefaultKeyManager,\ + com.ruoyi.core.CallbackController,\ + com.ruoyi.wx.WxpayConfig,\ + com.ruoyi.wx.WxPayElegentTrade,\ + com.ruoyi.wx.WxPayElegentValid,\ + com.ruoyi.ali.AlipayConfig,\ + com.ruoyi.ali.AlipayElegentTrade,\ + com.ruoyi.ali.AlipayElegentValid \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..61d1b47 --- /dev/null +++ b/pom.xml @@ -0,0 +1,231 @@ + + + 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.39 + 6.4.4 + 2.13.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} + + + + + 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} + + + + + + + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-quartz + ruoyi-generator + ruoyi-common + pay + + pom + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + ruoyi-system/** + ruoyi-common/** + + + + + + + + + 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/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml new file mode 100644 index 0000000..2186d33 --- /dev/null +++ b/ruoyi-admin/pom.xml @@ -0,0 +1,100 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + jar + ruoyi-admin + + + web服务入口 + + + + + + + org.springframework.boot + spring-boot-devtools + true + + + + + io.springfox + springfox-boot-starter + + + + + io.swagger + swagger-models + 1.6.2 + + + + + mysql + mysql-connector-java + + + + + com.ruoyi + ruoyi-framework + + + + + com.ruoyi + ruoyi-quartz + + + + + com.ruoyi + ruoyi-generator + + + com.ruoyi + pay + 1.0.0-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.5.15 + + 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/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java new file mode 100644 index 0000000..775f772 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -0,0 +1,32 @@ +package com.ruoyi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * 启动程序 + * + * @author ruoyi + */ +@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +@EnableScheduling +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" + + " ''-' `'-' `-..-' "); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java new file mode 100644 index 0000000..6de67dc --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/ArbitrSignatuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/ArbitrSignatuController.java new file mode 100644 index 0000000..def71be --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/ArbitrSignatuController.java @@ -0,0 +1,33 @@ +package com.ruoyi.web.controller.bestsign; + +import com.ruoyi.bestsign.domain.ArbitrSignatuVO; +import com.ruoyi.bestsign.domain.PersonRegisterVO; +import com.ruoyi.bestsign.service.ArbitrSignatuService; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/arbitrSignatu") +public class ArbitrSignatuController { + @Autowired + ArbitrSignatuService arbitrSignatuService; + + /** + * 申请状态查询 + * + * @param arbitrSignatuVO + * @return + */ + @PostMapping("/selectApplyStatus") + public AjaxResult selectApplyStatus (@Validated @RequestBody ArbitrSignatuVO arbitrSignatuVO) { + return arbitrSignatuService.selectApplyStatus(arbitrSignatuVO); + } + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/RegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/RegisterController.java new file mode 100644 index 0000000..5f3b0d1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bestsign/RegisterController.java @@ -0,0 +1,31 @@ +package com.ruoyi.web.controller.bestsign; + +import com.ruoyi.bestsign.domain.PersonRegisterVO; +import com.ruoyi.bestsign.service.SignRegisterService; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/register") +public class RegisterController { + @Autowired + SignRegisterService signRegisterService; + + /** + * 注册上上签个人用户 + * + * @param personRegisterVO + * @return + */ + @PostMapping("/registerPerson") + public AjaxResult createDocument(@Validated @RequestBody PersonRegisterVO personRegisterVO) { + return signRegisterService.registerPerson(personRegisterVO); + } +// @PostMapping("/registerEnterprise") +// public AjaxResult +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java new file mode 100644 index 0000000..d2d6e8c --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java new file mode 100644 index 0000000..cec5006 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java new file mode 100644 index 0000000..69470d0 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java new file mode 100644 index 0000000..cc805ad --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java new file mode 100644 index 0000000..e0175f4 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java new file mode 100644 index 0000000..6ca78cf --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java new file mode 100644 index 0000000..a442863 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java new file mode 100644 index 0000000..ab4653d --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java new file mode 100644 index 0000000..59e7588 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -0,0 +1,132 @@ +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)); + } + + /** + * 删除部门 + */ + @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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java new file mode 100644 index 0000000..59becaf --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java new file mode 100644 index 0000000..c53867c --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java new file mode 100644 index 0000000..13007eb --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java new file mode 100644 index 0000000..ebed683 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -0,0 +1,100 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.Set; + +import com.ruoyi.system.service.ISysUserService; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.service.IdentityAuthenticationService; +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; + @Autowired + IdentityAuthenticationService identityAuthenticationService; + @Autowired + private ISysUserService sysUserService; + + /** + * 登录方法 + * + * @param loginBody 登录信息 + * @return 结果 + */ + @PostMapping("/login") + public AjaxResult login(@RequestBody LoginBody loginBody) { + AjaxResult ajax = AjaxResult.success(); + // 生成令牌 + String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), + loginBody.getUuid()); + ajax.put(Constants.TOKEN, token); + //判断该用户是否已经实名认证(certificationStatus1已认证0未认证) + IdentityAuthentication identityAuthentication=new IdentityAuthentication(); + identityAuthentication.setUserName(loginBody.getUsername()); + String status = identityAuthenticationService.checkIsAuthentication(identityAuthentication); + + ajax.put("certificationStatus", status); + // 获取用户信息 + SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername()); + ajax.put("userId", sysUser!=null?sysUser.getUserId():""); + ajax.put("userName", sysUser!=null?sysUser.getUserName():""); + 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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java new file mode 100644 index 0000000..03b6b65 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java new file mode 100644 index 0000000..8622828 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java new file mode 100644 index 0000000..c37a543 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java new file mode 100644 index 0000000..be5af6a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -0,0 +1,136 @@ +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 currentUser = loginUser.getUser(); + currentUser.setNickName(user.getNickName()); + currentUser.setEmail(user.getEmail()); + currentUser.setPhonenumber(user.getPhonenumber()); + currentUser.setSex(user.getSex()); + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser)) + { + return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser)) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + if (userService.updateUserProfile(currentUser) > 0) + { + // 更新缓存用户信息 + 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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java new file mode 100644 index 0000000..fe19249 --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java new file mode 100644 index 0000000..232c5fa --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java new file mode 100644 index 0000000..e68e0f0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -0,0 +1,258 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.annotation.Anonymous; +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.*; +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 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 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)); + } + /** + * 根据userId获取用户信息 + * @param userId + * @return + */ + @Anonymous + @GetMapping("/selectUserById") + public AjaxResult selectUserById(@RequestParam(required = true) Long userId){ + return AjaxResult.success(userService.selectUserById(userId)); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java new file mode 100644 index 0000000..b4f6bac --- /dev/null +++ b/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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/AdjudicationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/AdjudicationController.java new file mode 100644 index 0000000..6d2513f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/AdjudicationController.java @@ -0,0 +1,191 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +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.redis.RedisCache; +import com.ruoyi.wisdomarbitrate.StringIdsReq; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.SealSignRecord; +import com.ruoyi.wisdomarbitrate.domain.vo.BookSendVO; +import com.ruoyi.wisdomarbitrate.domain.vo.LogisticsInfoVO; +import com.ruoyi.wisdomarbitrate.service.IAdjudicationService; +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.*; + +import java.util.List; + +@RestController +@RequestMapping("/adjudication") +public class AdjudicationController extends BaseController { + @Autowired + private IAdjudicationService adjudicationService; + + /** + * 根据签署流程id查询批量签名链接 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:selectSignUrl')") + @PostMapping("/selectBatchSignUrl") + public AjaxResult selectBatchSignUrl(@RequestBody StringIdsReq idsReq) { + if(CollectionUtil.isEmpty(idsReq.getIds())|| StrUtil.isEmpty(idsReq.getPsnAccount())){ + return error("参数校验失败"); + } + SealSignRecord sealSignRecordselect = adjudicationService.selectBatchSignUrl(idsReq); + return success(sealSignRecordselect); + } + + /** + * 根据签署流程id查询批量用印链接 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:selectSignUrl')") + @PostMapping("/selectBatchSealUrl") + public AjaxResult selectBatchSealUrl(@RequestBody StringIdsReq idsReq) { + if(CollectionUtil.isEmpty(idsReq.getIds())|| StrUtil.isEmpty(idsReq.getPsnAccount())){ + return error("参数校验失败"); + } + SealSignRecord sealSignRecordselect = adjudicationService.selectBatchSealUrl(idsReq); + return success(sealSignRecordselect); + } + /** + * 根据仲裁员手机号分页查询待签名/待用印的案件 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:selectSignUrl')") + @GetMapping("/pageSignAdjudicate") + public TableDataInfo pageSignAdjudicate(@RequestParam(value = "personAccount",required = false) String personAccount, @RequestParam("caseStatus") Integer caseStatus) { + startPage(); + List list = adjudicationService.selectSealSigning(personAccount,caseStatus); + return getDataTable(list); + } + + + /** + * 生成裁决书 + * @param caseApplication + * @return + */ + @PostMapping("/document") + public AjaxResult createDocument(@Validated @RequestBody CaseApplication caseApplication){ + if (caseApplication.getId() == null) { + return AjaxResult.error("案件id不能为空"); + } + return adjudicationService.createDocument(caseApplication); + } + /** + * 批量生成裁决书 + * @param caseApplication + * @return + */ + @PostMapping("/batchDocument") + public AjaxResult batchDocument(@Validated @RequestBody BatchCaseApplication caseApplication){ + if (CollectionUtil.isEmpty(caseApplication.getIds())) { + return AjaxResult.error("参数校验失败"); + } + return adjudicationService.batchDocument(caseApplication.getIds()); + } + + /** + * 重新生成裁决书 + * @param caseApplication + * @return + */ + @PostMapping("/regenerationDocument") + public AjaxResult regenerationDocument(@Validated @RequestBody CaseApplication caseApplication){ + return adjudicationService.regenerationDocument(caseApplication); + } + + /** + * 裁决书送达(电子邮件) + * @param bookSendVO + * @return + */ + @PostMapping("/delivery") + public AjaxResult sendDocumentByEmail(@RequestBody BookSendVO bookSendVO){ + return adjudicationService.sendDocumentByEmail(bookSendVO.getId(),bookSendVO.getAppEmail(),bookSendVO.getResEmail(),bookSendVO.getApptrackingNum(),bookSendVO.getRestrackingNum()); + } + + /** + * 根据快递单号查询物流信息 + * @param caseApplication + * @return + */ + @GetMapping("/logistics") +// @PreAuthorize("@ss.hasPermi('delivery:detail')") + public AjaxResult getLogisticsInfo(CaseApplication caseApplication){ + List logisticsInfo = adjudicationService.getLogisticsInfo(caseApplication); + return AjaxResult.success(logisticsInfo); + } + + /** + * 签名(暂时只改案件状态) + * @param caseApplication + * @return + */ + @PostMapping("/signature") +// @PreAuthorize("@ss.hasPermi('awardManagement:list:sign')") + public AjaxResult signature(@Validated @RequestBody CaseApplication caseApplication){ + return adjudicationService.signature(caseApplication); + } + + + /** + * 归档(暂时只改案件状态) + * @param batchCaseApplication + * @return + */ + @PostMapping("/caseFile") +// @PreAuthorize("@ss.hasPermi('awardManagement:list:file')") + public AjaxResult caseFile(@RequestBody BatchCaseApplication batchCaseApplication){ + if(CollectionUtil.isEmpty(batchCaseApplication.getIds())){ + return error("参数校验失败"); + } + return adjudicationService.caseFile(batchCaseApplication.getIds()); + } + + /** + * 送达(不包含发送电子邮件) + * @param bookSendVO + * @return + */ + @PostMapping("/service") +// @PreAuthorize("@ss.hasPermi('awardManagement:list:sendaward')") + public AjaxResult service(@RequestBody BookSendVO bookSendVO){ + return adjudicationService.service(bookSendVO.getId(),bookSendVO.getAppEmail(),bookSendVO.getResEmail(),bookSendVO.getApptrackingNum(),bookSendVO.getRestrackingNum()); + } + /** + * 用印(暂时只改案件状态) + * @param caseApplication + * @return + */ + @PostMapping("/stamp") +// @PreAuthorize("@ss.hasPermi('awardManagement:list:signprint')") + public AjaxResult stamp(@Validated @RequestBody CaseApplication caseApplication){ + return adjudicationService.stamp(caseApplication); + } + + /** + * 档案详情查询 + * @param id 案件id + * @return + */ + @GetMapping("/archives") + public AjaxResult getArchivesDetail(Long id){ + + return adjudicationService.getArchivesDetail(id); + } + /** + * 根据案件id获取邮箱 + * @param id 案件id + * @return + */ + @GetMapping("/emailByCaseId") + public AjaxResult emailByCaseId(@RequestParam("id") Long id){ + + return adjudicationService.emailByCaseId(id); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java new file mode 100644 index 0000000..b4af1e4 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java @@ -0,0 +1,44 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.service.ISysUserService; +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import com.ruoyi.wisdomarbitrate.service.IArbitratorService; +import org.springframework.beans.factory.annotation.Autowired; +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 java.util.List; + +@RestController +@RequestMapping("/arbitrator") +public class ArbitratorController extends BaseController { + @Autowired + private ISysUserService sysUserService; + + /** + * 查询仲裁员信息 + */ +// @PreAuthorize("@ss.hasPermi('arbitrator:list')") + @GetMapping("/list") + public TableDataInfo list(Arbitrator arbitrator) + { + startPage(); + List list = sysUserService.selectUserListByAdRole(arbitrator); + return getDataTable(list); + } + + + + + + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java new file mode 100644 index 0000000..4ab8ac6 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java @@ -0,0 +1,588 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alipay.api.internal.util.file.IOUtils; +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.FileTransformation; +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.EsignDemoException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.WxAppletNotifyUtils; +import com.ruoyi.util.FileUtil; +import com.ruoyi.wisdomarbitrate.StringIdsReq; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO; +import com.ruoyi.wisdomarbitrate.domain.vo.ToDoCount; +import com.ruoyi.wisdomarbitrate.service.IAdjudicationService; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +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.*; +import com.ruoyi.common.utils.poi.ExcelUtil; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.net.URLEncoder; +import java.util.List; + + +@RestController +@RequestMapping("/caseApplication") +public class CaseApplicationController extends BaseController { + @Autowired + private ICaseApplicationService caseApplicationService; + @Autowired + private IAdjudicationService adjudicationService; + + + /** + * 查询立案数据 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list')") + @GetMapping("/list") + public TableDataInfo list(CaseApplication caseApplication) { + if(StrUtil.isEmpty(caseApplication.getSelectCaseStatus())){ + caseApplication.setSelectCaseStatus("0"); + } + startPage(); + List list = caseApplicationService.selectCaseApplicationListByRole(caseApplication); + return getDataTable(list); + } + + /** + * 查询批量管理案件列表 + */ + @GetMapping("/listBatch") + public TableDataInfo listBatch(CaseApplication caseApplication) { + startPage(); + List list = caseApplicationService.selectCaseApplicationListBatchByRole(caseApplication); + return getDataTable(list); + } + + /** + * 根据角色查询待办数量 + * @return + */ + + @GetMapping("/toDoCount") + public AjaxResult toDoCount() { + ToDoCount toDoCount = caseApplicationService.selectToDoCount(); +// List list = caseApplicationService.selectCaseApplicationList(caseApplication); + return success(toDoCount); + } + + /** + * 新增立案数据 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:add')") + @Log(title = "新增立案数据", businessType = BusinessType.INSERT) + @PostMapping("/addCaseApplication") + public AjaxResult addCaseApplication(@Validated @RequestBody CaseApplication caseApplication) + { + + caseApplication.setCreateBy(getUsername()); + return toAjax(caseApplicationService.insertcaseApplication(caseApplication)); + } + + /** + * 修改立案数据 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:update')") + @Log(title = "修改立案数据", businessType = BusinessType.UPDATE) + @PostMapping("/editCaseApplication") + public AjaxResult editCaseApplication(@Validated @RequestBody CaseApplication caseApplication) { + + caseApplication.setUpdateBy(getUsername()); + return caseApplicationService.editCaseApplication(caseApplication); + } + + /** + * 修改立案数据自定义字段 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:update')") + @Log(title = "修改立案数据自定义字段", businessType = BusinessType.UPDATE) + @PostMapping("/editCaseApplicationDefineval") + public AjaxResult editCaseApplicationDefineval(@Validated @RequestBody CaseApplication caseApplication) { + return caseApplicationService.editCaseApplicationDefineval(caseApplication); + } + + /** + * 提交立案申请 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:submit')") + @Log(title = "提交立案申请", businessType = BusinessType.UPDATE) + @PostMapping("/submitCaseApplication") + public AjaxResult submitCaseApplication(@RequestBody BatchCaseApplication batchCaseApplication) { + if(CollectionUtil.isEmpty(batchCaseApplication.getIds())){ + return error("参数校验失败"); + } + return toAjax(caseApplicationService.submitCaseApplication(batchCaseApplication.getIds())); + } + + /** + * 批量提交立案申请 + */ + @Log(title = "批量提交立案申请", businessType = BusinessType.UPDATE) + @PostMapping("/submitCaseApplicationBatch") + public AjaxResult submitCaseApplicationBatch(@RequestBody BatchCaseApplication batchCaseApplication) { + if(StringUtils.isEmpty(batchCaseApplication.getBatchNumber())){ + return error("参数校验失败"); + } + return toAjax(caseApplicationService.submitCaseApplicationBatch(batchCaseApplication.getBatchNumber())); + } + + + + + /** + * 删除立案数据 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:delete')") + @Log(title = "删除立案数据", businessType = BusinessType.DELETE) + @PostMapping("/removeCaseApplication") + public AjaxResult removeCaseApplication(@RequestBody BatchCaseApplication batchCaseApplication) { + if(CollectionUtil.isEmpty(batchCaseApplication.getIds())){ + return error("参数校验失败"); + } + return success(caseApplicationService.deletecaseApplicationByIds(batchCaseApplication.getIds())); + } + + /** + * 查询立案信息 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:detail')") + @PostMapping("/selectCaseApplication") + public AjaxResult selectCaseApplication(@Validated @RequestBody CaseApplication caseApplication) { + + CaseApplication caseApplicationselect = caseApplicationService.selectCaseApplication(caseApplication); + return success(caseApplicationselect); + } + + /** + * 查询已签署裁决书URL + */ + @PostMapping("/selectSignSealUrl") + public AjaxResult selectSignSealUrl(@Validated @RequestBody CaseApplication caseApplication) throws EsignDemoException { + CaseApplication caseApplicationselect = caseApplicationService.selectSignSealUrl(caseApplication); + return success(caseApplicationselect); + } + + /** + * 查询案件进度 + */ + @PostMapping("/selectCaseProgress") + public AjaxResult selectCaseProgress(@Validated @RequestBody CaseApplication caseApplication) { + AjaxResult caseApplicationselect = caseApplicationService.selectCaseProgress(caseApplication); + return success(caseApplicationselect); + } + + + /** + * 查询签名链接 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:selectSignUrl')") + @PostMapping("/selectSignUrl") + public AjaxResult selectSignUrl(@Validated @RequestBody CaseApplication caseApplication) throws EsignDemoException { + SealSignRecord sealSignRecordselect = caseApplicationService.selectSignUrl(caseApplication); + return success(sealSignRecordselect); + } + + + /** + * 查询用印链接 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:selectSealUrl')") + @PostMapping("/selectSealUrl") + public AjaxResult selectSealUrl(@Validated @RequestBody CaseApplication caseApplication) throws EsignDemoException { + SealSignRecord sealUrlRecordselect = caseApplicationService.selectSealUrl(caseApplication); + return success(sealUrlRecordselect); + } + + + /** + * 案件证据材料压缩包上传 + * + * @param file 附件 + * @param id 案件申请id + * @return + */ + @PostMapping("/uploadZipFile") + public AjaxResult uploadZipFile(@RequestParam("file") MultipartFile file, Long id) { + String username = this.getUsername(); + Long userId = this.getUserId(); + return caseApplicationService.uploadZipFile(file, id, username, userId); + } + + /** + * 立案申请导入模板下载 + */ + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + // 读取文件 + try { + InputStream fileInputStream = new URL("http://121.40.189.20:8000/API/uploadPath/template/案件导入模板.xlsx").openStream(); + response.setHeader("content-type", "application/octet-stream"); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("案件导入模板.xlsx","UTF-8")); + byte[] buffer = new byte[1024]; + int length; + while ((length = fileInputStream.read(buffer)) > 0) { + response.getOutputStream().write(buffer, 0, length); + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + @Log(title = "立案信息导入", businessType = BusinessType.IMPORT) +// @PreAuthorize("@ss.hasPermi('caseManagement:list:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file) throws Exception { + if(file==null){ + return warn("请上传文件"); + } + ExcelUtil util = new ExcelUtil(CaseApplication.class); + List caseApplicationList = util.importExcel(file.getInputStream()); + String operName = getUsername(); + String message = caseApplicationService.importCaseApplication(caseApplicationList, operName); + return success(message); + } + + /** + * 组庭 + */ +// @PreAuthorize("@ss.hasPermi('caseApplication:pendTral')") + @Log(title = "组庭", businessType = BusinessType.UPDATE) + @PostMapping("/pendTral") + public AjaxResult pendTral(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendTral(caseApplication)); + } + + /** + * 组庭审核 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:checkgroup')") + @Log(title = "组庭审核", businessType = BusinessType.UPDATE) + @PostMapping("/pendTralCheck") + public AjaxResult pendTralCheck(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendTralCheck(caseApplication)); + } + + /** + * 组庭确认 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:confirmgroup')") + @Log(title = "组庭确认", businessType = BusinessType.UPDATE) + @PostMapping("/pendTralSure") + public AjaxResult pendTralSure(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendTralSure(caseApplication)); + } + + /** + * 批量组庭审核 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:checkgroup')") + @Log(title = "批量组庭审核", businessType = BusinessType.UPDATE) + @PostMapping("/pendTralCheckBatch") + public AjaxResult pendTralCheckBatch(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendTralCheckBatch(caseApplication)); + } + + /** + * 批量组庭确认 + */ + @Log(title = "批量组庭确认", businessType = BusinessType.UPDATE) + @PostMapping("/pendTralSureBatch") + public AjaxResult pendTralSureBatch(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendTralSureBatch(caseApplication)); + } + + /** + * 修改开庭时间 + */ + @Log(title = "修改开庭时间", businessType = BusinessType.UPDATE) + @PostMapping("/updateHeardate") + public AjaxResult updateHeardate(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.updateHeardate(caseApplication)); + } + + /** + * 核验裁决书 + */ +// @PreAuthorize("@ss.hasPermi('caseApplication:verificationArbitrateRecord')") + @Log(title = "核验裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/verificationArbitrateRecord") + public AjaxResult verificationArbitrateRecord(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.verificationArbitrateRecord(caseApplication)); + } + + /** + * 部门长审核裁决书 + */ +// @PreAuthorize("@ss.hasPermi('caseApplication:checkArbitrateRecord')") + @Log(title = "部门长审核裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/checkArbitrateRecord") + public AjaxResult checkArbitrateRecord(@Validated @RequestBody CaseApplication caseApplication) { + + return caseApplicationService.checkArbitrateRecord(caseApplication); + } + /** + * 仲裁员审核裁决书 + */ +// @PreAuthorize("@ss.hasPermi('caseApplication:checkArbitrateRecord')") + @Log(title = "仲裁员审核裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/arbitrator/checkArbitrateRecord") + public AjaxResult arbitratorCheckArbitrateRecord(@Validated @RequestBody CaseApplication caseApplication) { + + return caseApplicationService.arbitratorCheckArbitrateRecord(caseApplication); + } + + /** + * 批量操作仲裁员审核裁决书 + */ + @Log(title = "批量操作仲裁员审核裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/arbitrator/checkArbitrateRecordBatch") + public AjaxResult arbitratorCheckArbitrateRecordBatch(@Validated @RequestBody CaseApplication caseApplication) { + + return caseApplicationService.arbitratorCheckArbitrateRecordBatch(caseApplication); + } + + /** + * 批量部门长审核裁决书 + */ + @Log(title = "批量部门长审核裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/checkArbitrateRecordBatch") + public AjaxResult checkArbitrateRecordBatch(@Validated @RequestBody CaseApplication caseApplication) { + + return caseApplicationService.checkArbitrateRecordBatch(caseApplication); + } + + /** + * 批量核验裁决书 + */ + @Log(title = "批量核验裁决书", businessType = BusinessType.UPDATE) + @PostMapping("/verificationArbitrateRecordBatch") + public AjaxResult verificationArbitrateRecordBatch(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.verificationArbitrateRecordBatch(caseApplication)); + } + + + /** + * 是否指派仲裁员 + */ +// @PreAuthorize("@ss.hasPermi('caseApplication:pendingAppointArbotrar')") + @Log(title = "是否指派仲裁员", businessType = BusinessType.UPDATE) + @PostMapping("/pendingAppointArbotrar") + public AjaxResult pendingAppointArbotrar(@Validated @RequestBody CaseApplication caseApplication) { + return toAjax(caseApplicationService.pendingAppointArbotrar(caseApplication)); + } + + /** + * 提交立案审查 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:check')") + @Log(title = "提交立案审查", businessType = BusinessType.UPDATE) + @PostMapping("/submitCaseApplicationCheck") + public AjaxResult submitCaseApplicationCheck(@RequestBody BatchCaseApplication batchCaseApplication) { + if(CollectionUtil.isEmpty(batchCaseApplication.getIds())|| batchCaseApplication.getAgreeOrNotCheck()==null){ + return error("参数校验失败"); + } + return success(caseApplicationService.submitCaseApplicationCheck(batchCaseApplication.getIds(),batchCaseApplication.getAgreeOrNotCheck(),batchCaseApplication.getCaseCheckReject())); + } + + /** + * 确认缴费查询立案信息 + */ +// @PreAuthorize("@ss.hasPermi('paymentManagement:list:detail')") + @PostMapping("/selectCaseApplicationConfirm") + public AjaxResult selectCaseApplicationConfirm(@Validated @RequestBody CaseApplication caseApplication) { + CaseApplication caseApplicationselect = caseApplicationService.selectCaseApplicationConfirm(caseApplication); + return success(caseApplicationselect); + } + + /** + * 批量提交立案审查 + */ + @Log(title = "批量提交立案审查", businessType = BusinessType.UPDATE) + @PostMapping("/submitCaseApplicationCheckBatch") + public AjaxResult submitCaseApplicationCheckBatch(@RequestBody BatchCaseApplication batchCaseApplication) { + if(StringUtils.isEmpty(batchCaseApplication.getBatchNumber()) || batchCaseApplication.getAgreeOrNotCheck()==null){ + return error("参数校验失败"); + } + return success(caseApplicationService.submitCaseApplicationCheckBatch(batchCaseApplication.getBatchNumber(),batchCaseApplication.getAgreeOrNotCheck(),batchCaseApplication.getCaseCheckReject())); + } + + /** + * 下载案件压缩包 + */ + @PostMapping("/downloadCaseZipFile") + public AjaxResult downloadCaseZipFile(@Validated @RequestBody CaseApplication caseApplication) { + + CaseAttach caseAttach = caseApplicationService.downloadCaseZipFile(caseApplication); + return success(caseAttach); + } + + + + + + /** + * 发送房间号短信 + */ + @Anonymous + @PostMapping("/sendRoomNoMessage") + public AjaxResult sendRoomNoMessage(@Validated @RequestBody SendRoomNoMessageVO messageVO) { + String result = caseApplicationService.sendRoomNoMessage(messageVO); + return success(result); + } + /** + * 获取UrlScheme + */ + @Anonymous + @GetMapping("/getUrlScheme") + public AjaxResult getUrlScheme() { + String schemeUrl = WxAppletNotifyUtils.jumpAppletSchemeUrl(); + return success(schemeUrl); + } + + /** + * 生成庭审笔录 + * @param arbitrateRecord + * @return + */ + @PostMapping("/creatTrialRecord") +// @PreAuthorize("@ss.hasPermi('caseManagement:list:creatTrialRecord')") + public AjaxResult creatTrialRecord(@Validated @RequestBody ArbitrateRecord arbitrateRecord){ + return caseApplicationService.creatTrialRecord(arbitrateRecord); + } + + /** + * 记录庭审笔录 + * @param arbitrateRecord + * @return + */ + @PostMapping("/creatTrialRecordnew") +// @PreAuthorize("@ss.hasPermi('caseManagement:list:creatTrialRecord')") + public AjaxResult creatTrialRecordnew(@Validated @RequestBody ArbitrateRecord arbitrateRecord){ + return caseApplicationService.creatTrialRecordnew(arbitrateRecord); + } + + /** + * 案件锁定或者解锁 + * @param caseApplication + * @return + */ + @PostMapping("/updateCaseLockStatus") +// @PreAuthorize("@ss.hasPermi('caseManagement:list:creatTrialRecord')") + public AjaxResult updateCaseLockStatus(@Validated @RequestBody CaseApplication caseApplication){ + if(caseApplication.getId()==null || caseApplication.getLockStatus()==null){ + return error("参数校验失败"); + } + return AjaxResult.success(caseApplicationService.updateCaseLockStatus(caseApplication)); + } + + /** + * 查询短信发送记录 + * @param smsSendRecord + * @return + */ + @PostMapping("/smsRecord") + public TableDataInfo getSmsSendRecord(@RequestBody SmsSendRecord smsSendRecord){ + startPage(); + List list = caseApplicationService.getSmsSendRecord(smsSendRecord); + return getDataTable(list); + } + /** + * 获取userSign + * @param userId + * @return + */ + @Anonymous + @GetMapping("/generateUserSign") + public AjaxResult generateUserSign(@RequestParam(required = true) String userId){ + if(StrUtil.isEmpty(userId)){ + error("参数校验失败"); + } + return AjaxResult.success(caseApplicationService.generateUserSign(userId)); + } + /** + * 预约会议 + * @param reservedConferenceVO + * @return + */ + @PostMapping("/reservedConference") + public AjaxResult reservedConference(@Validated @RequestBody ReservedConferenceVO reservedConferenceVO) throws Exception { + + return caseApplicationService.reservedConference(reservedConferenceVO); + } + + /** + * 生成房间号 + * @return + */ + @Anonymous + @GetMapping("/createRoomId") + public AjaxResult createRoomId(@RequestParam("caseId") Long caseId) { + + return success(caseApplicationService.createRoomId(caseId)); + } + /** + * 删除房间号 + * @return + */ + @Anonymous + @PostMapping("/deleteRoom") + public AjaxResult deleteRoom(@RequestParam("roomId") String roomId) { + + return caseApplicationService.deleteRoom(roomId); + } + /** + * 根据案件id查询已预约的会议 + * @param caseId + * @return + */ + @Anonymous + @GetMapping("/reserveConferenceList") + public AjaxResult reserveConferenceList( @RequestParam("caseId") Long caseId) { + + return success(caseApplicationService.reserveConferenceList(caseId)); + } + + /** + * 案件压缩包导入 + * @param file + * @return + * @throws IOException + */ + @PostMapping("/uploadCaseZipFile") + public AjaxResult uploadCaseZipFile(@RequestParam("file") MultipartFile file,@RequestParam("templateId") Long templateId) throws IOException { + return caseApplicationService.uploadCaseZipFile(file,templateId); + } + + /** + * 根据附件id修改案件id + * @param caseAttach + * @return + */ + @PostMapping("/updateCaseIdByAnnexId") + public AjaxResult updateCaseIdByAnnexId(@RequestBody CaseAttach caseAttach) { + if(caseAttach.getAnnexId()==null || caseAttach.getCaseAppliId()==null){ + return error("参数校验失败"); + } + return caseApplicationService.updateCaseIdByAnnexId(caseAttach); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationLogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationLogController.java new file mode 100644 index 0000000..e980e1c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationLogController.java @@ -0,0 +1,107 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.vo.UpdateSubmitVO; +import com.ruoyi.wisdomarbitrate.service.CaseApplicationLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; + +import static com.ruoyi.common.core.domain.AjaxResult.success; + +/** + * @author wangqiong + * @description 案件日志 + * @date 2023-11-17 13:58 + */ +@RestController +@RequestMapping (value = "/caseApplicationLog") +public class CaseApplicationLogController { + + @Autowired + private CaseApplicationLogService caseApplicationLogService; + + /** + * 新增 + * @author wangqiong + * @date 2023/11/17 + **/ + @PostMapping("/insert") + public AjaxResult insert(@RequestBody CaseApplication caseApplicationLog){ + return success(caseApplicationLogService.insert(caseApplicationLog)); + } + + /** + * 刪除 + * @author wangqiong + * @date 2023/11/17 + **/ + @PostMapping("/delete") + public AjaxResult delete(Long id){ + return success(caseApplicationLogService.delete(id)); + } + /** + * 修改的案件提交到秘书 + * @author wangqiong + * @date 2023/11/17 + **/ + @PostMapping("/submit") + public AjaxResult submit(@RequestBody UpdateSubmitVO vo){ + if(vo.getCaseId()==null || vo.getVersion()==null){ + return AjaxResult.error("参数校验错误"); + } + return caseApplicationLogService.submit(vo); + } + + /** + * 修改撤销申请 + * @author wangqiong + * @date 2023/11/17 + **/ + @PostMapping("/revoke") + public AjaxResult revoke(@RequestBody UpdateSubmitVO vo){ + if(vo.getCaseId()==null || vo.getVersion()==null){ + return AjaxResult.error("参数校验错误"); + } + // todo 需确定 + return caseApplicationLogService.revoke(vo); + } + + /** + * 查询 根据主键 id 查询 + * @author wangqiong + * @date 2023/11/17 + **/ + @GetMapping("/selectByCaseIdAndVersion") + public AjaxResult selectByCaseIdAndVersion(@RequestParam(value = "caseId") Long caseId,@RequestParam(value = "version")Integer version ){ + return success(caseApplicationLogService.selectByCaseIdAndVersion(caseId,version)); + } + /** + * 秘书审核修改的案件 + * @author wangqiong + * @date 2023/11/17 + **/ + @PostMapping("/updateAudit") + public AjaxResult updateAudit(@RequestBody UpdateSubmitVO vo){ + if(vo.getCaseId()==null || vo.getVersion()==null || vo.getIsAgree()==null || vo.getUpdateSubmitStatus()==null){ + return AjaxResult.error("参数校验错误"); + } + return caseApplicationLogService.updateAudit(vo); + } + /** + * 查询该版本及之前版本案件进行对比 + * @author wangqiong + * @date 2023/11/17 + **/ + @Anonymous + @PostMapping("/selectCompareCase") + public AjaxResult selectCompareCase(@RequestBody UpdateSubmitVO vo){ + if(vo.getCaseId()==null || vo.getVersion()==null ){ + return AjaxResult.error("参数校验错误"); + } + return caseApplicationLogService.selectCompareCase(vo); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java new file mode 100644 index 0000000..198ccd8 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java @@ -0,0 +1,47 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.collection.CollectionUtil; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.ArbitrateRecord; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseIds; +import com.ruoyi.wisdomarbitrate.service.ICaseArbitrateService; +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.*; + +import java.util.List; + +@RestController +@RequestMapping("/arbitrate") +public class CaseArbitrateController extends BaseController { + @Autowired + private ICaseArbitrateService caseArbitrateService; + + /** + * 审核仲裁方式 + * @param caseApplication + * @param opinion 1同意,0拒绝 + * @return + */ + @PutMapping("/method") +// @PreAuthorize("@ss.hasPermi('caseManagement:list:checkarbitrationway')") + public AjaxResult examineArbitrateMethod(@Validated @RequestBody CaseApplication caseApplication + , Integer opinion, Integer arbitratMethod){ + return caseArbitrateService.examineArbitrateMethod(caseApplication,opinion,arbitratMethod); + } + + /** + * 书面审理 + * @param + * @return + */ + @PostMapping("/writtenHear") + public AjaxResult writtenHear(@RequestBody CaseIds caseIds){ + return caseArbitrateService.writtenHear(caseIds); + + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java new file mode 100644 index 0000000..152aacb --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java @@ -0,0 +1,160 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseEvidenceDirectory; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseEvidenceDTO; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO; +import com.ruoyi.wisdomarbitrate.service.ICaseEvidenceService; +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.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * 案件证据 + */ +@RestController +@RequestMapping("/evidence") +public class CaseEvidenceController extends BaseController { + private final ICaseEvidenceService caseEvidenceService; + + @Autowired + public CaseEvidenceController(ICaseEvidenceService caseEvidenceService) { + this.caseEvidenceService = caseEvidenceService; + } + + /** + * 根据案件id查询案件详情 + * + * @param id + * @return + */ + @GetMapping("/{id}") + public AjaxResult getCaseDetailsById(@PathVariable Long id) { + String username = this.getUsername(); + return caseEvidenceService.getCaseDetailsById(id, username); + } + + /** + * 案件证据上传 + * + * @param file 附件 + * @param annexType 附件类型,立案申请书(1)、证据材料(2)、仲裁文书(3)、案件视频(4)、身份证件(5) + * @param id 案件申请id + * @return + */ + @PostMapping("/upload") + public AjaxResult uploadEvidence(@RequestParam("file") MultipartFile file, Integer annexType, Long id) { + String username = this.getUsername(); + Long userId = this.getUserId(); + return caseEvidenceService.uploadEvidence(file, annexType, id, username, userId); + } + + /** + * 上传庭审笔录 + * + * @param file 附件 + * @param annexType 附件类型,庭审笔录(7) + * @param id 案件申请id + * @return + */ + @PostMapping("/uploadRecord") + public AjaxResult uploadRecord(@RequestParam("file") MultipartFile file, Integer annexType, Long id) { + String username = this.getUsername(); + Long userId = this.getUserId(); + return caseEvidenceService.uploadRecord(file, annexType, id, username, userId); + } + + @PostMapping("/batchUpload") + public AjaxResult batchUpload(@RequestParam("file") MultipartFile[] file, Integer annexType, Long id) { + if(file==null){ + return error("请选择要上传的文件"); + } + String username = this.getUsername(); + Long userId = this.getUserId(); + return caseEvidenceService.batchUpload(file, annexType, id, username, userId); + } + + /** + * 获取附件 + * @param caseAppliId + * @param annexTypeList + * @param + * @return + */ + @GetMapping("/fileList") + public AjaxResult fileList(Long caseAppliId, @RequestParam("annexTypeList") List annexTypeList){ + if(caseAppliId==null){ + return error("案件id不能为空"); + } + return caseEvidenceService.fileList(caseAppliId, annexTypeList); + } + + /** + * 删除附件 + * @param fileIds + * @return + */ + @PostMapping("/deleteFile") + public AjaxResult deleteFile( @RequestParam("fileIds") List fileIds){ + + if(CollectionUtil.isEmpty(fileIds)){ + return error("附件id不能为空"); + } + return toAjax(caseEvidenceService.deleteFile( fileIds)); + } + + + /** + * 查询当前用户案件列表 + * + * @param caseStatus + * @return + */ + @GetMapping("/all") + public AjaxResult getCaseListAll(@RequestParam("caseStatus") Integer caseStatus) { + + return success(caseEvidenceService.getCaseListAll(caseStatus)); + + } + + /** + * 证据确认 + * + * @param caseApplication 案件对象 + * @return 统一返回结果 + */ + @PutMapping("/confirm") + public AjaxResult evidenceConfirmation(@Validated @RequestBody CaseApplication caseApplication) { + return caseEvidenceService.evidenceConfirmation(caseApplication); + } + + /** + * 案件质证 + * + * @param caseEvidenceDTO + * @return + */ + @PostMapping("/crossexami") + public AjaxResult caseCrossexamination(@Validated @RequestBody CaseEvidenceDTO caseEvidenceDTO) { + return caseEvidenceService.caseCrossexamination(caseEvidenceDTO); + } + /** + * 获取证据目录树列表 + */ + @GetMapping("/evidenceTree") + public AjaxResult evidenceTree(CaseEvidenceDirectory caseEvidenceDirectory) + { + return success(caseEvidenceService.selectEvidenceTreeList(caseEvidenceDirectory)) ; + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseLogRecordController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseLogRecordController.java new file mode 100644 index 0000000..e67a1b3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseLogRecordController.java @@ -0,0 +1,40 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.service.ICaseLogRecordService; +import org.springframework.beans.factory.annotation.Autowired; +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 java.util.List; + +@RestController +@RequestMapping("/caseLogRecord") +public class CaseLogRecordController extends BaseController { + @Autowired + private ICaseLogRecordService caseLogRecordService; + + /** + * 查询案件日志列表 + */ +// @PreAuthorize("@ss.hasPermi('caseLog:list')") + @GetMapping("/list") + public AjaxResult list(CaseLogRecord caseLogRecord) + { + List list = caseLogRecordService.selectCaseLogRecordList(caseLogRecord); + return AjaxResult.success(list); + } + + + + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseNumRuleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseNumRuleController.java new file mode 100644 index 0000000..7d453ca --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseNumRuleController.java @@ -0,0 +1,74 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.wisdomarbitrate.domain.CaseNumRule; +import com.ruoyi.wisdomarbitrate.domain.TemplateManual; +import com.ruoyi.wisdomarbitrate.service.ICaseNumRuleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/caseNumRule") +public class CaseNumRuleController extends BaseController { + @Autowired + private ICaseNumRuleService caseNumRuleService; + + /** + * 新增案件编号规则 + * @param caseNumRule + * @return + */ + @PostMapping("/insertCaseNumRule") + public AjaxResult insertCaseNumRule(@RequestBody CaseNumRule caseNumRule){ + caseNumRule.setCreateBy(getUsername()); + return caseNumRuleService.insertCaseNumRule(caseNumRule); + } + + + + /** + * 修改案件编号规则 + * @param caseNumRule + * @return + */ + @PostMapping("/updateCaseNumRule") + public AjaxResult updateCaseNumRule(@RequestBody CaseNumRule caseNumRule){ + return caseNumRuleService.updateCaseNumRule(caseNumRule); + } + + /** + * 删除案件编号规则 + * @param caseNumRule + * @return + */ + @PostMapping("/deleteCaseNumRule") + public AjaxResult deleteCaseNumRule(@RequestBody CaseNumRule caseNumRule){ + return caseNumRuleService.deleteCaseNumRule(caseNumRule); + } + + /** + * 查询案件编号规则 + */ + @GetMapping("/list") + public TableDataInfo list(CaseNumRule caseNumRule) { + startPage(); + List list = caseNumRuleService.selectCaseNumRule(caseNumRule); + return getDataTable(list); + } + + + + + + + + + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java new file mode 100644 index 0000000..15a0cd2 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java @@ -0,0 +1,110 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.collection.CollectionUtil; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseConfirmPayDTO; +import com.ruoyi.wisdomarbitrate.service.ICasePaymentService; +import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * 缴费支付 + */ +@RestController +@RequestMapping("/pay") +public class CasePaymentController { + private final ICasePaymentService paymentService; + @Autowired + public CasePaymentController(ICasePaymentService paymentService){ + this.paymentService=paymentService; + } + /** + * 案件缴费 + * @param casePayDTO 缴费传入参数 + * @return 统一响应结果 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:pay')") + @PostMapping("/casePay") + public AjaxResult casePay(@Validated @RequestBody CasePayDTO casePayDTO) { + return paymentService.casePay(casePayDTO); + } + /** + * 确认缴费 + * @param payDTO 缴费传入参数 + * @return 统一响应结果 + */ +// @PreAuthorize("@ss.hasPermi('caseManagement:list:pay')") + @PostMapping("/confirmPay") + public AjaxResult confirmPay(@Validated @RequestBody CaseConfirmPayDTO payDTO) { + return paymentService.confirmPay(payDTO); + } + + /** + * 批量缴费 + * @param casePayDTO 缴费传入参数 + * @return 统一响应结果 + */ + @PostMapping("/casePayBatch") + public AjaxResult casePayBatch(@Validated @RequestBody CasePayDTO casePayDTO) { + return paymentService.casePayBatch(casePayDTO); + } + + /** + * 批量缴费 + * @param payDTO 缴费传入参数 + * @return 统一响应结果 + */ + @PostMapping("/confirmPayBatch") + public AjaxResult confirmPayBatch(@Validated @RequestBody CasePayDTO payDTO) { + return paymentService.confirmPayBatch(payDTO); + } + + /** + * 缴费确认 + * @param batchCaseApplication + * @return + */ +// @PreAuthorize("@ss.hasPermi('paymentManagement:list:payconfirm')") + @PutMapping("/confirm") + public AjaxResult confirmPayment(@Validated @RequestBody BatchCaseApplication batchCaseApplication) { + if(CollectionUtil.isEmpty(batchCaseApplication.getIds())){ + return AjaxResult.error("参数校验失败"); + } + return paymentService.confirmPayment(batchCaseApplication.getIds()); + } + /** + * 缴费列表查询 + * @param casePayDTO + * @return + */ + @GetMapping("/list") + public AjaxResult casePayList(CasePayDTO casePayDTO) { + return paymentService.casePayList(casePayDTO); + } + + @PostMapping("/listBatch") + public AjaxResult casePayListBatch(@Validated @RequestBody CasePayDTO casePayDTO) { + return paymentService.casePayListBatch(casePayDTO); + } + + /** + * 批量缴费确认 + * @param batchCaseApplication + * @return + */ + @PostMapping("/confirmBatch") + public AjaxResult confirmPaymentBatch(@Validated @RequestBody BatchCaseApplication batchCaseApplication) { + if(StringUtils.isEmpty(batchCaseApplication.getBatchNumber())){ + return AjaxResult.error("参数校验失败"); + } + return paymentService.confirmPaymentBatch(batchCaseApplication.getBatchNumber()); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/DeptIdentifyController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/DeptIdentifyController.java new file mode 100644 index 0000000..47b916a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/DeptIdentifyController.java @@ -0,0 +1,237 @@ +package com.ruoyi.web.controller.wisdomarbitrate; +import cn.hutool.core.util.StrUtil; +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.exception.EsignDemoException; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.SealListVO; +import com.ruoyi.wisdomarbitrate.service.IDeptIdentifyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("/deptIdentify") +public class DeptIdentifyController extends BaseController { + @Autowired + private IDeptIdentifyService deptIdentifyService; + + /** + * 新增机构 + * @param deptIdentify + * @return + */ + @PostMapping("/insert") + public AjaxResult insertDeptIdentify(@RequestBody DeptIdentify deptIdentify){ + return deptIdentifyService.insertDeptIdentify(deptIdentify); + } + + /** + * 删除机构 + * @param id + * @return + */ + @DeleteMapping("/delete") + public AjaxResult deleteDeptIdentify(Long id){ + return deptIdentifyService.deleteDeptIdentify(id); + } + + /** + * 修改机构信息 + * @param deptIdentify + * @return + */ + @PutMapping("/update") + public AjaxResult updateDeptIdentify(@RequestBody DeptIdentify deptIdentify){ + return deptIdentifyService.updateDeptIdentify(deptIdentify); + } + + /** + * 查询机构信息 + */ + @GetMapping("/list") + public TableDataInfo list(DeptIdentify deptIdentify) { + startPage(); + List list = deptIdentifyService.selectDeptIdentify(deptIdentify); + return getDataTable(list); + } + + /** + * 查询机构认证链接 + */ + @PostMapping("/selectDeptIndefiUrl") + public AjaxResult selectDeptIndefiUrl(@Validated @RequestBody DeptIdentify deptIdentify) throws EsignDemoException { + DeptIdentify deptIdentifyselect = deptIdentifyService.selectDeptIndefiUrl(deptIdentify); + return success(deptIdentifyselect); + } + + /** + * 机构启用/禁用 + */ + @PostMapping("/enableDept") + public AjaxResult enableDept(@Validated @RequestBody DeptIdentify deptIdentify) { + return deptIdentifyService.enableDept(deptIdentify); + } + + /** + * 上传自定义公章 + * + * @param + * @param file + * @return + */ + @PostMapping("/sealUpload") + public AjaxResult sealUpload(Long id, String sealName , @RequestParam("file") MultipartFile file) { + return deptIdentifyService.sealUpload(id, sealName ,file); + } + + /** + * 接收E签宝回调通知 + * @param body + * @return + */ + @GetMapping("/notify") + public AjaxResult receiveNotify(String body) { + return deptIdentifyService.receiveNotify(body); + } + + /** + * 公章列表查询 + * @param deptIdentify + * @return + */ + @GetMapping("/sealList") + public TableDataInfo getSealList( DeptIdentify deptIdentify ){ + startPage(); + List sealList = deptIdentifyService.getSealList(deptIdentify); + return getDataTable(sealList); + } + + /** + * 印章启用或者禁用 + * @param sealManage + * @return + */ + @PostMapping("/updateSealLockStatus") + public AjaxResult updateSealLockStatus(@Validated @RequestBody SealManage sealManage){ + if(sealManage.getId()==null ||sealManage.getIsUse()==null){ + return error("参数校验失败"); + } + return deptIdentifyService.updateSealLockStatus(sealManage); + } + + /** + * 新增模板 + * @param templateManage + * @return + */ + @PostMapping("/insertTemplate") + public AjaxResult insertTemplate(TemplateManage templateManage,@RequestParam("file") MultipartFile file){ + return deptIdentifyService.insertTemplate(templateManage,file); + } + /** + * 修改模板 + * @param templateManage + * @return + */ + @PostMapping("/updateTemplate") + public AjaxResult updateTemplate(TemplateManage templateManage,@RequestParam(value = "file", required = false) MultipartFile file){ + return deptIdentifyService.updateTemplate(templateManage,file); + } + + /** + * 删除模板 + * @param id + * @return + */ + @DeleteMapping("/deleteTemplate") + public AjaxResult deleteTemplate(Long id){ + return deptIdentifyService.deleteTemplate(id); + } + + /** + * 根据机构id查询模板 + * @param deptIdentify + * @return + */ + @GetMapping("/getTemplate") + public TableDataInfo getTemplateList( DeptIdentify deptIdentify){ + startPage(); + List sealList = deptIdentifyService.getTemplateList(deptIdentify); + return getDataTable(sealList); + } + /** + * 根据部门id查询岗位用户信息 + */ + @GetMapping("selectPostUserByDeptId") + public AjaxResult selectPostUserByDeptId(DeptIdentify deptIdentify){ + return AjaxResult.success(deptIdentifyService.selectPostUserByDeptId(deptIdentify)); + } + /** + * 给机构绑定经办人 + */ + @GetMapping("bindHandler") + public AjaxResult bindHandler(DeptIdentify deptIdentify){ + return deptIdentifyService.bindHandler(deptIdentify); + } + + /** + * 根据模板id查询抓取规则 + * @param templateManage + * @return + */ + @PostMapping("/getFatchRuleByTemplateid") + public AjaxResult getFatchRuleByTemplateid(@RequestBody TemplateManage templateManage){ + List fatchRuleList = deptIdentifyService.getFatchRuleByTemplateid(templateManage); + return AjaxResult.success(fatchRuleList); + } + + /** + * 保存抓取规则 + * @param templateManage + * @return + */ + @PostMapping("/saveFatchRules") + public AjaxResult saveFatchRules(@RequestBody TemplateManage templateManage){ + return deptIdentifyService.saveFatchRules(templateManage); + } + + /** + * 查询column和注释 + * @return + */ + @PostMapping("/selectColumnandComment") + public AjaxResult selectColumnandComment(){ + List fatchRuleList = deptIdentifyService.selectColumnandComment(); + return AjaxResult.success(fatchRuleList); + } + + /** + * 查询column + * @return + */ + @PostMapping("/selectColumnbycomment") + public AjaxResult selectColumnbycomment(@RequestBody FatchRule fatchRule){ + FatchRule fatchRulesel = deptIdentifyService.selectColumnbycomment(fatchRule); + return AjaxResult.success(fatchRulesel); + } + + /** + * 根据模板id查询模板字段列表 + * @param id + * @return + */ + @GetMapping("/getTemplateInfoById") + public AjaxResult getTemplateInfoById(@RequestParam("id") Long id){ + TemplateManage templateManage = new TemplateManage(); + templateManage.setId(id); + List fatchRuleList = deptIdentifyService.getTemplateInfoById(templateManage); + return AjaxResult.success(fatchRuleList); + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/IdentityAuthenticationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/IdentityAuthenticationController.java new file mode 100644 index 0000000..8e5f347 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/IdentityAuthenticationController.java @@ -0,0 +1,43 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.service.IdentityAuthenticationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/identityAuthentication") +public class IdentityAuthenticationController extends BaseController { + @Autowired + private IdentityAuthenticationService identityAuthenticationService; + + /** + * 获取EIDtoken + */ + @Anonymous + @PostMapping("/selectIdentityAuthenticaEIDtoken") + public AjaxResult selectIdentityAuthenticaEIDtoken() { + JSONObject tokenResult = identityAuthenticationService.selectIdentityAuthenticaEIDtoken(); + return success(tokenResult); + } + + /** + * 小程序人脸核身后查询身份认证结果 + */ + @Anonymous + @PostMapping("/selectIdentityAuthenticaRespon") + public AjaxResult selectIdentityAuthenticaRespon(@Validated @RequestBody IdentityAuthentication ientityAuthentication) { + AjaxResult checkResult = identityAuthenticationService.selectIdentityAuthenticaRespon(ientityAuthentication); + return checkResult; + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/SendMailRecordController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/SendMailRecordController.java new file mode 100644 index 0000000..cc9ac35 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/SendMailRecordController.java @@ -0,0 +1,48 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.domain.SendMailRecord; +import com.ruoyi.wisdomarbitrate.service.ISendMailRecordService; +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 java.util.List; + +@RestController +@RequestMapping("/sendMailRecord") +public class SendMailRecordController extends BaseController { + @Autowired + private ISendMailRecordService sendMailRecordService; + + /** + * 查询发送邮件记录列表 + */ + @GetMapping("/list") + public TableDataInfo list(SendMailRecord sendMailRecord) + { + startPage(); + List list = sendMailRecordService.selectSendMailRecordList(sendMailRecord); + return getDataTable(list); + } + + +// /** +// * 新增立案数据 +// */ +// @Log(title = "新增立案数据", businessType = BusinessType.INSERT) +// @PostMapping("/addSendMailRecord") +// public AjaxResult addSendMailRecord(@Validated @RequestBody SendMailRecord sendMailRecord) +// { +// +// return toAjax(sendMailRecordService.addSendMailRecord(sendMailRecord)); +// } + + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/TemplateController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/TemplateController.java new file mode 100644 index 0000000..78b5db1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/TemplateController.java @@ -0,0 +1,59 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.wisdomarbitrate.domain.DeptIdentify; +import com.ruoyi.wisdomarbitrate.domain.TemplateManual; +import com.ruoyi.wisdomarbitrate.service.ITemplateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/template") +public class TemplateController extends BaseController { + @Autowired + private ITemplateService templateService; + /** + * 新增模板 + * @param templateManual + * @return + */ + @PostMapping("/insert") + public AjaxResult insertTemplate(@RequestBody TemplateManual templateManual){ + return templateService.insertTemplate(templateManual); + } + + /** + * 删除模板 + * @param id + * @return + */ + @DeleteMapping("/delete") + public AjaxResult deleteTemplate(Long id){ + return templateService.deleteTemplate(id); + } + + /** + * 修改模板 + * @param templateManual + * @return + */ + @PutMapping("/update") + public AjaxResult updateTemplate(@RequestBody TemplateManual templateManual){ + return templateService.updateTemplate(templateManual); + } + + /** + * 查询模板 + */ + @GetMapping("/list") + public TableDataInfo list( TemplateManual templateManual) { + startPage(); + List list = templateService.selectTemplate(templateManual); + return getDataTable(list); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/VideoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/VideoController.java new file mode 100644 index 0000000..db1f865 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/VideoController.java @@ -0,0 +1,149 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; +import com.ruoyi.wisdomarbitrate.service.VideoService; +import com.ruoyi.wisdomarbitrate.service.WeChatUserService; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.trtc.v20190722.TrtcClient; +import com.tencentcloudapi.trtc.v20190722.models.*; +import com.tencentyun.TLSSigAPIv2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.io.IOException; + +/** + * @author wangqiong + * @description trtc实时音视频 + * @date 2023-10-26 11:25 + */ +@RestController +@RequestMapping("/video") +public class VideoController extends BaseController { + @Autowired + private VideoService videoService; + + /** + * 从腾讯云下载文件到本地 + * @param + * @return + */ + @Anonymous + @PostMapping("/videoRollBack") + public AjaxResult videoRollBack( @RequestBody String body, HttpServletRequest request) { + videoService.videoRollBack(body,request); + return success(); + } + /** + * 根据房间号绑定案件ID + * @param + * @return + */ + @Anonymous + @PostMapping("/bindCaseId") + public AjaxResult bindCaseId(@Valid @RequestBody SendRoomNoMessageVO vo) { + + return videoService.bindCaseId(vo.getId(),vo.getRoomNo()); + } + /** + * 根据案件ID查询视频 + * @param caseId 案件id + * @return + */ + @GetMapping("/videoList") + public AjaxResult videoList( @RequestParam Long caseId) { + + return videoService.videoList(caseId); + } + /** + * 开启腾讯云录制 + * @param vo + * @return + * @throws Exception + */ + @Anonymous + @PostMapping("/openCloudRecording") + private AjaxResult openCloudRecording( @RequestBody ReservedConferenceVO vo) { + if(vo.getCaseId()==null || vo.getRoomId()==null){ + return AjaxResult.error("参数错误"); + } + return videoService.openCloudRecording(vo.getCaseId(),vo.getRoomId()); + } + /** + * 关闭腾讯云录制 + * @param taskId 任务ID + * @return + */ + @Anonymous + @PostMapping("/closeDeleteCloudRecording") + public AjaxResult closeDeleteCloudRecording(@RequestParam("taskId") String taskId){ + return videoService.closeDeleteCloudRecording(taskId); + } + /** + * 解散房间 + * @param reservedConferenceVO + * @return + */ + @Anonymous + @PostMapping("/dissolveRoom") + public AjaxResult dissolveRoom( @RequestBody ReservedConferenceVO reservedConferenceVO) { + if( reservedConferenceVO.getRoomId()==null){ + return error("参数校验失败"); + } + + return videoService.dissolveRoom(reservedConferenceVO.getRoomId()); + } + /** + * 根据userId查询该用户是否是秘书 + * @param userId + * @return + */ + @Anonymous + @GetMapping("secretaryRoleByUserId") + public AjaxResult secretaryRoleByUserId( @RequestParam(value = "userId",required = true) Long userId) { + + return videoService.secretaryRoleByUserId(userId); + } + /** + * 根据html字符串转pdf并和案件关联 + * @param reservedConferenceVO + * @return + */ + @Anonymous + @PostMapping("htmlToPDF") + public AjaxResult secretaryRoleByUserId( @RequestBody ReservedConferenceVO reservedConferenceVO) { + if( reservedConferenceVO.getCaseId()==null || StrUtil.isEmpty(reservedConferenceVO.getHtmlContent())){ + return success(); + } + + return videoService.htmlToPDF(reservedConferenceVO); + } + /** + * 根据案件id和类型查询附件 + * @param caseAppliId + * @param annexType + * @return + */ + + @GetMapping("attachListByCaseId") + public AjaxResult attachListByCaseId( @RequestParam("caseAppliId") Long caseAppliId,@RequestParam("annexType") Integer annexType) { + + return videoService.attachListByCaseId(caseAppliId,annexType); + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/WeChatUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/WeChatUserController.java new file mode 100644 index 0000000..9f5f6f7 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/WeChatUserController.java @@ -0,0 +1,62 @@ +package com.ruoyi.web.controller.wisdomarbitrate; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.http.HttpUtils; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; +import com.ruoyi.wisdomarbitrate.service.WeChatUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author wangqiong + * @description 微信小程序用户注册登录 + * @date 2023-10-16 11:25 + */ +@RestController +@RequestMapping("/weChatUser") +public class WeChatUserController extends BaseController { + @Autowired + private WeChatUserService weChatUserService; + + /** + * 小程序端获取手机验证码 + * @param userVO + * @return + */ + @Anonymous + @GetMapping("/sendCode") + public AjaxResult sendCode( WeChatUserVO userVO) + { + if(StrUtil.isEmpty(userVO.getPhone())){ + return warn("手机号不能为空"); + } + return weChatUserService.sendCode(userVO); + } + /** + * 小程序注册 + */ + @Anonymous + @PostMapping("/registerUser") + public AjaxResult registerUser( @RequestBody IdentityAuthentication ientityAuthentication) { + if(ientityAuthentication.getId()==null + || StrUtil.isEmpty(ientityAuthentication.getName()) + || StrUtil.isEmpty(ientityAuthentication.getIdentityNo()) + || StrUtil.isEmpty(ientityAuthentication.getPhone()) + || StrUtil.isEmpty(ientityAuthentication.getUserName()) + || StrUtil.isEmpty(ientityAuthentication.getEmail()) + || StrUtil.isEmpty(ientityAuthentication.getVerifyCode()) + ){ + return warn("参数校验失败"); + } + logger.info("调用小程序注册==="+ientityAuthentication.toString()); + return weChatUserService.registerUser(ientityAuthentication); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java new file mode 100644 index 0000000..ae1c3ec --- /dev/null +++ b/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/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000..2b23f85 --- /dev/null +++ b/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/ruoyi-admin/src/main/resources/alipay_private.key b/ruoyi-admin/src/main/resources/alipay_private.key new file mode 100644 index 0000000..6a4759b --- /dev/null +++ b/ruoyi-admin/src/main/resources/alipay_private.key @@ -0,0 +1 @@ +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQC12YM9mR+HFQYTx/fHKHZbgszVtDHDB0B/ysWl3MbcPpGtjcZlDr5aynRMRLaoduRHT++A98IaNVIVGj9RHdXrX2j9I/Uz6fYDH63cdu6FZ6Pk82yPwNZW7pebprbVHInR/7gzsKQWSWEST70BgjCRqlbfAE6xzUZFTeYxciCjptm0rUQ2MC24xRdkvZByIDIYFnQ/AdmSFqNtKDR2WpEV/M8aBjyuPPomRJZ1X8oudWuJIU4ySdas04fCbDxD10TY/wyQcDHXuG1IrQpXme4DOGQeJZ0/aOFphBkDFUyPGfYMmLshOPNdBKi2IqWHPPs4XsV4Rv6+tvTSnMF2uGqHAgMBAAECggEAPa1sifPpcZN74DGupGng2uDeQI1BY3iOM8m+h6b9+61tE4RGifgaMAkCsOuNWE4a1uURwphFyUXUdTvVxdlsuMw/e7w6akUsH5sbCO99rtmcCQdXBtrM1+dMnIpK8LUhOYyWGVIMFVMGDYPmAyD5AC7aEAC2sC+DafYl4RdoYpidq1YxeE7DVw1aQHCI2mKhYjZG+3RDDGDfNFvdyH61MgdYjoGkeXNvARzEXgfWvfiTrHZ3H1SYgvOEHofzKDTrWsQL2dvaEsc55Jiw0AgNUVcgby7al8PUekTJoK3ZvrE3pSWaUirBcqsqWISHjeR7Xx501CHIha8EnZwlnDoM4QKBgQDtnYzwQ5mHg7cRHD8Z6QdTpvBvYSEPesiUT/HeI+AKQKDCVJxKiLvJagc6zZkOzV9bZDS/WLgzXWMyxUb+OTjht0jLWAMcf7NfFp3tPKq9wkmQQ/vQSBQ1lFmO6A4Zq1eoGKeUCB4pKBG6cSM+t8+ruhm7s1ZUt+6EBwCVN/izrQKBgQDD62jIm+6NFErdidUaIrGiFUrzqdR13w6JOexfk+O6Aau3wRqsr7Wz4nqQvVVxGMRpXbOH06zpeiS+vMmjwgO973VoLAmH+hJ0GZz8qj3zA2GEOFWjD2V7tqeRvGkQvz0v46pl+8sBJkrRHLN7DWNYY5NDI+b7exwqcTc/LL19gwJ/a6r4MeZvqvgD+7zQ2uy8ZSs/xzg7wsfgG1QeRIn8+qhOL8AnEZ7jeGCS5hJDSHHGw6KkRA/vZ1bpnBfIE2naXGywj3NR9Zfnry6QYO8cbt+adcRYVghTH/QYoKiFuxvonEKPrIQBJqUBY3ngforLjwTEpEie1cSCT1Dc8sBp8QKBgQCaz8fqzRyBKknGKQXVMxj+JKknRUl3IpzP3o9jLu9BqdRQzSwQzH9d91Y2TQXY6mM5hys35xG5JCUo+vCyj7p5OWCiwjl90yMFzr93/+YXwtIpsoIo6R+d1EUxKZoz+4mT7+hT0dUlwWZZOr6wO3IHBBf3c8UvbqZg+zlWmDnblQKBgEs6jwMkb5zaG2fyBJ7PJUN/8nIz8V+X0SxQfcEqIX0J+EC+7MAgFjcdZFp+lca3Vd9z+8Ksd4rMzMa5y856ositL2NZ+K0fs8i8EBaQPny61OgCFUuXEuv5keB2YuGMSns5FYRWuByrtDXl4PxzKXvq05iKWLKCaCq9v4momvKZ \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/alipay_public.key b/ruoyi-admin/src/main/resources/alipay_public.key new file mode 100644 index 0000000..21236fb --- /dev/null +++ b/ruoyi-admin/src/main/resources/alipay_public.key @@ -0,0 +1 @@ +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhUnjdAKwZApwZEcfq+5L0pa77Vg3mqcoXv+th8RR0SYotkPsH1f2JkbS48ySaSCM6YNWSMNfqp5qdOla2zUJOBnJ/yaBg7s7fVD6V3M2mEog8kCDYGKt/3P4VII3xYl8lFYMQ3IcFRELkxCBBCA8JDKmf5z2R4F/Z/jFFEuOwxaJvp+7Ke9OzZHYdWGNnU6QP8YYLYUeX7VNZLHEuly34ExAw6A+yJkNDsYEho2Lu31QjT2pLh9g+88MlRfiI92iN25O9NVdeM4f5RcpvBPrBQZQs9tlFmALYSFS3prIf3FAobWM+W7iwxT6J25nFIhst1DdJQfIBpaeRUJVTkn99QIDAQAB \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml new file mode 100644 index 0000000..fb697f9 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -0,0 +1,61 @@ +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://121.40.189.20:3306/test_smart_arbitration?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai&useSSL=false + username: root + password: YMzc157# + # 从库数据源 + 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/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml new file mode 100644 index 0000000..22aa6db --- /dev/null +++ b/ruoyi-admin/src/main/resources/application.yml @@ -0,0 +1,197 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.8.6 + # 版权年份 + copyrightYear: 2023 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: /home/ruoyi/uploadPath + # 获取ip地址开关 + addressEnabled: false + # 验证码类型 math 数字计算 char 字符验证 + captchaType: math + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 8001 + servlet: + # 应用的访问路径 + context-path: / + 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: 50MB + # 设置总上传的文件大小 + max-request-size: 500MB + # 服务模块 + devtools: + restart: + # 热部署开关 + enabled: true + # redis 配置 + redis: + # 地址 + host: 121.40.189.20 + # 端口,默认为6379 + port: 6389 + # 数据库索引 + database: 0 + # 密码 + password: + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + web: + resources: + static-locations: file:/home/ruoyi/ + mail: + host: smtp.163.com + port: 25 + username: lmj1549843951@163.com + password: JGIOQVFCLAZKXRKO + default-encoding: UTF-8 + properties: + mail: + smtp: + connectiontimeout: 5000 + timeout: 5000 + writetimeout: 5000 + socketFactoryClass: javax.net.ssl.SSLSocketFactory + socketFactoryFallback: false + socketFactoryPort: 465 + debug: false + protocol: smtp +#上上签配置参数 +ssq: + developerId: 1695872832013855470 + privateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiDRuz+dxqkWqHdov0hK+KEWLw/e8MQSqkZZ4c01Yr6cSmQiWyV8Xin0u5S/EA02FWxpjLi1nLriVtOBhZGsoryFmcJrwzSnQ5PORP/HhfcAWFE/Y+3qSQS1OiU7e5wbReCgEUvx4GHZuhdu8cOvq5DG9l33YFZrIEMBTmnf8eKT54STx0tjcKl7U6B6nsiThy3zVtpWXVv6H1HGmxC0KT4EQ388s/PFjrwmk+GFb3EpKCns/GQHf7QrtNz1ZOgCXfgQiQ+91/tcngzUH+zMCIxn5lS+ENAxVI6Ev3W9Y0QHtKwmO4ORVuAskJYzBB2xKI/gw8+PUXNziMAKXuoUAjAgMBAAECggEAd7yHw6vTGUrpE76cGsgPjEzcdoSqpLth7qbG9TWSblAEZXRqtiP0q0ZYhUl/gcSuH5gOPhdw+fZq4RCZrP0GdONMkvxsAtn4lnJPoGpD5wC2k2X0hO+tWJDP8xk4n6BozTNHKTUt0gb+f4eJlapep2xwwy0h30vKLR3504zafEV9j/2D8l5TFSv6rd3UVxUvrDKQ9mhfATEUlrTpjs0SfWupMkr4j7TuJJ8qSUSiEADe4hyUB6+LouDZCt8jV4aLojQBJKrQ6VPVdDFkHGsePu4tHtvcKsaOZJ0pjpJ7MT6D5ElD/sJjo0g/3qK5/FToVFVbrxtykVreK6mE5oSTQQKBgQDpEFSgH1d4N7NsZhviaCIUkB97hO0jpRbD7UZirzZ9ok96Fk+SmfhdmypDMoiaRHCNhQuu5dI9mg5RbUhz9mCZnAhzJRL+DmE4bhNvQmbtJA7KT6n/AdH2zy0mYulrcG17dQspvTr/5421PTEE2+FRoCbG6hBsSSUit9HLvAU13QKBgQCx/7ql+hbx+t0Yb02XckBHiA+MWrFLO4dMX9cKf3LldC0nhn0K9HOSoZmM0KcmXRnMo+/4t89xOJRl7JRXwcLoy/64OaUBVv+8FFV1yY4THka3nEnQE40vVWy+vuNJtt+eKlEhJ35N1GIHXo7/4j0POtEuNU7KSqMnLUD+Oy/t/wKBgEiajcJUASuyLnLWXFlrlzJQs34HKtiv1Se0Avk7G/6HUbr2uFMzI+wFKmVEmMl2CJoNmFYjwhruowc6xBdb6TvxH7C/G+uJD0BFCkjeprG5SeI8bvjB2GbKo4YRyiVuIK0VCSU3jemqeLq9FUguN0L2YR4WTIdvQeJO4UxWhkkBAoGBAJk7TxDHZK1XirIYTzGK928c4FWxVWMwkd7buqGc6epBwwV9r3OY0U1vtGIW1W4fQ7B5iIISqpALZyT/Lw0FDqedxWAOr8+hd3IQBynpI1et/q7d6mUoD6ip332tkrjIp2TfhQwHlaGmreUuL+h0eJ/9wEoJNhTLf/yf5o11omM9AoGBAOLVlXR9FbU2Ubpp3HwTumSzKDWzq3T5eQcqC1zE3BPOo29uAf9BQTumPxe51U64egttW/nif5FH4v4Gentmxb2B2ckdOs/u9zIWz3JPfHU7RqMyMokuWrQ6lMoiSYpH3MSHoavLyAEhAnpceX3oktXgpYHO9d8MfON3XKJl23ip + serverHost: https://openapi.bestsign.info/openapi/v2/ + +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 30 + +# MyBatis配置 +mybatis: + # 搜索指定包别名 + typeAliasesPackage: com.ruoyi.**.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: /dev-api + +# 防止XSS攻击 +xss: + # 过滤开关 + enabled: true + # 排除链接(多个用逗号分隔) + excludes: /system/notice + # 匹配链接 + urlPatterns: /system/*,/monitor/*,/tool/* +#支付相关配置 +elegent: + pay: + wxpay: + mchId: 1561414331 + appId: wx6592a2db3f85ed25 + appSecret: d9a9ff00a633cd7353a8925119063b01 + mchSerialNo: 25FBDE3EFD31B03A4377EB9A4A47C517969E6620 + apiV3Key: CZBK51236435wxpay435434323FFDuv3 + alipay: + appId: 2021003141676135 + callback: + domain: http://121.40.189.20:9001/ + watch: true + cycle: 10 +identityAuthentication: + credentialSecretId: AKID3xfHgroY4MQHvLXUXMwIQL1UjmbBX1Tv + credentialSecretKey: INDrIXcT8YmomZBcsy0oNirnU0LTN4X7 + merchantId: 0NSJ2309281116194321 + privateKeyHexDecodeinfo: 4c3b311bf7b98969994e85928e069574a1e95777f24d1c510679cc3c2f460faf +# 腾讯云即时通信相关配置 +imConfig: + # sdkAppId + sdkAppId: 1600011167 + # 密钥 + sdkSecretKey: 17d136d9327576a247f991bdfed3a6d14cebc7d540a52245086829c3a1421a86 + # 腾讯云账户 SecretId + secretId: AKID3xfHgroY4MQHvLXUXMwIQL1UjmbBX1Tv + # 腾讯云密钥 + secretKey: INDrIXcT8YmomZBcsy0oNirnU0LTN4X7 +#jodconverter: +# local: +# host: 121.40.189.20 + #暂时关闭预览,启动时会有点慢 +# enabled: true + #设置libreoffice主目录 linux地址如:/usr/lib64/libreoffice +# office-home: /usr/lib64/libreoffice/ +# office-home: D:\app\libreOffice\ + #开启多个libreoffice进程,每个端口对应一个进程 +# port-numbers: 8100 + #libreoffice进程重启前的最大进程数 +# max-tasks-per-process: 100 diff --git a/ruoyi-admin/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt new file mode 100644 index 0000000..0931cb8 --- /dev/null +++ b/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/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..93de005 --- /dev/null +++ b/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/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml new file mode 100644 index 0000000..a360583 --- /dev/null +++ b/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/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..ac47c03 --- /dev/null +++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-admin/src/main/resources/wxpay_private.key b/ruoyi-admin/src/main/resources/wxpay_private.key new file mode 100644 index 0000000..d4be12f --- /dev/null +++ b/ruoyi-admin/src/main/resources/wxpay_private.key @@ -0,0 +1 @@ +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBHGgIh80193GhdpD1LtMZfTRpcWI0fImyuBCyrd3gYb3rrsARebGcHdJsQA3mVjVqVp5ybhEZDPa4ecoK4Ye1hTppNpI/lmLt4/uUV/zhF5ahli7hi+116Ty6svHSbuMQBuUZeTFOwGrxjvofU/4pGIwh8ZvkcSnyOp9uX2177UVxDBkhgbZbJp9XF2b83vUa5eHo93CziPzn3hFdAlBCdTXB7DH+m0nN3Jou0szGukvq7cIgGpHku4ycKSTkIhhl9WRhN6OoSEJxq88MXzjkzTruc85PHN52aUTUifwg3T8Y4XqFQ61dTnEmgxeD2O6/pLdB9gLsp6yCGqN5Lqk7AgMBAAECggEBAL4X+WzUSbSjFS9NKNrCMjm4H1zgqTxjj6TnPkC1mGEltjAHwLgzJBw62wWGdGhWWpSIGccpBBm1wjTMZpAZfF66fEpP1t1Ta6UjtGZNyvfFIZmE3jdWZ/WXGBnsxtFQKKKBNwrBW0Fbdqq9BQjLxLitmlxbmwrgPttcy855j6vZqq4MBT1v8CtUT/gz4UWW2xWovVnmWOrRSScv7Nh0pMbRpPLkNHXrBwSSNz/keORzXB9JSm85wlkafa7n5/IJbdTml3A/uAgW3q3JZZQotHxQsYvD4Zb5Cnc9CPAXE5L2Yk877kVXZMGt5QPIVcPMj/72AMtaJT67Y0fN0RYHEGkCgYEA38BIGDY6pePgPbxB7N/l6Df0/OKPP0u8mqR4Q0aQD3VxeGiZUN1uWXEFKsKwlOxLfIFIFk1/6zQeC0xetNTKk0gTL8hpMUTNkE7vI9gFWws2LY6DE86Lm0bdFEIwh6d7Fr7zZtyQKPzMsesC3XV9sdSUExEi5o/VwAyf+xZlOXcCgYEA3PGZYlILjg3esPNkhDz2wxFw432i8l/BCPD8ZtqIV9eguu4fVtFYcUVfawBb0T11RamJkc4eiSOqayC+2ehgb+GyRLJNK4FqbFcsIT+CK0HlscZw51jrMR0MxTc4RzuOIMoYDeZqeGB6/YnNyG4pw2sD8bIwHm8406gtJsX/v10CgYAo8g3/aEUZQHcztPS3fU2cTkkl0ev24Ew2XGypmwsX2R0XtMSBuNPNyFHyvkgEKK2zrhDcC/ihuRraZHJcUyhzBViFgP5HBtk7VEaM36YzP/z9Hzw7bqu7kZ85atdoq6xpwC3Yn/o9le17jY8rqamD1mv2hUdGvAGYsHbCQxnpBwKBgHTkeaMUBzr7yZLS4p435tHje1dQVBJpaKaDYPZFrhbTZR0g+IGlNmaPLmFdCjbUjiPyA2+Znnwt227cHz0IfWUUAo3ny3419QkmwZlBkWuzbIO2mms7lwsf9G6uvV6qepKMeVd5TWEsokVbT/03k27pQmfwPxcK/wS0GFdIL/udAoGAOYdDqY5/aadWCyhzTGI6qXPLvC+fsJBPhK2RXyc+jYV0KmrEv4ewxlK5NksuFsNkyB7wlI1oMCa/xB3T/2vTBALgGFPi8BJqceUjtnTYtI4R2JIVEl08RtEJwyU5JZ2rvWcilsotVZYwfuLZ9KfdhkTrgNxlp/KKkr+UuKce4Vs= \ No newline at end of file diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml new file mode 100644 index 0000000..a84dbae --- /dev/null +++ b/ruoyi-common/pom.xml @@ -0,0 +1,290 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-common + + + + common通用工具 + + + + + + + org.apache.poi + poi-ooxml + 4.1.2 + + + + + + org.apache.poi + poi-scratchpad + 4.1.1 + + + + commons-io + commons-io + 2.6 + + + org.jodconverter + jodconverter-core + 4.2.0 + + + org.jodconverter + jodconverter-local + 4.2.0 + + + org.jodconverter + jodconverter-spring-boot-starter + 4.2.0 + + + com.artofsolving + jodconverter + 2.2.1 + + + org.openoffice + jurt + 3.0.1 + + + org.openoffice + ridl + 3.0.1 + + + org.openoffice + juh + 3.0.1 + + + org.openoffice + unoil + 3.0.1 + + + + + + + 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.projectlombok + lombok + 1.18.22 + + + + + com.tencentcloudapi + tencentcloud-sdk-java + 3.1.876 + + + + com.tencentcloudapi + tencentcloud-sdk-java-faceid + 3.1.875 + + + + cn.hutool + hutool-all + 5.7.15 + + + + org.bouncycastle + bcprov-jdk15to18 + 1.69 + + + + + com.deepoove + poi-tl + 1.9.1 + + + + com.documents4j + documents4j-local + 1.0.3 + + + com.documents4j + documents4j-transformer-msoffice-word + 1.0.3 + + + org.apache.pdfbox + pdfbox + 2.0.27 + + + + + com.itextpdf + itextpdf + 5.5.13 + + + com.itextpdf.tool + xmlworker + 5.5.13 + + + + + + org.springframework.boot + spring-boot-starter-mail + 3.1.4 + + + org.springframework.boot + spring-boot-starter-websocket + + + javax.activation + activation + 1.1.1 + + + + + javax.mail + mail + 1.4.7 + + + org.apache.httpcomponents + httpclient + + + + + + \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java new file mode 100644 index 0000000..1d6d4f4 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java new file mode 100644 index 0000000..be49c80 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java new file mode 100644 index 0000000..79cd191 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java new file mode 100644 index 0000000..58a4bc6 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -0,0 +1,187 @@ +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 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 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN + */ + public int roundingMode() default BigDecimal.ROUND_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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java new file mode 100644 index 0000000..1f1cc81 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java new file mode 100644 index 0000000..1eb8e49 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java new file mode 100644 index 0000000..0f024c7 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java new file mode 100644 index 0000000..b769748 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/VoidFunction.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/VoidFunction.java new file mode 100644 index 0000000..3022ec0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/VoidFunction.java @@ -0,0 +1,13 @@ +package com.ruoyi.common.annotation; +/** + * 一个参数、没有返回 + * @author wangqiong + */ +@FunctionalInterface +public interface VoidFunction { + /** + * 有一个参数 + * @param param + */ + void apply(T param); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/EsignDemoConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/EsignDemoConfig.java new file mode 100644 index 0000000..f9888e2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/EsignDemoConfig.java @@ -0,0 +1,13 @@ +package com.ruoyi.common.config; + +public class EsignDemoConfig { + + // 应用ID + public static final String EsignAppId = "7438987614"; + // 应用密钥 + public static final String EsignAppSecret = "9d7844f13830931037772b9d20cf1529"; + // e签宝接口调用域名(模拟环境) + public static final String EsignHost = "https://smlopenapi.esign.cn"; + // e签宝接口调用域名(正式环境) + // public static final String EsignHost = "https://openapi.esign.cn"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java new file mode 100644 index 0000000..68a1ef1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -0,0 +1,148 @@ +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"; + } + + /** + * 获取上传路径 + */ + public static String getVideoUploadPath() + { + return getProfile() + "/video"; + } + public static String getHtml2PDFPath() + { + return getProfile() + "/upload/html2PDF"; + } + // https://1304001529.vod-qcloud.com/b78823bbvodcq1304001529/3ce565bf3270835011486046286/f0.mp4 +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java new file mode 100644 index 0000000..30d3a56 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -0,0 +1,45 @@ +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:"; + public static final String WE_CHAT_SMS_VERIFY_CODE_KEY="we_chat_sms_verify_code:"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CaseApplicationConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CaseApplicationConstants.java new file mode 100644 index 0000000..e7802e4 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CaseApplicationConstants.java @@ -0,0 +1,58 @@ +package com.ruoyi.common.constant; +/** + * 立案申请案件状态 + * + */ +public class CaseApplicationConstants { + /** 立案申请 */ + public static final int CASE_APPLICATION = 0; + /** 待立案审查 */ + public static final int CASE_CHECK = 1; + /** 待缴费 */ + public static final int PENDING_PAYMENT = 2; + /** 待缴费确认 */ + public static final int PENDING_PAYMENT_CONFIRM = 3; + /** 待案件质证 */ + public static final int CASE_CROSSEXAMI = 4; + + /** 待组庭 */ + public static final int PENDING_TRIAL = 26; + /** 待组庭审核 */ + public static final int CONFIRMDED_PENDING_TRIAL_SUBMMIT = 5; + /** 待组庭确定 */ + public static final int CONFIRMDED_PENDING_TRIAL = 6; + + /** 待审核仲裁方式 */ + public static final int CHECK_ARBITRATION_METHOD = 7; + /** 待开庭审理 */ + public static final int PENDING_OPENCOURT_HEAR = 8; + /** 待书面审理 */ + public static final int PENDING_WRIITEN_HEAR = 9; + /** 待生成仲裁文书 */ + public static final int GENERATED_ARBITRATION = 10; + /**待秘书核验仲裁文书*/ + public static final int VERPRIF_ARBITRATION = 11; + /**待部门长审核仲裁文书*/ + public static final int CHECK_ARBITRATION = 12; + /**待仲裁文书签名*/ + public static final int SIGN_ARBITRATION = 13; + /** 待仲裁文书用印 */ + public static final int ARBITRATED_SEAL = 14; + /** 待仲裁文书送达 */ + public static final int ARBITRATION_DELIVERY = 15; + /** 待案件归档*/ + public static final int CASE_FILING = 16; + /** 已归档*/ + public static final int CASE_ARCHIVED = 17; + + /** 待修改开庭时间*/ + public static final int MODIFY_HEARDATE = 31; + /**待仲裁员审核仲裁文书*/ + public static final int HEAD_CHECK_ARBITRATION = 18; + + + + + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java new file mode 100644 index 0000000..e46e514 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -0,0 +1,157 @@ +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://"; + /** + * br标签 + */ + public static final String BR = "
"; + /** + * pdf拼接符 + */ + public static final String PDFSTR = "∰"; + + /** + * 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 DEFAULT_PASSWORD = "123456"; + public static final String SPLIT_COMMA =","; + + /** + * 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全) + */ + public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" }; + + /** + * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) + */ + 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/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignEncryption.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignEncryption.java new file mode 100644 index 0000000..ade398b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignEncryption.java @@ -0,0 +1,371 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.ruoyi.common.constant; +import com.ruoyi.common.exception.EsignDemoException; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.message.BasicNameValuePair; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.Collator; +import java.text.MessageFormat; +import java.util.*; + +/** + * @description 请求数据通用处理类 + * @author 澄泓 + * @date 2020年10月22日 下午14:25:31 + * @since JDK1.7 + */ +public class EsignEncryption { + + /** + * 不允许外部创建实例 + */ + private EsignEncryption(){} + + /** + * 拼接待签名字符串 + * @param httpMethod + * @param url + * @return + */ + public static String appendSignDataString(String httpMethod, String contentMd5,String accept,String contentType,String headers,String date, String url) throws EsignDemoException { + StringBuffer sb = new StringBuffer(); + sb.append(httpMethod).append("\n").append(accept).append("\n").append(contentMd5).append("\n") + .append(contentType).append("\n"); + + if ("".equals(date) || date == null) { + sb.append("\n"); + } else { + sb.append(date).append("\n"); + } + if ("".equals(headers) || headers == null) { + sb.append(url); + } else { + sb.append(headers).append("\n").append(url); + } + return new String(sb); + } + + /*** + * Content-MD5的计算方法 + * @param str 待计算的消息 + * @return MD5计算后摘要值的Base64编码(ContentMD5) + * @throws EsignDemoException 加密过程中的异常信息 + */ + public static String doContentMD5(String str) throws EsignDemoException { + byte[] md5Bytes = null; + MessageDigest md5 = null; + String contentMD5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + // 计算md5函数 + md5.update(str.getBytes("UTF-8")); + // 获取文件MD5的二进制数组(128位) + md5Bytes = md5.digest(); + // 把MD5摘要后的二进制数组md5Bytes使用Base64进行编码(而不是对32位的16进制字符串进行编码) + contentMD5 = Base64.encodeBase64String(md5Bytes); + + } catch (NoSuchAlgorithmException e) { + EsignDemoException ex = new EsignDemoException("不支持此算法",e); + ex.initCause(e); + throw ex; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return contentMD5; + } + + /*** + * 计算请求签名值-HmacSHA256摘要 + * @param message 待签名字符串 + * @param secret 密钥APP KEY + * @return reqSignature HmacSHA256计算后摘要值的Base64编码 + * @throws EsignDemoException 加密过程中的异常信息 + */ + public static String doSignatureBase64(String message, String secret) throws EsignDemoException { + String algorithm = "HmacSHA256"; + Mac hmacSha256; + String digestBase64 = null; + try { + hmacSha256 = Mac.getInstance(algorithm); + byte[] keyBytes = secret.getBytes("UTF-8"); + byte[] messageBytes = message.getBytes("UTF-8"); + hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm)); + // 使用HmacSHA256对二进制数据消息Bytes计算摘要 + byte[] digestBytes = hmacSha256.doFinal(messageBytes); + // 把摘要后的结果digestBytes使用Base64进行编码 + digestBase64 = Base64.encodeBase64String(digestBytes); + } catch (NoSuchAlgorithmException e) { + EsignDemoException ex = new EsignDemoException("不支持此算法",e); + ex.initCause(e); + throw ex; + } catch (InvalidKeyException e) { + EsignDemoException ex = new EsignDemoException("无效的密钥规范",e); + ex.initCause(e); + throw ex; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return digestBase64; + } + + /** + * 获取时间戳 + * @return + */ + public static String timeStamp() { + long timeStamp = System.currentTimeMillis(); + return String.valueOf(timeStamp); + } + + /** + * byte字节数组转换成字符串 + * @param b + * @return + */ + public static String byteArrayToHexString(byte[] b) { + StringBuilder hs = new StringBuilder(); + String stmp; + for (int n = 0; b != null && n < b.length; n++) { + stmp = Integer.toHexString(b[n] & 0XFF); + if (stmp.length() == 1) + hs.append('0'); + hs.append(stmp); + } + return hs.toString().toLowerCase(); + } + + /** + * hash散列加密算法 + * @return + */ + public static String Hmac_SHA256(String message,String key) throws EsignDemoException { + byte[] rawHmac=null; + try { + SecretKeySpec sk = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(sk); + rawHmac = mac.doFinal(message.getBytes()); + }catch (InvalidKeyException e){ + EsignDemoException ex = new EsignDemoException("无效的密钥规范",e); + ex.initCause(e); + throw ex; + } catch (NoSuchAlgorithmException e) { + EsignDemoException ex = new EsignDemoException("不支持此算法",e); + ex.initCause(e); + throw ex; + }catch (Exception e){ + EsignDemoException ex = new EsignDemoException("hash散列加密算法报错",e); + ex.initCause(e); + throw ex; + }finally { + return byteArrayToHexString(rawHmac); + } + + } + + /** + * MD5加密32位 + */ + public static String MD5Digest(String text) throws EsignDemoException { + byte[] digest=null; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(text.getBytes()); + digest = md5.digest(); + }catch (NoSuchAlgorithmException e){ + EsignDemoException ex = new EsignDemoException("不支持此算法",e); + ex.initCause(e); + throw ex; + }finally { + return byteArrayToHexString(digest); + } + + } + + public static void formDataSort(List param) { + Collections.sort(param, new Comparator() { + @Override + public int compare(BasicNameValuePair o1, BasicNameValuePair o2) { + Comparator com = Collator.getInstance(Locale.CHINA); + return com.compare(o1.getName(), o2.getName()); + } + }); + } + + /*** + * 字符串是否为空(含空格校验) + * @param str + * @return + */ + public static boolean isBlank(String str) { + if (null == str || 0 == str.length()) { + return true; + } + + int strLen = str.length(); + + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } + return true; + } + + + /*** + * 对请求URL中的Query参数按照字段名的 ASCII 码从小到大排序(字典排序) + * + * @param apiUrl + * @return 排序后的API接口地址 + * @throws Exception + */ + public static String sortApiUrl(String apiUrl) throws EsignDemoException { + + if (!apiUrl.contains("?")) { + return apiUrl; + } + + int queryIndex = apiUrl.indexOf("?"); + String apiUrlPath =apiUrl.substring(0,queryIndex+1); + String apiUrlQuery = apiUrl.substring(queryIndex+1); + //apiUrlQuery为空时返回 + if(isBlank(apiUrlQuery)){ + return apiUrl.substring(0,apiUrl.length()-1); + } + // 请求URL中Query参数转成Map + Map queryParamsMap = new HashMap(); + String[] params = apiUrlQuery.split("&"); + for (String str : params) { + int index = str.indexOf("="); + String key = str.substring(0, index); + String value = str.substring(index + 1); + if (queryParamsMap.containsKey(key)) { + String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key); + throw new EsignDemoException(msg); + } + queryParamsMap.put(key, value); + } + + ArrayList queryMapKeys = new ArrayList(); + for (Map.Entry entry : queryParamsMap.entrySet()) { + queryMapKeys.add((String) entry.getKey()); + } + // 按照字段名的 ASCII 码从小到大排序(字典排序) + Collections.sort(queryMapKeys, new Comparator() { + @Override + public int compare(String o1, String o2) { + return (o1.compareToIgnoreCase(o2) == 0 ? -o1.compareTo(o2) : o1.compareToIgnoreCase(o2)); + } + }); + + StringBuffer queryString = new StringBuffer(); + // 构造Query参数键值对值对的格式 + for (int i = 0; i < queryMapKeys.size(); i++) { + String key = queryMapKeys.get(i); + String value = (String) queryParamsMap.get(key); + queryString.append(key); + queryString.append("="); + queryString.append(value); + queryString.append("&"); + } + if (queryString.length() > 0) { + queryString = queryString.deleteCharAt(queryString.length() - 1); + } + + // Query参数排序后的接口请求地址 + StringBuffer sortApiUrl = new StringBuffer(); + sortApiUrl.append(apiUrlPath); + sortApiUrl.append(queryString.toString()); + return sortApiUrl.toString(); + } + + /** + *获取query + * @param apiUrl + * @return + * @throws EsignDemoException + */ + public static ArrayList getQuery(String apiUrl) throws EsignDemoException { + ArrayList BasicNameValuePairList = new ArrayList<>(); + + if (!apiUrl.contains("?")) { + return BasicNameValuePairList; + } + + int queryIndex = apiUrl.indexOf("\\?"); + String apiUrlQuery = apiUrl.substring(queryIndex,apiUrl.length()); + + // 请求URL中Query参数转成Map + Map queryParamsMap = new HashMap(); + String[] params = apiUrlQuery.split("&"); + for (String str : params) { + int index = str.indexOf("="); + String key = str.substring(0, index); + String value = str.substring(index + 1); + if (queryParamsMap.containsKey(key)) { + String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key); + throw new EsignDemoException(msg); + } + BasicNameValuePairList.add(new BasicNameValuePair(key,value)); + queryParamsMap.put(key, value); + } + return BasicNameValuePairList; + } + /** + * + */ + public static boolean callBackCheck(String timestamp,String requestQuery,String body,String key,String signature){ + String algorithm="HmacSHA256"; + String encoding="UTF-8"; + Mac mac = null; + try { + String data = timestamp + requestQuery + body; + mac = Mac.getInstance(algorithm); + SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(encoding), algorithm); + mac.init(secretKey); + mac.update(data.getBytes(encoding)); + } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) { + e.printStackTrace(); + System.out.println("获取Signature签名信息异常:" + e.getMessage()); + return false; + } + return byte2hex(mac.doFinal()).equalsIgnoreCase(signature); + } + + /*** + * 将byte[]转成16进制字符串 + * + * @param data + * + * @return 16进制字符串 + */ + public static String byte2hex(byte[] data) { + StringBuilder hash = new StringBuilder(); + String stmp; + for (int n = 0; data != null && n < data.length; n++) { + stmp = Integer.toHexString(data[n] & 0XFF); + if (stmp.length() == 1) + hash.append('0'); + hash.append(stmp); + } + return hash.toString(); + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHeaderConstant.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHeaderConstant.java new file mode 100644 index 0000000..ae1e035 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHeaderConstant.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.constant; +/** + * @description 头部信息常量 + * @author 澄泓 + * @date 2020/10/22 15:05 + * @version JDK1.7 + */ +public enum EsignHeaderConstant { + ACCEPT("*/*"), + DATE(""), + HEADERS( ""), + CONTENTTYPE_FORMDATA("application/x-www-form-urlencoded"), + CONTENTTYPE_JSON("application/json; charset=UTF-8"), + CONTENTTYPE_PDF("application/pdf"), + CONTENTTYPE_STREAM("application/octet-stream"), + AUTHMODE("Signature"); + + private String value; + private EsignHeaderConstant(String value) { + this.value=value; + } + + public String VALUE(){ + return this.value; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHttpCfgHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHttpCfgHelper.java new file mode 100644 index 0000000..78162ed --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHttpCfgHelper.java @@ -0,0 +1,486 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.ruoyi.common.constant; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.enums.EsignRequestType; +import com.ruoyi.common.exception.EsignDemoException; +import org.apache.http.*; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.*; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.UnknownHostException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @description Http请求 辅助类 + * @author 澄泓 + * @since JDK1.7 + */ +public class EsignHttpCfgHelper { + + private static Logger LOGGER = LoggerFactory.getLogger(EsignHttpCfgHelper.class); + /** + * 超时时间,默认15000毫秒 + */ + private static int MAX_TIMEOUT = 15000; + /** + * 请求池最大连接数,默认100个 + */ + private static int MAX_TOTAL=100; + /** + * 单域名最大的连接数,默认50个 + */ + private static int ROUTE_MAX_TOTAL=50; + /** + * 请求失败重试次数,默认3次 + */ + private static int MAX_RETRY = 3; + /** + * 是否需要域名校验,默认不需要校验 + */ + private static boolean SSL_VERIFY=false; + + /** + * 正向代理IP + */ + private static String PROXY_IP; + /** + * 正向代理端口,默认8888 + */ + private static int PROXY_PORT=8888; + /** + * 代理协议,默认http + */ + private static String PROXY_AGREEMENT="http"; + + /** + * 是否开启代理,默认false + */ + private static boolean OPEN_PROXY=false; + + /** + * 代理服务器用户名 + */ + private static String PROXY_USERNAME=""; + + /** + * 代理服务器密码 + */ + private static String PROXY_PASSWORD=""; + + + private static PoolingHttpClientConnectionManager connMgr; //连接池 + private static HttpRequestRetryHandler retryHandler; //重试机制 + + private static CloseableHttpClient httpClient=null; + + public static int getMaxTimeout() { + return MAX_TIMEOUT; + } + + public static void setMaxTimeout(int maxTimeout) { + MAX_TIMEOUT = maxTimeout; + } + + public static int getMaxTotal() { + return MAX_TOTAL; + } + + public static void setMaxTotal(int maxTotal) { + MAX_TOTAL = maxTotal; + } + + public static int getRouteMaxTotal() { + return ROUTE_MAX_TOTAL; + } + + public static void setRouteMaxTotal(int routeMaxTotal) { + ROUTE_MAX_TOTAL = routeMaxTotal; + } + + public static int getMaxRetry() { + return MAX_RETRY; + } + + public static void setMaxRetry(int maxRetry) { + MAX_RETRY = maxRetry; + } + + public static boolean isSslVerify() { + return SSL_VERIFY; + } + + public static void setSslVerify(boolean sslVerify) { + SSL_VERIFY = sslVerify; + } + + public static String getProxyIp() { + return PROXY_IP; + } + + public static void setProxyIp(String proxyIp) { + PROXY_IP = proxyIp; + } + + public static int getProxyPort() { + return PROXY_PORT; + } + + public static void setProxyPort(int proxyPort) { + PROXY_PORT = proxyPort; + } + + public static String getProxyAgreement() { + return PROXY_AGREEMENT; + } + + public static void setProxyAgreement(String proxyAgreement) { + PROXY_AGREEMENT = proxyAgreement; + } + + public static boolean getOpenProxy() { + return OPEN_PROXY; + } + + public static void setOpenProxy(boolean openProxy) { + OPEN_PROXY = openProxy; + } + + public static String getProxyUsername() { + return PROXY_USERNAME; + } + + public static void setProxyUserame(String proxyUsername) { + PROXY_USERNAME = proxyUsername; + } + + public static String getProxyPassword() { + return PROXY_PASSWORD; + } + + public static void setProxyPassword(String proxyPassword) { + PROXY_PASSWORD = proxyPassword; + } + + + + + /** + * 不允许外部创建实例 + */ + private EsignHttpCfgHelper() { + } + + //------------------------------公有方法start-------------------------------------------- + + + /** + * @description 发起HTTP / HTTPS 请求 + * + * @param reqType + * {@link EsignRequestType} 请求类型 GET、 POST 、 DELETE 、 PUT + * @param httpUrl + * {@link String} 请求目标地址 + * @param headers + * {@link Map} 请求头 + * @param param + * {@link Object} 参数 + * @return + * @throws EsignDemoException + * @author 澄泓 + */ + public static EsignHttpResponse sendHttp(EsignRequestType reqType, String httpUrl, Map headers, Object param, boolean debug) + throws EsignDemoException { + HttpRequestBase reqBase=null; + if(httpUrl.startsWith("http")){ + reqBase=reqType.getHttpType(httpUrl); + }else{ + throw new EsignDemoException("请求url地址格式错误"); + } + if(debug){ + LOGGER.info("请求头:{}",headers+"\n"); + LOGGER.info("请求参数\n{}", param+"\n"); + LOGGER.info("请求地址\n:{}\n请求方式\n:{}",reqBase.getURI(),reqType+"\n"); + } + //请求方法不是GET或者DELETE时传入body体,否则不传入。 + String[] methods = {"DELETE", "GET"}; + if(param instanceof String&&Arrays.binarySearch(methods, reqType.name())<0){//POST或者PUT请求 + ((HttpEntityEnclosingRequest) reqBase).setEntity( + new StringEntity(String.valueOf(param), ContentType.create("application/json", "UTF-8"))); + } + //参数时字节流数组 + else if(param instanceof byte[]) { + reqBase=reqType.getHttpType(httpUrl); + byte[] paramBytes = (byte[])param; + ((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes)); + } + //参数是form表单时 + else if(param instanceof List){ + ((HttpEntityEnclosingRequest) reqBase).setEntity(new UrlEncodedFormEntity((Iterable) param)); + } + httpClient = getHttpClient(); + config(reqBase); + + //设置请求头 + if(headers != null &&headers.size()>0) { + for(Map.Entry entry :headers.entrySet()) { + reqBase.setHeader(entry.getKey(), entry.getValue()); + } + } + //响应对象 + CloseableHttpResponse res = null; + //响应内容 + String resCtx = null; + int status; + EsignHttpResponse esignHttpResponse = new EsignHttpResponse(); + try { + //执行请求 + res = httpClient.execute(reqBase); + status=res.getStatusLine().getStatusCode(); + + //获取请求响应对象和响应entity + HttpEntity httpEntity = res.getEntity(); + if(httpEntity != null) { + resCtx = EntityUtils.toString(httpEntity,"utf-8"); + } + if(debug) { + LOGGER.info("响应\n{}", resCtx + "\n"); + LOGGER.info("----------------------------end------------------------"); + } + } catch (NoHttpResponseException e) { + throw new EsignDemoException("服务器丢失了",e); + } catch (SSLHandshakeException e){ + String msg = MessageFormat.format("SSL握手异常", e); + EsignDemoException ex = new EsignDemoException(msg, e); + throw ex; + } catch (UnknownHostException e){ + EsignDemoException ex = new EsignDemoException("服务器找不到", e); + ex.initCause(e); + throw ex; + } catch(ConnectTimeoutException e){ + EsignDemoException ex = new EsignDemoException("连接超时", e); + ex.initCause(e); + throw ex; + } catch(SSLException e){ + EsignDemoException ex = new EsignDemoException("SSL异常",e); + ex.initCause(e); + throw ex; + } catch (ClientProtocolException e) { + EsignDemoException ex = new EsignDemoException("请求头异常",e); + ex.initCause(e); + throw ex; + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("网络请求失败",e); + ex.initCause(e); + throw ex; + } finally { + if(res != null) { + try { + res.close(); + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("--->>关闭请求响应失败",e); + ex.initCause(e); + throw ex; + } + } + } + esignHttpResponse.setStatus(status); + esignHttpResponse.setBody(resCtx); + return esignHttpResponse; + } + //------------------------------公有方法end---------------------------------------------- + + //------------------------------私有方法start-------------------------------------------- + + /** + * @description 请求头和超时时间配置 + * + * @param httpReqBase + * @author 澄泓 + */ + private static void config(HttpRequestBase httpReqBase) { + // 配置请求的超时设置 + RequestConfig.Builder builder = RequestConfig.custom() + .setConnectionRequestTimeout(MAX_TIMEOUT) + .setConnectTimeout(MAX_TIMEOUT) + .setSocketTimeout(MAX_TIMEOUT); + if(OPEN_PROXY){ + HttpHost proxy=new HttpHost(PROXY_IP,PROXY_PORT,PROXY_AGREEMENT); + builder.setProxy(proxy); + } + RequestConfig requestConfig = builder.build(); + httpReqBase.setConfig(requestConfig); + } + + /** + * @description 连接池配置 + * + * @return + * @author 澄泓 + */ + private static void cfgPoolMgr() throws EsignDemoException { + ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); + LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory(); + if(!SSL_VERIFY){ + sslsf=sslConnectionSocketFactory(); + } + + Registry registry = RegistryBuilder.create() + .register("http", plainsf) + .register("https", sslsf) + .build(); + + //连接池管理器 + connMgr = new PoolingHttpClientConnectionManager(registry); + //请求池最大连接数 + connMgr.setMaxTotal(MAX_TOTAL); + //但域名最大的连接数 + connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL); + } + + + + + /** + * @description 设置重试机制 + * + * @author 澄泓 + */ + private static void cfgRetryHandler() { + retryHandler = new HttpRequestRetryHandler() { + + @Override + public boolean retryRequest(IOException e, int excCount, HttpContext ctx) { + //超过最大重试次数,就放弃 + if(excCount > MAX_RETRY) { + return false; + } + //服务器丢掉了链接,就重试 + if(e instanceof NoHttpResponseException) { + return true; + } + //不重试SSL握手异常 + if(e instanceof SSLHandshakeException) { + return false; + } + //中断 + if(e instanceof InterruptedIOException) { + return false; + } + //目标服务器不可达 + if(e instanceof UnknownHostException) { + return false; + } + //连接超时 + //SSL异常 + if(e instanceof SSLException) { + return false; + } + + HttpClientContext clientCtx = HttpClientContext.adapt(ctx); + HttpRequest req = clientCtx.getRequest(); + //如果是幂等请求,就再次尝试 + if(!(req instanceof HttpEntityEnclosingRequest)) { + return true; + } + return false; + } + }; + } + + /** + * 忽略域名校验 + */ + private static SSLConnectionSocketFactory sslConnectionSocketFactory() throws EsignDemoException { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); // 创建一个上下文(此处指定的协议类型似乎不是重点) + X509TrustManager tm = new X509TrustManager() { // 创建一个跳过SSL证书的策略 + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + }; + ctx.init(null, new TrustManager[] { tm }, null); // 使用上面的策略初始化上下文 + return new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE); + }catch (Exception e){ + EsignDemoException ex = new EsignDemoException("忽略域名校验失败",e); + ex.initCause(e); + throw ex; + } + + } + + /** + * @description 获取单例HttpClient + * + * @return + * @author 澄泓 + */ + private static synchronized CloseableHttpClient getHttpClient() throws EsignDemoException { + if(httpClient==null) { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(PROXY_IP,PROXY_PORT),new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD)); + cfgPoolMgr(); + cfgRetryHandler(); + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); + httpClient = httpClientBuilder.setDefaultCredentialsProvider(credsProvider).setConnectionManager(connMgr).setRetryHandler(retryHandler).build(); + } + return httpClient; + + } + //------------------------------私有方法end---------------------------------------------- + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/FileTransformation.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/FileTransformation.java new file mode 100644 index 0000000..c1c6384 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/FileTransformation.java @@ -0,0 +1,286 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.ruoyi.common.constant; + +import com.ruoyi.common.exception.EsignDemoException; +import org.apache.commons.codec.binary.Base64; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author 澄泓 + * @version JDK1.7 + * @description 文件转换类 + * @date 2020/10/26 10:47 + */ +public class FileTransformation { + + /** + * 传入本地文件路径转二进制byte + * + * @param srcFilePath 本地文件路径 + * @return + * @throws EsignDemoException + */ + public static byte[] fileToBytes(String srcFilePath) throws EsignDemoException { + return getBytes(srcFilePath); + } + + /** + * 图片转base64 + * + * @param filePath 本地文件路径 + * @return + * @throws EsignDemoException + */ + public static String fileToBase64(String filePath) throws EsignDemoException { + byte[] bytes; + String base64 = null; + bytes = fileToBytes(filePath); + base64 = Base64.encodeBase64String(bytes); + base64 = base64.replaceAll("\r\n", ""); + return base64; + } + + public static void main(String[] args) throws EsignDemoException { + System.out.println(getFileContentMD5("D:\\文档\\PLT2022-02124CT.pdf")); + } + + /*** + * 计算文件内容的Content-MD5 + * @param filePath 文件路径 + * @return + */ + public static String getFileContentMD5(String filePath) throws EsignDemoException { + // 获取文件MD5的二进制数组(128位) + byte[] bytes = getFileMD5Bytes128(filePath); + // 对文件MD5的二进制数组进行base64编码 + return new String(Base64.encodeBase64String(bytes)); + } + + /** + * 下载文件 + * + * @param httpUrl 网络文件地址url + * @return + */ + public static boolean downLoadFileByUrl(String httpUrl, String dir) throws EsignDemoException { + boolean downLoadFileFlag = false; + InputStream fis = null; + FileOutputStream fileOutputStream = null; + try { + URL url = new URL(httpUrl); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn.connect(); + fis = httpConn.getInputStream(); + fileOutputStream = new FileOutputStream(new File(dir)); + byte[] md5Bytes = null; + + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + fileOutputStream.write(buffer, 0, length); + } + downLoadFileFlag = true; + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("获取文件流异常", e); + ex.initCause(e); + return downLoadFileFlag; + } finally { + try { + if (fis != null) { + fis.close(); + } + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("关闭文件流异常", e); + ex.initCause(e); + return downLoadFileFlag; + } + } + return downLoadFileFlag; + } + + + /** + * 网络文件转二进制MD5数组并获取文件大小 + * + * @param fileUrl 网络文件地址url + * @return + */ + public static Map fileUrlToBytes(String fileUrl) throws EsignDemoException { + HashMap map = new HashMap(); + try { + URL url = new URL(fileUrl); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn.connect(); + InputStream fis = httpConn.getInputStream(); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + outStream.close(); + map.put("fileSize", fis.available()); + byte[] md5Bytes = null; + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + md5.update(buffer, 0, length); + outStream.write(buffer, 0, length); + } + md5Bytes = md5.digest(); + byte[] fileData = outStream.toByteArray(); + map.put("fileData", fileData); + outStream.close(); + fis.close(); + map.put("md5Bytes", md5Bytes); + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("获取文件流异常", e); + ex.initCause(e); + throw ex; + } catch (NoSuchAlgorithmException e) { + EsignDemoException ex = new EsignDemoException("文件计算异常", e); + ex.initCause(e); + throw ex; + } + return map; + } + + /*** + * 获取文件MD5的二进制数组(128位) + * @param filePath + * @return + * @throws EsignDemoException + */ + public static byte[] getFileMD5Bytes128(String filePath) throws EsignDemoException { + FileInputStream fis = null; + byte[] md5Bytes = null; + try { + File file = new File(filePath); + fis = new FileInputStream(file); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + md5.update(buffer, 0, length); + } + md5Bytes = md5.digest(); + fis.close(); + } catch (FileNotFoundException e) { + EsignDemoException ex = new EsignDemoException("文件找不到", e); + ex.initCause(e); + throw ex; + } catch (NoSuchAlgorithmException e) { + EsignDemoException ex = new EsignDemoException("不支持此算法", e); + ex.initCause(e); + throw ex; + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("输入流或输出流异常", e); + ex.initCause(e); + throw ex; + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e); + ex.initCause(e); + throw ex; + } + } + } + return md5Bytes; + } + + /** + * @param path + * @return + * @throws EsignDemoException + * @description 根据文件路径,获取文件base64 + * @author 宫清 + * @date 2019年7月21日 下午4:22:08 + */ + public static String getBase64Str(String path) throws EsignDemoException { + InputStream is = null; + try { + is = new FileInputStream(new File(path)); + byte[] bytes = new byte[is.available()]; + is.read(bytes); + return Base64.encodeBase64String(bytes); + } catch (Exception e) { + EsignDemoException ex = new EsignDemoException("获取文件输入流失败", e); + ex.initCause(e); + throw ex; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e); + ex.initCause(e); + throw ex; + } + } + } + } + + /** + * @param path 文件路径 + * @return + * @description 获取文件名称 + * @author 宫清 + * @date 2019年7月21日 下午8:21:16 + */ + public static String getFileName(String path) { + return new File(path).getName(); + } + + /** + * @param filePath {@link String} 文件地址 + * @return + * @throws EsignDemoException + * @description 获取文件字节流 + * @date 2019年7月10日 上午9:17:00 + * @author 宫清 + */ + public static byte[] getBytes(String filePath) throws EsignDemoException { + File file = new File(filePath); + FileInputStream fis = null; + byte[] buffer = null; + try { + fis = new FileInputStream(file); + buffer = new byte[(int) file.length()]; + fis.read(buffer); + } catch (Exception e) { + EsignDemoException ex = new EsignDemoException("获取文件字节流失败", e); + ex.initCause(e); + throw ex; + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + EsignDemoException ex = new EsignDemoException("关闭文件字节流失败", e); + ex.initCause(e); + throw ex; + } + } + } + return buffer; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java new file mode 100644 index 0000000..7d899d4 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java new file mode 100644 index 0000000..a983c77 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java new file mode 100644 index 0000000..62ad815 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java new file mode 100644 index 0000000..96b149c --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java new file mode 100644 index 0000000..a685e06 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java new file mode 100644 index 0000000..a7abfe4 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java new file mode 100644 index 0000000..b121515 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -0,0 +1,117 @@ +package com.ruoyi.common.core.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 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", timezone = "Asia/Shanghai") + private Date createTime; + + /** + * 更新者 + */ + private String updateBy; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + 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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java new file mode 100644 index 0000000..ef15802 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java new file mode 100644 index 0000000..a180a18 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java new file mode 100644 index 0000000..4f8e08d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java @@ -0,0 +1,79 @@ +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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignCoreSdkInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignCoreSdkInfo.java new file mode 100644 index 0000000..d97603d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignCoreSdkInfo.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.core.domain.entity; +/** + * esignSDK-core信息类 + * @author 澄泓 + * @date 2022/2/22 13:59 + * @version + */ +public class EsignCoreSdkInfo { + private static final String SdkVersion="Esign-Sdk-Core1.0"; + private static final String SupportedVersion="JDK1.7 MORE THAN"; + + private static final String Info="sdk-esign-api核心工具包,主要处理e签宝公有云产品接口调用时的签名计算以及网络请求,通过EsignHttpHelper.signAndBuildSignAndJsonHeader构造签名鉴权+json数据格式的请求头,通过HttpHelper.doCommHttp方法入参发起网络请求。让开发者无需关注具体的请求签名算法,专注于接口业务的json参数构造"; + public static String getSdkVersion() { + return SdkVersion; + } + + public static String getInfo() { + return Info; + } + + public static String getSupportedVersion() { + return SupportedVersion; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignHttpResponse.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignHttpResponse.java new file mode 100644 index 0000000..26375c0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignHttpResponse.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.core.domain.entity; +/** + * 网络请求的response类 + */ +public class EsignHttpResponse { + private int status; + private String body; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java new file mode 100644 index 0000000..f98291a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -0,0 +1,214 @@ +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 deptType; + + /** 显示顺序 */ + 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; + + public Integer getDeptType() { + return deptType; + } + + public void setDeptType(Integer deptType) { + this.deptType = deptType; + } + + /** 子部门 */ + 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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java new file mode 100644 index 0000000..738f12c --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java new file mode 100644 index 0000000..e324fcf --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java new file mode 100644 index 0000000..94e1a18 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java new file mode 100644 index 0000000..488d49c --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java new file mode 100644 index 0000000..4fd0af0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -0,0 +1,350 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.*; +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; + + /** 用户账号 */ + @Excel(name = "登录名称") + private String userName; + + + + /** 用户昵称 */ + @Excel(name = "用户名称") + private String nickName; + + /** 用户昵称和待办数量 */ + private String nickNameAndNum; + + public String getNickNameAndNum() { + return nickNameAndNum; + } + + public void setNickNameAndNum(String nickNameAndNum) { + this.nickNameAndNum = nickNameAndNum; + } + + /** 用户身份证号 */ + @Excel(name = "身份证号") + private String idCard; + + /** 用户邮箱 */ + @Excel(name = "用户邮箱") + private String email; + + /** 手机号码 */ + @Excel(name = "手机号码") + private String phonenumber; + + /** 用户性别 */ + @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") + private String sex; + + /** 用户头像 */ + private String avatar; + + /** 密码 */ + private String password; + + /** 帐号状态(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; + } + + @Xss(message = "用户昵称不能包含脚本字符") + @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @Xss(message = "用户账号不能包含脚本字符") + @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 getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + 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; + } + + public String getIdCard() { + return idCard; + } + + public void setIdCard(String idCard) { + this.idCard = idCard; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("idCard", getIdCard()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java new file mode 100644 index 0000000..b5bc8c8 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java new file mode 100644 index 0000000..670e6b3 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java new file mode 100644 index 0000000..868a1fc --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java new file mode 100644 index 0000000..8966cb4 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java new file mode 100644 index 0000000..847685b --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java new file mode 100644 index 0000000..a120c30 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java new file mode 100644 index 0000000..44e80d8 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java new file mode 100644 index 0000000..84124aa --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java new file mode 100644 index 0000000..c918e36 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java new file mode 100644 index 0000000..c78ac77 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java new file mode 100644 index 0000000..10b7306 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java new file mode 100644 index 0000000..2e17c4a --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java new file mode 100644 index 0000000..0d945be --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/EsignRequestType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EsignRequestType.java new file mode 100644 index 0000000..8b87de6 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EsignRequestType.java @@ -0,0 +1,39 @@ +package com.ruoyi.common.enums; + +import org.apache.http.client.methods.*; + +/** + * @description 请求类型 + * @author 澄泓 + * @since JDK1.7 + */ +public enum EsignRequestType { + + POST{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpPost(url); + } + }, + GET{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpGet(url); + } + }, + DELETE{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpDelete(url); + } + }, + PUT{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpPut(url); + } + }, + ; + + public abstract HttpRequestBase getHttpType(String url); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java new file mode 100644 index 0000000..a0cf8e5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java @@ -0,0 +1,32 @@ +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/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java new file mode 100644 index 0000000..c609fd8 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java new file mode 100644 index 0000000..bdd143c --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/UpdateSubmitStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UpdateSubmitStatus.java new file mode 100644 index 0000000..41a0ccb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UpdateSubmitStatus.java @@ -0,0 +1,38 @@ +package com.ruoyi.common.enums; + +/** + * @author wangqiong + * @description 修改案件的提交状态 + * @date 2023-11-17 14:05 + */ +public enum UpdateSubmitStatus +{ + UNCOMMITTED(0, "未提交"), + COMMITTED(1, "已提交"), + REVOKE(2, "撤销"), + AGREE(3, "同意已修改的案件"), + REFUSE(4, "拒绝已修改的案件"), + + AGREE_REVOKE(5, "同意撤销修改"), + REFUSE_REVOKE(6, "拒绝撤销修改"), + ; + + private final Integer code; + private final String text; + + UpdateSubmitStatus(Integer code, String text) + { + this.code = code; + this.text = text; + } + + public Integer getCode() + { + return code; + } + + public String getText() + { + return text; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java new file mode 100644 index 0000000..d7ff44a --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/enums/YesOrNoEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/YesOrNoEnum.java new file mode 100644 index 0000000..412c338 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/YesOrNoEnum.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.enums; + +/** + * @author wangqiong + * @description 是否枚举 + * @date 2023-11-17 14:05 + */ +public enum YesOrNoEnum +{ + NO(0, "否"), + YES(1, "是"), + + ; + + private final Integer code; + private final String text; + + YesOrNoEnum(Integer code, String text) + { + this.code = code; + this.text = text; + } + + public Integer getCode() + { + return code; + } + + public String getText() + { + return text; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java new file mode 100644 index 0000000..f6ad2ab --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/EsignDemoException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/EsignDemoException.java new file mode 100644 index 0000000..7be2957 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/EsignDemoException.java @@ -0,0 +1,36 @@ +package com.ruoyi.common.exception; + +/** + * description 自定义全局异常 + * @author 澄泓 + * datetime 2019年7月1日上午10:43:24 + */ +public class EsignDemoException extends Exception { + + private static final long serialVersionUID = 4359180081622082792L; + private Exception e; + + public EsignDemoException(String msg) { + super(msg); + } + + public EsignDemoException(String msg, Throwable cause) { + super(msg,cause); + } + + public EsignDemoException(){ + + } + + public Exception getE() { + return e; + } + + public void setE(Exception e) { + this.e = e; + } + + + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java new file mode 100644 index 0000000..81a71b5 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java new file mode 100644 index 0000000..fcc7ab6 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java new file mode 100644 index 0000000..980fa46 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java new file mode 100644 index 0000000..b55d72e --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java new file mode 100644 index 0000000..871f09b --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java new file mode 100644 index 0000000..70e0ec9 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java new file mode 100644 index 0000000..ec6ab05 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java new file mode 100644 index 0000000..f45e7ef --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java new file mode 100644 index 0000000..011f308 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java new file mode 100644 index 0000000..a567b40 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java new file mode 100644 index 0000000..2bf5038 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java new file mode 100644 index 0000000..389dbc7 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java new file mode 100644 index 0000000..85f9486 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java new file mode 100644 index 0000000..c292d70 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java new file mode 100644 index 0000000..eff8181 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java new file mode 100644 index 0000000..a7f3e5f --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java new file mode 100644 index 0000000..c887cf1 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java new file mode 100644 index 0000000..e1e431b --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java new file mode 100644 index 0000000..a1bcfe2 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java new file mode 100644 index 0000000..407d1ba --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java new file mode 100644 index 0000000..9052f0d --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..05149f0 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java new file mode 100644 index 0000000..b6326c2 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java new file mode 100644 index 0000000..fb2ae21 --- /dev/null +++ b/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 endDate 最后时间 + * @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/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java new file mode 100644 index 0000000..cc5eab2 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailOutUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailOutUtil.java new file mode 100644 index 0000000..3fef049 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailOutUtil.java @@ -0,0 +1,436 @@ +package com.ruoyi.common.utils; + + + +import com.ruoyi.common.utils.uuid.UUID; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.SimpleMailMessage; + +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.activation.DataHandler; +import javax.mail.*; +import javax.mail.internet.*; +import javax.mail.search.*; +import javax.mail.util.ByteArrayDataSource; +import javax.validation.constraints.NotNull; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Security; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +/** + * @ClassName EmailInUtil + * @Description 邮件发送工具 + */ +@Component +@Data +@Slf4j +public class EmailOutUtil { + private static Pattern emailPattern = Pattern.compile("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"); + // private static Pattern phonePattern = Pattern.compile("0?(13|14|15|18)[0-9]{9}"); + private static Pattern phonePattern = Pattern.compile("^1\\d{10}$"); + + +// @Autowired +// private JavaMailSender mailSender; + + // 发送发邮箱地址(外网地址) +// @Value("${spring.mail-out-network.from}") +// private static String fromOut; + @Value("${spring.mail.host}") + private String hostOut; +// @Value("${spring.mail.username}") +// private String usernameOut; + private String usernameOut="wq18792927508@163.com"; +// @Value("${spring.mail.password}") +// private String passwordOut; + private String passwordOut= "WDFHKSEMCKVRELEA"; + @Value("${spring.mail.port}") + private Integer portOut; + + public JavaMailSender rebuildMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost(hostOut); + mailSender.setUsername(usernameOut); + mailSender.setPassword(passwordOut); + mailSender.setPort(portOut); + mailSender.setProtocol("smtp"); + mailSender.setDefaultEncoding("UTF-8"); + return mailSender; + } + + /** + * 发送纯文本邮件信息 + * + * @param to 接收方 + * @param subject 邮件主题 + * @param content 邮件内容(发送内容) + */ + public void sendMessage(String to, String subject, String content, String from, JavaMailSender mailSender) { + // 创建一个邮件对象 + SimpleMailMessage msg = new SimpleMailMessage(); + msg.setFrom(from); + msg.setTo(to); + // 设置邮件主题 + msg.setSubject(subject); + // 设置邮件内容 + msg.setText(content); + // 发送邮件 + mailSender.send(msg); + ////System.out.println("发送成功:" + from + ":to:" + to); + } + + /** + * @param to 收件人 + * @param message 邮件内容 + * @param subject 邮件主题 + * @param fileList 邮件附件 + */ + public Boolean sendEmil(String to, String message, String subject, List fileList, File file) { + try { + String messageContent = "

"+message+"。

"; + MimeBodyPart messageBodyPart = new MimeBodyPart(); + messageBodyPart.setContent(messageContent, "text/html;charset=utf-8"); + messageBodyPart.setContentID(UUID.randomUUID().toString()); + Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); + final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + //设置邮件会话参数 + Properties props = new Properties(); + //邮箱的发送服务器地址 + props.setProperty("mail.smtp.host", "smtp.163.com"); + props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); + props.setProperty("mail.smtp.socketFactory.fallback", "false"); + //邮箱发送服务器端口,这里设置为465端口 + props.setProperty("mail.smtp.port", "465"); + props.setProperty("mail.smtp.socketFactory.port", "465"); + props.put("mail.smtp.auth", "true"); + //获取到邮箱会话,利用匿名内部类的方式,将发送者邮箱用户名和密码授权给jvm + Session session = Session.getDefaultInstance(props, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(usernameOut, passwordOut); + } + }); + //通过会话,得到一个邮件,用于发送 + Message msg = new MimeMessage(session); + //设置发件人 + msg.setFrom(new InternetAddress(usernameOut)); + //设置收件人,to为收件人,cc为抄送,bcc为密送 + msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); + msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(to, false)); + msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(to, false)); + //设置邮件消息 + msg.setSubject(subject); + msg.setText(message); + msg.setDescription("messageutf-8html"); + //设置发送的日期 + msg.setSentDate(new Date()); + // 创建邮件正文 + MimeMultipart multipart = new MimeMultipart(); +// MimeBodyPart bodyPart = new MimeBodyPart(); +// bodyPart.setContent("This is the body of the email", "text/html"); + multipart.addBodyPart(messageBodyPart); + // 添加附件 + if (file != null) { + MimeBodyPart attachmentPart = new MimeBodyPart(); + attachmentPart.attachFile(file); + attachmentPart.setFileName(MimeUtility.encodeText(file.getName())); + multipart.addBodyPart(attachmentPart); + //将multipart对象放入邮件 + msg.setContent(multipart); + } else if (fileList != null && fileList.size() > 0) { + // 添加附件(多个) + if (fileList != null && fileList.size() > 0) { + for (File tempfile : fileList) { + MimeBodyPart attachmentPart = new MimeBodyPart(); + attachmentPart.attachFile(tempfile); + attachmentPart.setFileName(MimeUtility.encodeText(tempfile.getName())); + multipart.addBodyPart(attachmentPart); + } + msg.setContent(multipart); + } + } + //调用Transport的send方法去发送邮件 + Transport.send(msg); + }catch (Exception e) { + e.printStackTrace(); + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + /** + * 发送带附件的邮件信息 + * + * @param to 接收方 + * @param subject 邮件主题 + * @param content 邮件内容(发送内容) + * @param fileList 文件集合 // 可发送多个附件 + */ + public void sendMessageCarryFiles(String to, String subject, String content, List fileList, String from, @NotNull JavaMailSender mailSender) { + MimeMessage mimeMessage = mailSender.createMimeMessage(); + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(from); + helper.setTo(to); + // 设置邮件主题 + helper.setSubject(subject); + // 设置邮件内容 + helper.setText(content); + // 添加附件(多个) + if (fileList != null && fileList.size() > 0) { + for (File file : fileList) { + helper.addAttachment(file.getName(), file); + } + } + } catch (MessagingException e) { + e.printStackTrace(); + } + // 发送邮件 + mailSender.send(mimeMessage); + } + + /** + * 发送带附件的邮件信息 + * + * @param to 接收方 + * @param subject 邮件主题 + * @param content 邮件内容(发送内容) + * @param file 单个文件 + */ + public void sendMessageCarryFile(String to, String subject, String content, File file, String from, JavaMailSender mailSender) { + MimeMessage mimeMessage = mailSender.createMimeMessage(); + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(from); + helper.setTo(to); + // 设置邮件主题 + helper.setSubject(subject); + // 设置邮件内容 + helper.setText(content); + // 单个附件 + helper.addAttachment(file.getName(), file); + } catch (MessagingException e) { + e.printStackTrace(); + } + // 发送邮件 + mailSender.send(mimeMessage); + } + + /** + * 初始化内外网邮件发送对象 + * + * @param num + */ +// public static JavaMailSender initJavaMailSender(Integer num) { +// if (num != null && num == 1) { +// //内网 +// return rebuildMailSender(hostIn, usernameIn, passwordIn, Integer.parseInt(portIn), "smtps"); +// } else { +// //外网 +// return rebuildMailSender(hostOut, usernameOut, passwordOut, Integer.parseInt(portOut), "smtps"); +// } +// } + +// public static String getInnerFrom() { +// return EmailInUtil; +// } +// +// public static String getOutterFrom() { +// return fromOut; +// } + + /** + * 验证邮箱格式 + * + * @param str + * @return + */ + public static boolean isEmail(String str) { + boolean flag = false; + Matcher matcher = emailPattern.matcher(str); + if (matcher.matches()) { + flag = true; + } + return flag; + } + + public static boolean isPhoneNumber(String str) { + boolean flag = false; + Matcher matcher = phonePattern.matcher(str); + if (matcher.matches()) { + flag = true; + } + return flag; + } +public void buildReceiveConnect() throws Exception { + + //POP3主机名 + String host = "pop3.163.com"; + //设置传输协议 + String protocol = "pop3"; + //用户账号 + String username = "wq18792927508@163.com"; + //密码或者授权码 + String password = "WDFHKSEMCKVRELEA"; + /* + * 获取Session + */ + Properties props = new Properties(); + //协议 + props.setProperty("mail.store.protocol", protocol); + //POP3主机名 + props.setProperty("mail.pop3.host", host); + props.setProperty("mail.smtp.auth", "true"); + props.setProperty("mail.pop3.default-encoding", "UTF-8"); + Session session = Session.getDefaultInstance(props, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(usernameOut, passwordOut); + } + }); + URLName urlName = new URLName(protocol, host, 110, null, username, password); + Store store = session.getStore(urlName); + store.connect(username, password); + + + Folder folder = store.getFolder("INBOX"); + + folder.open(Folder.READ_ONLY); + + } + /** + * 接收邮件 + */ + public List receiverMail() { + List messageIds=new ArrayList<>(); + +// session.setDebug(true); + + try { + //POP3主机名 + String host = "pop3.163.com"; + //设置传输协议 + String protocol = "pop3"; + //用户账号 + String username = "wq18792927508@163.com"; + //密码或者授权码 + String password = "WDFHKSEMCKVRELEA"; + /* + * 获取Session + */ + Properties props = new Properties(); + //协议 + props.setProperty("mail.store.protocol", protocol); + //POP3主机名 + props.setProperty("mail.pop3.host", host); + props.setProperty("mail.smtp.auth", "true"); + props.setProperty("mail.pop3.default-encoding", "UTF-8"); + Session session = Session.getDefaultInstance(props, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(usernameOut, passwordOut); + } + }); + URLName urlName = new URLName(protocol, host, 110, null, username, password); + Store store = session.getStore(urlName); + store.connect(username, password); + + + Folder folder = store.getFolder("INBOX"); + folder.open(Folder.READ_ONLY); + SearchTerm orTerm = new SubjectTerm("退信"); + // Message[] messages = folder.search(orTerm); + Date endTime= new Date(); + long oneDayMillis=24*60*60*1000L; + Date startTime=new Date(endTime.getTime()-oneDayMillis); + // SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GE, startTime); + // SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, endTime); + // SearchTerm comparisonAndTerm = new AndTerm(comparisonTermGe, comparisonTermLe); + // SearchTerm searchTerm = new AndTerm(comparisonAndTerm, orTerm); + Message[] messages = folder.search(orTerm); + if (messages != null) { + + Arrays.stream(messages).forEach(message -> { + String messageId=""; + try { + messageId = EmailUtil.getMessageId(message,session); + } catch (Exception e) { + e.printStackTrace(); + } + messageIds.add(messageId); + }); + + } + + folder.close(false); + store.close(); + } catch (Exception e) { + return messageIds; + } + return messageIds; + } + + public void analyseMail(Session session, Object content) throws Exception { + + if (content instanceof Multipart) { + Multipart multipart = (Multipart) content; + for (int i = 0; i < multipart.getCount(); i++) { + BodyPart bodyPart = multipart.getBodyPart(i); +// if (bodyPart.isMimeType("message/rfc822")) { if(bodyPart.getContentType().startsWith("Message/Rfc822")); +// MimeMessage mimeMessage = new MimeMessage(session, bodyPart.getInputStream()); +// } + if(bodyPart.isMimeType("Message/Rfc822")){ + MimeMessage mimeMessage = new MimeMessage(session, bodyPart.getInputStream()); + } + } + } + } + public static String getMessageId(Part part) throws Exception { + if (!part.isMimeType("multipart/*")) { + return ""; + } + + Multipart multipart = (Multipart) part.getContent(); + for (int i = 0; i < multipart.getCount(); i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + + if (part.isMimeType("message/rfc822")) { + return getMessageId((Part) part.getContent()); + } + InputStream inputStream = bodyPart.getInputStream(); + + try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { + String strLine; + while ((strLine = br.readLine()) != null) { + if (strLine.startsWith("Message_Id:")) { + String[] split = strLine.split("Message_Id:"); + return split.length > 1 ? split[1].trim() : null; + } + } + } + } + + return ""; + } + + +//检查退信邮件 +// Folder folder = ...; //打开收件箱 +// Message[] messages = folder.getMessages(); +// for (Message message : messages) { +// if (message.getSubject().contains("Delivery Status Notification")) { +// System.out.println("Delivery failed for recipient: " + message.getRecipients()[0]); +// } +// } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailUtil.java new file mode 100644 index 0000000..bb1f2d2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EmailUtil.java @@ -0,0 +1,68 @@ +package com.ruoyi.common.utils; + +import lombok.extern.slf4j.Slf4j; + +import javax.mail.*; +import javax.mail.internet.MimeMessage; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +@Slf4j +public final class EmailUtil { + + private static final String multipart = "multipart/*"; + + + + public static String getMessageId(Part part, Session session) throws Exception { + if (!part.isMimeType(multipart)) { + return ""; + + } + + Multipart multipart = (Multipart) part.getContent(); + for (int i = 0; i < multipart.getCount(); i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + if(bodyPart.getContentType().contains("Message/Rfc822")){ + MimeMessage mimeMessage = new MimeMessage(session, bodyPart.getInputStream()); + if(mimeMessage.getSubject()!=null&&mimeMessage.getSubject().contains("裁决书")){ + String[] split = mimeMessage.getSubject().split("裁决书"); + if(split.length>0){ + return split[0]; + } + } + } + } return ""; + } + + public static boolean isContainAttachment(Part part) { + boolean attachFlag = false; + try { + if (part.isMimeType(multipart)) { + Multipart mp = (Multipart) part.getContent(); + for (int i = 0; i < mp.getCount(); i++) { + BodyPart mpart = mp.getBodyPart(i); + String disposition = mpart.getDisposition(); + if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) + attachFlag = true; + else if (mpart.isMimeType(multipart)) { + attachFlag = isContainAttachment((Part) mpart); + } else { + String contype = mpart.getContentType(); + if (contype.toLowerCase().contains("application")) + attachFlag = true; + if (contype.toLowerCase().contains("name")) + attachFlag = true; + } + } + } else if (part.isMimeType("message/rfc822")) { + attachFlag = isContainAttachment((Part) part.getContent()); + } + } catch (MessagingException | IOException e) { + e.printStackTrace(); + } + return attachFlag; + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignApplicaConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignApplicaConfig.java new file mode 100644 index 0000000..0d5bda7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignApplicaConfig.java @@ -0,0 +1,13 @@ +package com.ruoyi.common.utils; + +public class EsignApplicaConfig { + + // 应用ID + public static final String EsignAppId = "7438987614"; + // 应用密钥 + public static final String EsignAppSecret = "9d7844f13830931037772b9d20cf1529"; + // e签宝接口调用域名(模拟环境) + public static final String EsignHost = "https://smlopenapi.esign.cn"; + // e签宝接口调用域名(正式环境) + // public static final String EsignHost = "https://openapi.esign.cn"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignHttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignHttpHelper.java new file mode 100644 index 0000000..ed255e5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignHttpHelper.java @@ -0,0 +1,178 @@ +package com.ruoyi.common.utils; + + +import com.ruoyi.common.constant.EsignEncryption; +import com.ruoyi.common.constant.EsignHeaderConstant; +import com.ruoyi.common.constant.EsignHttpCfgHelper; +import com.ruoyi.common.core.domain.entity.EsignCoreSdkInfo; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.enums.EsignRequestType; +import com.ruoyi.common.exception.EsignDemoException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * @description Http 请求 辅助类 + * @author 澄泓 + * @since JDK1.7 + */ +public class EsignHttpHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(EsignHttpHelper.class); + + /** + * 不允许外部创建实例 + */ + private EsignHttpHelper() { + + } + + /** + * @description 发送常规HTTP 请求 + * + * @param reqType 请求方式 + * @param url 请求路径 + * @param paramStr 请求参数 + * @return + * @throws EsignDemoException + * @author 澄泓 + */ + public static EsignHttpResponse doCommHttp(String host, String url, EsignRequestType reqType, Object paramStr , Map httpHeader, boolean debug) throws EsignDemoException { + + return EsignHttpCfgHelper.sendHttp(reqType, host+url,httpHeader, paramStr, debug); + + } + + + /** + * @description 发送文件流上传 HTTP 请求 + * + * @param reqType 请求方式 + * @param uploadUrl 请求路径 + * @param param 请求参数 + * @param fileContentMd5 文件fileContentMd5 + * @param contentType 文件MIME类型 + * @return + * @throws EsignDemoException + * @author 澄泓 + */ + public static EsignHttpResponse doUploadHttp( String uploadUrl,EsignRequestType reqType,byte[] param, String fileContentMd5, + String contentType, boolean debug) throws EsignDemoException { + Map uploadHeader = buildUploadHeader(fileContentMd5, contentType); + if(debug){ + LOGGER.info("----------------------------start------------------------"); + LOGGER.info("fileContentMd5:{}",fileContentMd5); + LOGGER.info("contentType:{}",contentType); + } + return EsignHttpCfgHelper.sendHttp(reqType,uploadUrl, uploadHeader, param,debug); + } + + + + /** + * @description 构建一个签名鉴权+json数据的esign请求头 + * @return + * @author 澄泓 + */ + public static Map buildSignAndJsonHeader(String projectId,String contentMD5,String accept,String contentType,String authMode) { + + Map header = new HashMap<>(); + header.put("X-Tsign-Open-App-Id", projectId); + header.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion()); + header.put("X-Tsign-Open-Ca-Timestamp", EsignEncryption.timeStamp()); + header.put("Accept",accept); + header.put("Content-MD5",contentMD5); + header.put("Content-Type", contentType); + header.put("X-Tsign-Open-Auth-Mode", authMode); + return header; + } + + /** + * 签名计算并且构建一个签名鉴权+json数据的esign请求头 + * @param httpMethod + * * The name of a supported {@linkplain java.nio.charset.Charset + * * charset} + * @return + */ + public static Map signAndBuildSignAndJsonHeader(String projectId, String secret,String paramStr,String httpMethod,String url,boolean debug) throws EsignDemoException { + String contentMD5=""; + //统一转大写处理 + httpMethod = httpMethod.toUpperCase(); + if("GET".equals(httpMethod)||"DELETE".equals(httpMethod)){ + paramStr=null; + contentMD5=""; + } else if("PUT".equals(httpMethod)||"POST".equals(httpMethod)){ + //对body体做md5摘要 + contentMD5= EsignEncryption.doContentMD5(paramStr); + }else{ + throw new EsignDemoException(String.format("不支持的请求方法%s",httpMethod)); + } + //构造一个初步的请求头 + Map esignHeaderMap = buildSignAndJsonHeader(projectId, contentMD5, EsignHeaderConstant.ACCEPT.VALUE(), EsignHeaderConstant.CONTENTTYPE_JSON.VALUE(), EsignHeaderConstant.AUTHMODE.VALUE()); + //排序 + url=EsignEncryption.sortApiUrl(url); + //传入生成的bodyMd5,加上其他请求头部信息拼接成字符串 + String message = EsignEncryption.appendSignDataString(httpMethod, esignHeaderMap.get("Content-MD5"),esignHeaderMap.get("Accept"),esignHeaderMap.get("Content-Type"),esignHeaderMap.get("Headers"),esignHeaderMap.get("Date"), url); + //整体做sha256签名 + String reqSignature = EsignEncryption.doSignatureBase64(message, secret); + //请求头添加签名值 + esignHeaderMap.put("X-Tsign-Open-Ca-Signature",reqSignature); + if(debug){ + LOGGER.info("----------------------------start------------------------"); + LOGGER.info("待计算body值:{}", paramStr+"\n"); + LOGGER.info("MD5值:{}",contentMD5+"\n"); + LOGGER.info("待签名字符串:{}",message+"\n"); + LOGGER.info("签名值:{}",reqSignature+"\n"); + } + return esignHeaderMap; + } + + + /** + * @description 构建一个Token鉴权+jsons数据的esign请求头 + * @return + * @author 澄泓 + */ + public static Map buildTokenAndJsonHeader(String appid,String token) { + Map esignHeader = new HashMap<>(); + esignHeader.put("X-Tsign-Open-Version-Sdk", EsignCoreSdkInfo.getSdkVersion()); + esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_JSON.VALUE()); + esignHeader.put("X-Tsign-Open-App-Id", appid); + esignHeader.put("X-Tsign-Open-Token", token); + return esignHeader; + } + + /** + * @description 构建一个form表单数据的esign请求头 + * @return + * @author 澄泓 + */ + public static Map buildFormDataHeader(String appid) { + Map esignHeader = new HashMap<>(); + esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion()); + esignHeader.put("X-Tsign-Open-Authorization-Version","v2"); + esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_FORMDATA.VALUE()); + esignHeader.put("X-Tsign-Open-App-Id", appid); + return esignHeader; + } + + /** + * @description 创建文件流上传 请求头 + * + * @param fileContentMd5 + * @param contentType + * @return + * @author 澄泓 + */ + public static Map buildUploadHeader(String fileContentMd5, String contentType) { + Map header = new HashMap<>(); + header.put("Content-MD5", fileContentMd5); + header.put("Content-Type", contentType); + + return header; + } + + // ------------------------------私有方法end---------------------------------------------- +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java new file mode 100644 index 0000000..214e4a0 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtils.java new file mode 100644 index 0000000..04cef0f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtils.java @@ -0,0 +1,57 @@ +package com.ruoyi.common.utils; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +/** + * @author wangqiong + * @description 根据身份证号提取有效信息 + * @date 2023-12-11 11:45 + */ +public class IdCardUtils { + /** + * 通过身份证号码获取出生日期、性别、年龄 + * @param certificateNo + * @return 返回的出生日期格式:1990-01-01 性别格式:1-女,0-男 + */ + public static Map getBirAgeSex(String certificateNo) { + String birthday = ""; + String age = ""; + String sexCode = ""; + + int year = Calendar.getInstance().get(Calendar.YEAR); + char[] number = certificateNo.toCharArray(); + boolean flag = true; + if (number.length == 15) { + for (int x = 0; x < number.length; x++) { + if (!flag) return new HashMap(); + flag = Character.isDigit(number[x]); + } + } else if (number.length == 18) { + for (int x = 0; x < number.length - 1; x++) { + if (!flag) return new HashMap(); + flag = Character.isDigit(number[x]); + } + } + if (flag && certificateNo.length() == 15) { + birthday = "19" + certificateNo.substring(6, 8) + "-" + + certificateNo.substring(8, 10) + "-" + + certificateNo.substring(10, 12); + sexCode = Integer.parseInt(certificateNo.substring(certificateNo.length() - 3, certificateNo.length())) % 2 == 0 ? "1" : "0"; + age = (year - Integer.parseInt("19" + certificateNo.substring(6, 8))) + ""; + } else if (flag && certificateNo.length() == 18) { + birthday = certificateNo.substring(6, 10) + "-" + + certificateNo.substring(10, 12) + "-" + + certificateNo.substring(12, 14); + sexCode = Integer.parseInt(certificateNo.substring(certificateNo.length() - 4, certificateNo.length() - 1)) % 2 == 0 ? "1" : "0"; + age = (year - Integer.parseInt(certificateNo.substring(6, 10))) + ""; + } + Map map = new HashMap(); + map.put("birthday", birthday); + map.put("age", age); + map.put("sexCode", sexCode); + return map; + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdWorkerUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdWorkerUtil.java new file mode 100644 index 0000000..e9f2af4 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdWorkerUtil.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.utils; + +import cn.hutool.core.lang.Snowflake; +import cn.hutool.core.util.IdUtil; +import com.ruoyi.common.utils.uuid.UUID; + +import java.math.BigInteger; +import java.util.Random; + +/** + * 雪花算法工具类 + * zq + * @since 2020/10/30 9:59 + **/ +public class IdWorkerUtil { + private static final long EPOCH = 1479533469598L; //开始时间,固定一个小于当前时间的毫秒数 + private static final int max12bit = 4095; + private static final long max41bit= 1099511627775L; + private static String machineId = "" ; // 机器ID + + /** + * + * 创建ID + * + * @return + * + */ + public static Long getId(){ + + long time = System.currentTimeMillis() - EPOCH + max41bit; + // 二进制的 毫秒级时间戳 + String base = Long.toBinaryString(time); + + // 序列数 + String randomStr = StringUtils.leftPad(Integer.toBinaryString(new Random().nextInt(max12bit)),12,'0'); + if(StringUtils.isNotEmpty(machineId)){ + machineId = StringUtils.leftPad(machineId, 10, '0'); + } + + //拼接 + String appendStr = base + machineId + randomStr; + // 转化为十进制 返回 + BigInteger bi = new BigInteger(appendStr, 2); + + return Long.valueOf(bi.toString()); + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java new file mode 100644 index 0000000..0de30c6 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java new file mode 100644 index 0000000..7dac75a --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/MoneyFormatUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MoneyFormatUtils.java new file mode 100644 index 0000000..5436693 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MoneyFormatUtils.java @@ -0,0 +1,53 @@ +package com.ruoyi.common.utils; + +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +/** + * @author wangqiong + * @description 金额格式化 + * @date 2023-12-11 11:45 + */ +public class MoneyFormatUtils { + + /** + * 增加千分位 + * @param money + * @return + */ + public static String moneyFormat(String money) { + // 金额格式化 + try { + Double.parseDouble(money); + + } catch (NumberFormatException e) { + + String regEx = "[^0-9]"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(money); + String result = m.replaceAll("").trim(); + BigDecimal bigDecimal = null; + if (money.contains("百")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("100")); + } else if (money.contains("千")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("1000")); + } else if (money.contains("万")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("10000")); + } else if (money.contains("百万")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("1000000")); + } else if (money.contains("千万")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("10000000")); + } else if (money.contains("亿")) { + bigDecimal = new BigDecimal(result).multiply(new BigDecimal("100000000")); + } + + NumberFormat format = NumberFormat.getInstance(); + return format.format(bigDecimal); + + } + return ""; + } + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ObjectFieldUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ObjectFieldUtils.java new file mode 100644 index 0000000..5b469c6 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ObjectFieldUtils.java @@ -0,0 +1,57 @@ +package com.ruoyi.common.utils; + +import cn.hutool.core.util.StrUtil; + +import java.lang.reflect.Field; + +/** + * 反射工具类 + */ +public class ObjectFieldUtils { + public static String getValue(Object obj,String fieldName){ + if(obj==null || StrUtil.isEmpty(fieldName)){ + return ""; + } + Field field=null; + try{ + field=obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return String.valueOf(field.get(obj)==null?"":field.get(obj)); + }catch (Exception e){ + if(obj.getClass().getSuperclass()!=Object.class){ + try{ + field=obj.getClass().getSuperclass().getDeclaredField(fieldName); + field.setAccessible(true); + return String.valueOf(field.get(obj)==null?"":field.get(obj)); + }catch (Exception e1){ + e.printStackTrace(); + } + } + e.printStackTrace(); + } + return null; + } + + public static void setValue(Object obj,String fieldName,Object value){ + if(obj==null || StrUtil.isEmpty(fieldName)||value==null){ + return; + } + Field field=null; + try{ + field=obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj,value); + }catch (Exception e){ + if(obj.getClass().getSuperclass()!=Object.class){ + try{ + field=obj.getClass().getSuperclass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj,value); + }catch (Exception e1){ + e.printStackTrace(); + } + } + e.printStackTrace(); + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java new file mode 100644 index 0000000..70e9b08 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/PdfUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PdfUtils.java new file mode 100644 index 0000000..05afb65 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PdfUtils.java @@ -0,0 +1,147 @@ +package com.ruoyi.common.utils; + +import com.documents4j.api.DocumentType; +import com.documents4j.api.IConverter; +import com.documents4j.job.LocalConverter; +import com.itextpdf.text.Document; +import com.itextpdf.text.Font; +import com.itextpdf.text.PageSize; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfWriter; +import com.itextpdf.tool.xml.XMLWorkerFontProvider; +import com.itextpdf.tool.xml.XMLWorkerHelper; +import com.ruoyi.common.config.RuoYiConfig; +import com.tencentcloudapi.teo.v20220901.models.CC; +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.nio.charset.Charset; +import java.nio.file.Files; + +import static cn.hutool.core.util.ClassLoaderUtil.getClassLoader; + +/** + * @author wangqiong + * @description pdf转换工具类 + * @date 2023-11-28 15:20 + */ +@Slf4j +public class PdfUtils { + /** + * 将html字符串转为pdf + * @param pdfFilePath 保存的路径 + * @param htmlcontent:必须是完整的html格式,比如123 + */ + public static boolean htmlStringConvertToPDF(String pdfFilePath, String htmlcontent) { + Document document = new Document(); + PdfWriter writer = null; + try { + writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath)); + // 设置底部距离60,解决重叠问题 + + document.setPageSize(PageSize.A4); + document.setMargins(50, 45, 50, 60); + document.setMarginMirroring(false); + document.open(); + // 解决PDF中文不显示 + String fontPath = "/D:/simsun.ttf"; //字体文件路径 + XMLWorkerFontProvider provider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); + provider.register(fontPath);//注册字体 + log.error("注册字体"); + XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmlcontent.getBytes("UTF-8")), Charset.forName("UTF-8"), provider); + } catch (Exception e) { + log.error("htmlStringConvertToPDF error", e.getMessage()); + return false; + } finally { + if (null != document) { + document.close(); + } + if (null != writer) { + writer.close(); + } + } + return true; + } + /** + * 根据html文件生成pdf + * @param pdfFilePath pdf文件生成路径 + * @param htmlFilePath html文件路径 + */ + public static boolean htmlFileConvertToPDF(String pdfFilePath, String htmlFilePath) { + Document document = new Document(); + PdfWriter writer = null; + FileOutputStream fileOutputStream = null; + FileInputStream fileInputStream = null; + try { + fileOutputStream = new FileOutputStream(pdfFilePath); + writer = PdfWriter.getInstance(document, fileOutputStream); + // 设置底部距离60,解决重叠问题 + document.setPageSize(PageSize.A4); + document.setMargins(50, 45, 50, 60); + document.setMarginMirroring(false); + document.open(); + StringBuffer sb = new StringBuffer(); + fileInputStream = new FileInputStream(htmlFilePath); + BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8")); + String readStr = ""; + while ((readStr = br.readLine()) != null) { + sb.append(readStr); + } + XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(sb.toString().getBytes("Utf-8")), null, Charset.forName("UTF-8")); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (null != document) { + document.close(); + } + if (null != writer) { + writer.close(); + } + if (null != fileInputStream) { + try { + fileInputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != fileOutputStream) { + try { + fileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return true; + } + + /** + * docx转pdf + * @param pdfSaveDirectory:文件保存目录,例:D:\\pdf\\ + * @param fileName:保存的文件名称,例:test.pdf + * @param docxFile:需要转换的docx文件 + * @return + */ + private static boolean docxConvertToPDF(String pdfSaveDirectory,String fileName,File docxFile) { + // 不存在则新建 + File directory = new File(pdfSaveDirectory); + if (!directory.exists()) { + directory.mkdirs(); + } + String pdfFilePath = pdfSaveDirectory + fileName; + File outputFile = new File(pdfFilePath); + try { + InputStream docxInputStream = Files.newInputStream(docxFile.toPath()); + OutputStream outputStream = Files.newOutputStream(outputFile.toPath()); + IConverter converter = LocalConverter.builder().build(); + converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute(); + docxInputStream.close(); + outputStream.close(); + + } catch (Exception e) { + return false; + } + return true; + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ReadFileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ReadFileUtils.java new file mode 100644 index 0000000..870f4af --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ReadFileUtils.java @@ -0,0 +1,86 @@ +package com.ruoyi.common.utils; + +import org.apache.poi.hwpf.extractor.WordExtractor; +import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +import java.io.*; + +/** + * @author wangqiong + * @description 读取文件内容 + * @date 2023-12-11 11:45 + */ +public class ReadFileUtils { + + + public static String readerTxtFile(String filePath){ + BufferedReader br=null; + StringBuilder result=new StringBuilder(); + try { + br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)),"GBK")); + String line=null; + while ((line=br.readLine())!=null) { + result.append(line).append("\n"); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (null!=br){ + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return result.toString(); + } + public static String readWord(String filePath) throws Exception{ + + File file = new File(filePath); + if(file.length()==0) return ""; // 需要操作原因是可能会空文件问题,如果不做处理,在下面读取中会报错 + StringBuffer sb = new StringBuffer(); + String buffer = ""; + try { + if (filePath.endsWith(".doc")) { + InputStream is = new FileInputStream(file); + WordExtractor ex = new WordExtractor(is); + buffer = ex.getText(); + if(buffer.length() > 0){ + //使用回车换行符分割字符串 + String [] arry = buffer.split("r\\n"); + for (String string : arry) { + sb.append(string.trim()); + } + } + } else if (filePath.endsWith(".docx")) { + FileInputStream fis = new FileInputStream(file); + XWPFDocument xdoc = new XWPFDocument(fis); + XWPFWordExtractor extractor = new XWPFWordExtractor(xdoc); + buffer = extractor.getText(); + sb.append(buffer!=null?buffer:""); + + +// OPCPackage opcPackage = POIXMLDocument.openPackage(filePath); +// XWPFWordExtractor extractor = new XWPFWordExtractor(opcPackage); +// buffer = extractor.getText(); +// if(buffer.length() > 0){ +// //使用换行符分割字符串 +// String [] arry = buffer.split("\n"); +// for (String string : arry) { +// sb.append(string.trim()); +// } +// } + } else { + return null; + } + return sb.toString(); + } catch (Exception e) { + System.out.print("error---->"+filePath); + e.printStackTrace(); + return null; + } + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SealUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SealUtil.java new file mode 100644 index 0000000..9cab428 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SealUtil.java @@ -0,0 +1,123 @@ +package com.ruoyi.common.utils; + +import com.ruoyi.common.config.EsignDemoConfig; +import com.ruoyi.common.constant.EsignHeaderConstant; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.enums.EsignRequestType; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.utils.bean.EsignFileBean; + +import java.util.Map; + +public class SealUtil { + private static String eSignHost = EsignDemoConfig.EsignHost; + private static String eSignAppId = EsignDemoConfig.EsignAppId; + private static String eSignAppSecret = EsignDemoConfig.EsignAppSecret; + + /** + * 获取机构认证&授权页面链接 + * + * @return + */ + public static EsignHttpResponse getOrgEmpower() throws EsignDemoException { + String apiaddr = "/v3/org-auth-url"; + String nickName = "何进波"; + String phonenumber = "15191509780"; + String deptName = "西安云美公司"; + String jsonParm = "{\n" + + " \"orgAuthConfig\": {\n" + + " \"orgName\": \"" + deptName + " \",\n" + + " \"transactorInfo\": {\n" + + " \"psnAccount\": \"" + phonenumber + "\",\n" + + " \"psnInfo\": {\n" + + " \"psnName\": \"" + nickName + "\",\n" + + " \"psnMobile\": \"" + phonenumber + "\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"authorizeConfig\": {\n" + + " \"authorizedScopes\": [\n" + + " \"get_org_identity_info\",\n" + + " \"get_psn_identity_info\",\n" + + " \"org_initiate_sign\",\n" + + " \"psn_initiate_sign\",\n" + + " \"manage_org_resource\",\n" + + " \"manage_psn_resource\",\n" + + " \"use_org_order\"\n" + + " ]\n" + + " }\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true); + + } + /** + * 查询认证授权流程详情 + * + * @return + */ + public static EsignHttpResponse queryAuthProcess(String authFlowId ) throws EsignDemoException { + String apiaddr = "/v3/auth-flow/" + authFlowId; + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm=null; + //请求方法 + EsignRequestType requestType= EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true); + } + + + + + /** + * 步骤一:获取印章图片上传地址fileUploadUrl + * + * @return + */ + public static EsignHttpResponse getFileUploadUrl(String filePath) throws EsignDemoException { + //自定义的文件封装类,传入文件地址可以获取文件的名称大小,文件流等数据 + EsignFileBean esignFileBean = new EsignFileBean(filePath); + String apiaddr="/v3/files/file-key"; + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm="{\n" + + " \"contentMd5\": \""+esignFileBean.getFileContentMD5()+"\",\n" + + " \"fileName\":\""+esignFileBean.getFileName()+"\"," + + " \"fileSize\": "+esignFileBean.getFileSize()+",\n" + + " \"contentType\": \""+ EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE()+"\"\n" + + "}"; + //请求方法 + EsignRequestType requestType= EsignRequestType.POST; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true); + } + + /** + * 步骤二:将印章图片文件流上传到fileUploadUrl + * + * @return + */ + public static EsignHttpResponse fileStreamUpload(String uploadUrl,String filePath) throws EsignDemoException { + //根据文件地址获取文件contentMd5 + EsignFileBean esignFileBean = new EsignFileBean(filePath); + //请求方法 + EsignRequestType requestType= EsignRequestType.PUT; + return EsignHttpHelper.doUploadHttp(uploadUrl,requestType,esignFileBean.getFileBytes(),esignFileBean.getFileContentMD5(), EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE(),true); + } + public static void main(String[] args) throws Exception { + queryAuthProcess("OF-2b1e52987408005c"); + // createOrgByImage(); + // getOrgEmpower(); + // queryAuthProcess("OF-2b00885895080028"); + // getFileUploadUrl(); +// String uplodUrl = "https://esignoss.esign.cn/7438987614/8e278262-5960-4004-bff3-297c11e2652e/Snipaste_2023-10-27_09-59-23.jpg?Expires=1699439095&OSSAccessKeyId=STS.NTZ8NBHcTVQXgsxVRH4iyC5AY&Signature=3yu3ZQifphZsnOgN0CI0SJdqFhY%3D&callback-var=eyJ4OmZpbGVfa2V5IjoiJDliM2Y3ZjkyLTdkOWUtNGZkZi04NWU4LWE4ZDU4MzEwZjIzOCQ0MTQwNTE2ODk5In0%3D%0A&callback=eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9zbWx0YXBpLnRzaWduLmNuL2FueWRvb3IvZmlsZS1zeXN0ZW0vY2FsbGJhY2svYWxpb3NzIiwiY2FsbGJhY2tCb2R5IjogIntcIm1pbWVUeXBlXCI6JHttaW1lVHlwZX0sXCJzaXplXCI6ICR7c2l6ZX0sXCJidWNrZXRcIjogJHtidWNrZXR9LFwib2JqZWN0XCI6ICR7b2JqZWN0fSxcImV0YWdcIjogJHtldGFnfSxcImZpbGVfa2V5XCI6JHt4OmZpbGVfa2V5fX0iLCJjYWxsYmFja0JvZHlUeXBlIjogImFwcGxpY2F0aW9uL2pzb24ifQ%3D%3D%0A&security-token=CAIS%2BAF1q6Ft5B2yfSjIr5fvc%2FT2pbx14ZOzZVXJslIdOOZVrPDquzz2IHtKdXRvBu8Xs%2F4wnmxX7f4YlqB6T55OSAmcNZEoWWWTbdH4MeT7oMWQweEurv%2FMQBqyaXPS2MvVfJ%2BOLrf0ceusbFbpjzJ6xaCAGxypQ12iN%2B%2Fm6%2FNgdc9FHHPPD1x8CcxROxFppeIDKHLVLozNCBPxhXfKB0ca0WgVy0EHsPnvm5DNs0uH1AKjkbRM9r6ceMb0M5NeW75kSMqw0eBMca7M7TVd8RAi9t0t1%2FIVpGiY4YDAWQYLv0rda7DOltFiMkpla7MmXqlft%2BhzcgeQY0pc%2FRqAAXGx8FDtPQxW3RSasFgOFBJaxbYjH3WFFrbV25v8a%2BS9OWPAYqOCvmkxbM7N4hOge2iaBAG4SRLMb6ypPJ15YEpoZI8KkdeDvQJryZEWchmc0Lhz0yDRqrN%2BzYhgu4VpBJu1WJg%2FyXrvAZ0gWhBN%2BILrblSR9QHVWVVYZTAKN4ejIAA%3D"; +// fileStreamUpload(uplodUrl,"D:\\develop\\Snipaste_2023-10-27_09-59-23.jpg"); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java new file mode 100644 index 0000000..a6f3d53 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java new file mode 100644 index 0000000..febb603 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java new file mode 100644 index 0000000..ff0ce9e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java @@ -0,0 +1,78 @@ +package com.ruoyi.common.utils; + +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.cvm.v20170312.CvmClient; +import com.tencentcloudapi.cvm.v20170312.models.DescribeRegionsRequest; +import com.tencentcloudapi.cvm.v20170312.models.DescribeRegionsResponse; +import com.tencentcloudapi.sms.v20210111.SmsClient; +import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; +import com.tencentcloudapi.sms.v20210111.models.SendStatus; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import lombok.var; + +import java.util.Objects; + +@Slf4j +public class SmsUtils { + //应用id + private static final String SDK_APP_ID = "1400854852"; + //API的SecretId + private static final String SECRET_ID = "AKIDeEf2A8uX1HSainvvnXAc3X9ZlhtyvkMp"; + //API的SecretKey + private static final String SECRET_KEY = "QjphKo8zkHZigT8j9PVtFPJyfIvO3d6V"; + //签名内容 + private static final String SIGN_NAME = "乙巢智慧仲裁网"; + + public static Boolean sendSms(SendSmsRequest request) { + Credential cred = new Credential(SECRET_ID, SECRET_KEY ); + + SmsClient client = new SmsClient(cred, "ap-guangzhou"); + + final var req = new com.tencentcloudapi.sms.v20210111.models.SendSmsRequest(); + req.setPhoneNumberSet(new String[]{"+86" + request.getPhone()}); + req.setSmsSdkAppId(SDK_APP_ID ); + req.setSignName(SIGN_NAME); + req.setTemplateId(request.getTemplateId()); + req.setTemplateParamSet(request.getTemplateParamSet()); + SendSmsResponse res = null; + try { + res = client.SendSms(req); + } catch (TencentCloudSDKException e) { + log.error("发送短信出错:", e); + return Boolean.FALSE; + } + SendStatus sendStatus = res.getSendStatusSet()[0]; + log.info("发送短信结果:Code={}, Message={}", sendStatus.getCode(), sendStatus.getMessage()); + + if (Objects.nonNull(res.getSendStatusSet()) && res.getSendStatusSet().length > 0 && "Ok".equals(res.getSendStatusSet()[0].getCode())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + } + /** + * 参数对象 + */ + @Data + public static class SendSmsRequest { + /** + * 电话 + */ + private String phone; + + /** + * 模板 ID: 必须填写已审核通过的模板 ID + */ + private String templateId; + + /** + * 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 + */ + private String[] templateParamSet; + private Long caseId; + + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtil.java new file mode 100644 index 0000000..9f36643 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtil.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @author wangqiong + * @description 获取bean工具类 + * @date 2023-12-11 11:45 + */ +@Component +public class SpringUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if(SpringUtil.applicationContext==null){ + SpringUtil.applicationContext=applicationContext; + } + } + + public static ApplicationContext getApplicationContext(){ + return applicationContext; + } + + public static T getBean(Class clazz){ + return getApplicationContext().getBean(clazz); + } + + public static T getBean(String name, Class clazz){ + return getApplicationContext().getBean(name,clazz); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java new file mode 100644 index 0000000..e683d54 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java new file mode 100644 index 0000000..71fe6d5 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java new file mode 100644 index 0000000..236fee7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java @@ -0,0 +1,210 @@ +package com.ruoyi.common.utils; + + +import cn.hutool.core.io.resource.ClassPathResource; +import com.deepoove.poi.XWPFTemplate; +import com.deepoove.poi.config.Configure; +import com.deepoove.poi.data.*; +import com.deepoove.poi.data.style.ParagraphStyle; +import com.deepoove.poi.data.style.Style; +import com.deepoove.poi.policy.PictureRenderPolicy; +import com.deepoove.poi.util.PoitlIOUtils; +import org.apache.commons.io.FileUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.wp.usermodel.Paragraph; +import org.apache.poi.xwpf.usermodel.*; + +import javax.print.Doc; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 文档生成工具类 + */ +public class WordUtil { + + private CellRenderData cell; + + /** + * 查询生成的word文件流 + * + * @param response + * @param datas + * @param modalFilePath + * @param resultFilePath + * @throws IOException + */ + public static void getDocStreamFile(HttpServletResponse response, Map datas, String modalFilePath, String resultFilePath, String fileName) throws IOException { + //获取word模板和填充数据 + XWPFTemplate template = XWPFTemplate.compile(modalFilePath).render(datas); + //设置返回类型及文件名 + response.setContentType("application/octet-stream"); + response.setHeader("Content-disposition", "attachment;filename=\"" + fileName + "\""); + //获取返回输出流 + OutputStream out = response.getOutputStream(); + BufferedOutputStream bos = new BufferedOutputStream(out); + template.write(bos); + bos.flush(); + out.flush(); + PoitlIOUtils.closeQuietlyMulti(template, bos, out); + } + + /** + * 查询生成的word文件路径 + * + * @param datas + * @param modalFilePath + * @param resultFilePath + * @return + * @throws IOException + */ + public static String getDocFilePath(Map datas, String modalFilePath, String resultFilePath) throws IOException { + //获取word模板和填充数据 + XWPFTemplate template = XWPFTemplate.compile(modalFilePath).render(datas); + template.writeAndClose(new FileOutputStream(resultFilePath)); + return resultFilePath; + } + + /** + * 构造绘制表格的方法 + */ + public static TableRenderData rebuildWordTableData(List headerList, String headerBackgroundColor, String textColor, List> tableContentList) { + RowRenderData header = rebuildWordTableHead(headerList, headerBackgroundColor, textColor); + List content = rebuildWordTableContent(tableContentList); + TableRenderData tableRenderData = Tables.create().addRow(header); + for (int i = 0; content != null && i < content.size(); i++) { + tableRenderData.addRow(content.get(i)); + } + return tableRenderData; + } + + /** + * 构造表格表头 + * + * @return + */ + public static RowRenderData rebuildWordTableHead(List headerList, String headerBackgroundColor, String textColor) { + RowRenderData header = new RowRenderData(); + for (int i = 0; headerList != null && i < headerList.size(); i++) { + CellRenderData cellRenderData = new CellRenderData(); + ParagraphRenderData paragraphRenderData = new ParagraphRenderData(); + Style style = new Style(); + style.setColor(textColor); + style.setFontSize(12.0); + ParagraphStyle paragraphStyle = ParagraphStyle.builder() + .withAlign(ParagraphAlignment.CENTER) + // .withBackgroundColor(headerBackgroundColor) + .withDefaultTextStyle(style) + .build(); + paragraphRenderData.addText(headerList.get(i)); + paragraphRenderData.setParagraphStyle(paragraphStyle); + cellRenderData.addParagraph(paragraphRenderData); + header.addCell(cellRenderData); + } + return header; + } + + /** + * 构造表格内容 + * + * @return + */ + public static List rebuildWordTableContent(List> tableContentList) { + List rowContentList = new ArrayList<>(); + for (int i = 0; tableContentList != null && i < tableContentList.size(); i++) { + List rowdataList = tableContentList.get(i); + RowRenderData rowcontent = new RowRenderData(); + for (int j = 0; rowdataList != null && j < rowdataList.size(); j++) { + CellRenderData cellRenderData = new CellRenderData(); + ParagraphRenderData paragraphRenderData = new ParagraphRenderData(); + Style style = new Style(); + style.setFontSize(12.0); + ParagraphStyle paragraphStyle = ParagraphStyle.builder() + .withAlign(ParagraphAlignment.CENTER) + .withDefaultTextStyle(style) + .build(); + paragraphRenderData.addText(rowdataList.get(j)); + paragraphRenderData.setParagraphStyle(paragraphStyle); + cellRenderData.addParagraph(paragraphRenderData); + rowcontent.addCell(cellRenderData); + } + rowContentList.add(rowcontent); + } + return rowContentList; + } + + /** + * 构建图片内容 + */ + public static PictureRenderData rebuildImageContent(Integer with, Integer height, String imageUrl, String relatedPath) { + PictureRenderData pictureRenderData = null; + if (!StringUtils.isBlank(imageUrl)) { + //pictureRenderData = Pictures.of(imageUrl).size(with, height).create(); + //Pictures.PictureBuilder pictureBuilder = Pictures.of("https://res.wx.qq.com/a/wx_fed/weixin_portal/res/static/img/1EtCRvm.png"); + } else if (!StringUtils.isBlank(relatedPath)) { + pictureRenderData = Pictures.ofLocal(relatedPath).size(with, height).create(); +// Pictures.PictureBuilder pictureBuilder = Pictures.of("https://res.wx.qq.com/a/wx_fed/weixin_portal/res/static/img/1EtCRvm.png"); + } + return pictureRenderData; + + } + + public static String getResultFilePath(Map datas, Configure config, String modalFilePath, String resultFilePath) throws IOException { + //获取word模板和填充数据 + XWPFTemplate template = XWPFTemplate.compile(modalFilePath, config).render(datas); + template.writeAndClose(new FileOutputStream(resultFilePath)); + return resultFilePath; + } + + public static void changeText(XWPFDocument document) { + //获取文字段落集合 + List paragraphs = document.getParagraphs(); + //所有类型集合(文字段落、表格、图片等) + List listBe = document.getBodyElements(); + List runList = new ArrayList<>(); + int n = 0; + + for (int i = 0; i < listBe.size(); i++) { + + //BodyElementType.PARAGRAPH : 枚举中的文字段落 + //文字为空时,先添加到list中; + //注意picture类型也在PARAGRAPH中,需要校验embeddedPictures的长度是否为0 + //为0表示空行,大于0表示有图片,可能还有其他类型,暂时没遇到,各位自行斟酌 + if (paragraphs.size() > n && !paragraphs.get(n).getRuns().isEmpty()) { + if (StringUtils.isEmpty(paragraphs.get(n).getRuns().get(0).text()) + && paragraphs.get(n).getRuns().get(0).getEmbeddedPictures().size() == 0) { + + runList.add(i); + + } + } + n++; + + //非文字段落n-1 + if (listBe.get(i).getElementType() != BodyElementType.PARAGRAPH) { + n--; + } + + } + + //遍历list删除 + if (!runList.isEmpty()) { + for (int i = runList.size() - 1; i >= 0; i--) { + int index = runList.get(i); + if (index >= 0 && index < document.getBodyElements().size()) { + document.removeBodyElement(index); + } + } + } + } + + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletNotifyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletNotifyUtils.java new file mode 100644 index 0000000..f7a0fc7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletNotifyUtils.java @@ -0,0 +1,64 @@ +package com.ruoyi.common.utils; + +/** + * @author wangqiong + * @description 获取微信小程序url scheme + * @date 2023-10-13 10:16 + */ + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; + +public class WxAppletNotifyUtils { + + /** + * scheme 跳转微信小程序,需中转H5 + + */ + public static String jumpAppletSchemeUrl(){ + + String token= getAccessToken(); + + //接口地址 + String url = "https://api.weixin.qq.com/wxa/generatescheme?access_token="+token; + JSONObject body = JSONUtil.createObj(); + JSONObject jumpWxa = JSONUtil.createObj(); + jumpWxa.putOpt("path","pages/login"); + jumpWxa.putOpt("query",""); + jumpWxa.putOpt("env_version","release"); + body.putOpt("jump_wxa",jumpWxa); + //链接过期类型:0时间戳 1间隔天数 + body.putOpt("expire_type",1); + body.putOpt("is_expire",true); + //指定失效天数,最多30 + body.putOpt("expire_interval",30); + String post = HttpUtil.post(url,body.toJSONString(2)); + JSONObject result = JSONUtil.parseObj(post); + if(result!=null && result.containsKey("openlink")){ + return result.getStr("openlink"); + } + return null; + } + + + //凭证调用 + public static String getAccessToken(){ + String token; + //小程序APPID + String appid="wx91cb8459dca561b4";//自行获取 + //小程序secret + String secret="190aaa3bda96a65d25318fbb0e133fc6";//自己去公众号后台获取 + String httpUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"; + + httpUrl= httpUrl+"&appid="+appid+"&secret="+secret; + //get请求 + String result = HttpUtil.get(httpUrl); + //解析结果 + JSONObject jsonObject = JSONUtil.parseObj(result); + //get AccessToken + token=jsonObject.get("access_token",String.class,false); + return token; + } + +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java new file mode 100644 index 0000000..4463662 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java new file mode 100644 index 0000000..80bfed7 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/EsignFileBean.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/EsignFileBean.java new file mode 100644 index 0000000..5f46713 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/EsignFileBean.java @@ -0,0 +1,57 @@ +package com.ruoyi.common.utils.bean; + + +import com.ruoyi.common.constant.FileTransformation; +import com.ruoyi.common.exception.EsignDemoException; + +import java.io.File; + +/** + * @description 文件基础信息封装类 + * @author 澄泓 + * @date 2020/10/26 14:54 + * @version JDK1.7 + */ +public class EsignFileBean { + //文件名称 + private String fileName; + //文件大小 + private int fileSize; + //文件内容MD5 + private String fileContentMD5; + //文件地址 + private String filePath; + + + public EsignFileBean(String filePath) throws EsignDemoException { + this.filePath=filePath; + this.fileContentMD5 = FileTransformation.getFileContentMD5(filePath); + File file = new File(filePath); + if (!file.exists()) { + throw new EsignDemoException("文件不存在"); + } + this.fileName = file.getName(); + this.fileSize = (int) file.length(); + } + + public String getFileName() { + return fileName; + } + + public int getFileSize() { + return fileSize; + } + + public String getFileContentMD5() { + return fileContentMD5; + } + + /** + * 传入本地文件地址获取二进制数据 + * @return + * @throws EsignDemoException + */ + public byte[] getFileBytes() throws EsignDemoException { + return FileTransformation.fileToBytes(filePath); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java new file mode 100644 index 0000000..68130b9 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java new file mode 100644 index 0000000..d9f2b13 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java new file mode 100644 index 0000000..b659420 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -0,0 +1,305 @@ +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; + } + /** + * 获取文件后缀名 + * @param file + * @return + */ + public static String getFileExtension(File file) { + String name = file.getName(); + int lastIndexOfDot = name.lastIndexOf("."); + if (lastIndexOfDot != -1 && lastIndexOfDot < name.length() - 1) { + return name.substring(lastIndexOfDot + 1); + } else { + return ""; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java new file mode 100644 index 0000000..432dfda --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java new file mode 100644 index 0000000..f968f1a --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/SaaSAPIFileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/SaaSAPIFileUtils.java new file mode 100644 index 0000000..9017df7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/SaaSAPIFileUtils.java @@ -0,0 +1,138 @@ +package com.ruoyi.common.utils.file; + +import cn.hutool.json.JSONObject; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.ruoyi.common.config.EsignDemoConfig; +import com.ruoyi.common.constant.EsignHeaderConstant; +import com.ruoyi.common.constant.FileTransformation; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.enums.EsignRequestType; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.utils.EsignHttpHelper; +import com.ruoyi.common.utils.bean.EsignFileBean; +import com.ruoyi.common.utils.uuid.IdUtils; + +import java.time.LocalDate; +import java.util.Map; + +public class SaaSAPIFileUtils { + private static String eSignHost= EsignDemoConfig.EsignHost; + private static String eSignAppId= EsignDemoConfig.EsignAppId; + private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret; + /** + * 获取文件上传地址 + */ + public static EsignHttpResponse getUploadUrl(String filePath) throws EsignDemoException { + //自定义的文件封装类,传入文件地址可以获取文件的名称大小,文件流等数据 + EsignFileBean esignFileBean = new EsignFileBean(filePath); + String apiaddr = "/v3/files/file-upload-url"; + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm = "{\n" + + " \"contentMd5\": \"" + esignFileBean.getFileContentMD5() + "\",\n" + + " \"fileName\":\"" + esignFileBean.getFileName() + "\"," + + " \"fileSize\": " + esignFileBean.getFileSize() + ",\n" + + " \"convertToPDF\":" +true+ ",\n" + + " \"contentType\": \"" + EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE() + "\"\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true); + } + /** + * 上传文件流 + */ + public static EsignHttpResponse uploadFile(String uploadUrl,String filePath) throws EsignDemoException { + //根据文件地址获取文件contentMd5 + EsignFileBean esignFileBean = new EsignFileBean(filePath); + //请求方法 + EsignRequestType requestType= EsignRequestType.PUT; + return EsignHttpHelper.doUploadHttp(uploadUrl,requestType,esignFileBean.getFileBytes(),esignFileBean.getFileContentMD5(), EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE(),true); + } + + /** + * 获取文件上传状态 + */ + public static EsignHttpResponse getFileStatus(String fileId) throws EsignDemoException { + String apiaddr="/v3/files/"+fileId; + + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm=null; + //请求方法 + EsignRequestType requestType= EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true); + } + + /** + * 下载已签署文件及附属材料 + */ + public static EsignHttpResponse fileDownloadUrl(String signFlowId) throws EsignDemoException { + String apiaddr = "/v3/sign-flow/"+ signFlowId +"/file-download-url"; + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm=null; + //请求方法 + EsignRequestType requestType= EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,false); + } + + + + public static void main(String[] args) throws EsignDemoException { + String filePath = "D:\\home\\ruoyi\\uploadPath\\upload\\2023\\10\\7\\23893bfd3f2249ffa5c82850c11c482e.docx"; + EsignHttpResponse uploadUrl = getUploadUrl(filePath); + String body = uploadUrl.getBody(); + JSONObject jsonObject = new JSONObject(body); + JSONObject dataObj = jsonObject.getJSONObject("data"); + String fileUploadUrl = dataObj.get("fileUploadUrl").toString(); + System.out.println("这是fileUploadUrl:"+fileUploadUrl); + String fileId = dataObj.get("fileId").toString(); + System.out.println("这是fileId:"+fileId); + //String fileUploadUrl = "https://esignoss.esign.cn/1111564182/ccf6db5a-92da-4523-89ba-385a30423596/23893bfd3f2249ffa5c82850c11c482e.docx?Expires=1697021257&OSSAccessKeyId=STS.NTmgvSC8n5Zg1y7EciQftF23N&Signature=CxVZmpwFksWmLYkxPjVz9K4mVyA%3D&callback-var=eyJ4OmZpbGVfa2V5IjoiJDAyODhjOTg3LWNlNzgtNDM1OC04NWYwLTdlNmUyM2NjOTJmNiQzNDk1NzQ3MjE5In0%3D%0A&callback=eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9zbWx0YXBpLnRzaWduLmNuL2FueWRvb3IvZmlsZS1zeXN0ZW0vY2FsbGJhY2svYWxpb3NzIiwiY2FsbGJhY2tCb2R5IjogIntcIm1pbWVUeXBlXCI6JHttaW1lVHlwZX0sXCJzaXplXCI6ICR7c2l6ZX0sXCJidWNrZXRcIjogJHtidWNrZXR9LFwib2JqZWN0XCI6ICR7b2JqZWN0fSxcImV0YWdcIjogJHtldGFnfSxcImZpbGVfa2V5XCI6JHt4OmZpbGVfa2V5fX0iLCJjYWxsYmFja0JvZHlUeXBlIjogImFwcGxpY2F0aW9uL2pzb24ifQ%3D%3D%0A&security-token=CAIS%2BAF1q6Ft5B2yfSjIr5fYLMznrudPgpiMM1%2BGoWM8XelYqfeYrDz2IHtKdXRvBu8Xs%2F4wnmxX7f4YlqB6T55OSAmcNZEofT7katr4MeT7oMWQweEurv%2FMQBqyaXPS2MvVfJ%2BOLrf0ceusbFbpjzJ6xaCAGxypQ12iN%2B%2Fm6%2FNgdc9FHHPPD1x8CcxROxFppeIDKHLVLozNCBPxhXfKB0ca0WgVy0EHsPnvm5DNs0uH1AKjkbRM9r6ceMb0M5NeW75kSMqw0eBMca7M7TVd8RAi9t0t1%2FIVpGiY4YDAWQYLv0rda7DOltFiMkpla7MmXqlft%2BhzcgeQY0pc%2FRqAAaxcPCSY0Du8wgErfR1llD8t2zeFG%2B1mktU4Rsl7AgxsSFxrwILBUk2x7imVsFVA0kkS8rNBMDKGIsIZTCl5M7S2L%2BD8364htwcZgIZYHK2fCN6gCuy%2Bfk9C%2FfQaTc00IWBMw8OubuJ%2Fq2mdMh32yoi7dLuJyhwt1z%2F%2BWf5vIFHdIAA%3D"; + EsignHttpResponse esignHttpResponse = uploadFile(fileUploadUrl, filePath); + System.out.println("这是上传文件流的结果:"+esignHttpResponse.getBody()); +// EsignHttpResponse fileStatus = getFileStatus(fileId); +// System.out.println("这是获取文件上传状态的结果:"+fileStatus.getBody()); +// getFileStatus("a808f1f39a744357a2f018e4ab34c55d"); +// fileDownloadUrl(""); + + +// Gson gson = new Gson(); +// EsignHttpResponse fileDownload = fileDownloadUrl(signFlowId); +// JsonObject fileDownloadJsonObject = gson.fromJson(fileDownload.getBody(),JsonObject.class); +// JsonObject fileDownloadData = fileDownloadJsonObject.getAsJsonObject("data"); +// JsonArray filesArray = fileDownloadData.get("files").getAsJsonArray(); +// if(filesArray!=null&&filesArray.size()>0){ +// JsonObject fileObject = (JsonObject)filesArray.get(0); +// String fileDownloadUrl = fileObject.get("downloadUrl").toString(); +// String fileName = java.util.UUID.randomUUID().toString().replace("-", "") + ".pdf"; +// String savePath = "/home/ruoyi/uploadPath/upload"; +// LocalDate now = LocalDate.now(); +// String year = Integer.toString(now.getYear()); +// String month = String.format("%02d", now.getMonthValue()); +// String day = String.format("%02d", now.getDayOfMonth()); +// String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; +// String fileDownloadUrlnew = fileDownloadUrl.substring(1,fileDownloadUrl.length()-1); +// FileTransformation.downLoadFileByUrl(fileDownloadUrlnew,dir); +// } + + + + + + + } + + + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java new file mode 100644 index 0000000..f52e83e --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java new file mode 100644 index 0000000..ebff3fd --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java new file mode 100644 index 0000000..589d123 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java new file mode 100644 index 0000000..f85c82c --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java new file mode 100644 index 0000000..edfe419 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java new file mode 100644 index 0000000..8e89e30 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java new file mode 100644 index 0000000..ccab288 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.utils.poi; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Excel数据格式处理适配器 + * + * @author ruoyi + */ +public interface ExcelHandlerAdapter +{ + /** + * 格式化 + * + * @param value 单元格数据值 + * @param args excel注解args参数组 + * @param cell 单元格对象 + * @param wb 工作簿对象 + * + * @return 处理后的值 + */ + Object format(Object value, String[] args, Cell cell, Workbook wb); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java new file mode 100644 index 0000000..6f45d5b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -0,0 +1,1758 @@ +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.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) + { + List list = null; + try + { + list = importExcel(is, 0); + } + catch (Exception e) + { + log.error("导入Excel异常{}", e.getMessage()); + throw new UtilException(e.getMessage()); + } + finally + { + IOUtils.closeQuietly(is); + } + return list; + } + + /** + * 对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.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(); + } + 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, null); + } + 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, cell)); + } + 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, Cell cell) + { + try + { + Object instance = excel.handler().newInstance(); + Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class }); + value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb); + } + 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/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java new file mode 100644 index 0000000..b19953e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java @@ -0,0 +1,410 @@ +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.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())) + && !method.isAccessible()) + { + 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())) && !field.isAccessible()) + { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得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/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java new file mode 100644 index 0000000..ca1cd92 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java new file mode 100644 index 0000000..c1c58db --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java new file mode 100644 index 0000000..f290ec3 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java new file mode 100644 index 0000000..93b0347 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java @@ -0,0 +1,70 @@ +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_\\ \\,\\.]+"; + + /** + * 限制orderBy最大长度 + */ + private static final int ORDER_BY_MAX_LENGTH = 500; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new UtilException("参数不符合规范,不能进行查询"); + } + if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH) + { + 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/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadListParam.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadListParam.java new file mode 100644 index 0000000..71c0882 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadListParam.java @@ -0,0 +1,22 @@ +package com.ruoyi.common.utils.thread; + +import lombok.Data; + +import java.util.List; +import java.util.function.Function; + +/** + * @author wangqiong + * @date 2023/11/25 9:25 + **/ +@Data +public class MultipleThreadListParam { + /**需要执行的方法*/ + private Function,R> function; + /**参数ID*/ + private List list; + public MultipleThreadListParam(Function,R> function, List list){ + this.function=function; + this.list=list; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadStringParam.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadStringParam.java new file mode 100644 index 0000000..32fa680 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadStringParam.java @@ -0,0 +1,21 @@ +package com.ruoyi.common.utils.thread; + +import lombok.Data; + +import java.util.function.Function; + +/** + * @author wangqiong + * @date 2023/11/25 9:25 + **/ +@Data +public class MultipleThreadStringParam { + /**需要执行的方法*/ + private Function function; + /**参数ID*/ + private String ids; + public MultipleThreadStringParam(Function function, String ids){ + this.function=function; + this.ids=ids; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadWorkUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadWorkUtil.java new file mode 100644 index 0000000..cfb5d2e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/MultipleThreadWorkUtil.java @@ -0,0 +1,592 @@ +package com.ruoyi.common.utils.thread; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.annotation.VoidFunction; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.ServiceException; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Function; + +/** + * @description 多线程操作数据库,一个线程异常全部回滚 + * @Author wangqiong + * @Date 2023/11/25 14:02 + * @Version V1.0 + **/ +@Slf4j +public class MultipleThreadWorkUtil { + private static int SIMPLE_TIME_COUNT=1000; + + public static List exec(Function,R> execFun, List list){ + List returnList=new ArrayList<>(); + if(CollectionUtil.isEmpty(list)){ + return returnList; + } + if(list.size()0){ + times++; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List> futureList=new ArrayList<>(); + for (int i = 0; i future=executorService.submit(new ExecThread(mainLatch,threadLatch,rollBack,resultList,list.subList(i*SIMPLE_TIME_COUNT,i*SIMPLE_TIME_COUNT+SIMPLE_TIME_COUNT),execFun)); + futureList.add(future); + }else{ + Future future=executorService.submit(new ExecThread(mainLatch,threadLatch,rollBack,resultList,list.subList(i*SIMPLE_TIME_COUNT,list.size()),execFun)); + futureList.add(future); + } + } + setResult(executorService,returnList,futureList,resultList, + mainLatch,threadLatch,rollBack,times); + return returnList; + } + + public static void exec(VoidFunction> execFun, Set set){ + if(set.size()0){ + times++; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List list=new ArrayList<>(set); + List futureList=new ArrayList<>(); + for (int i = 0; i backUpResult=new ArrayList<>(); + try{ + // + boolean await=threadLatch.await(times*3,TimeUnit.SECONDS); + if(!await){ + rollBack.setRollBack(true); + }else{ + //查看执行情况,如果有存在需要回滚的线程,则全部回滚 + for (int i = 0; i List execFun(MultipleThreadStringParam...params){ + List returnList=new ArrayList<>(); + if(ArrayUtil.isEmpty(params)){ + return returnList; + } + List threadCountList=new ArrayList<>(); + for (MultipleThreadStringParam param : params) { + List idList= Arrays.asList(param.getIds().split(Constants.SPLIT_COMMA)); + if(idList.size()0){ + threadCountList.add(idList.size()/SIMPLE_TIME_COUNT+1); + }else{ + threadCountList.add(idList.size()/SIMPLE_TIME_COUNT); + } + } + } + int times=0; + for (Integer count : threadCountList) { + times+=count; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List> futureList=new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + MultipleThreadStringParam param=params[i]; + List idList= Arrays.asList(param.getIds().split(Constants.SPLIT_COMMA)); + for (int j = 0; j future=executorService.submit(new ExecByIdsStringThread<>(mainLatch,threadLatch,rollBack,resultList,StrUtil.join(Constants.SPLIT_COMMA,idList.subList(j*SIMPLE_TIME_COUNT,j*SIMPLE_TIME_COUNT+SIMPLE_TIME_COUNT)),param.getFunction())); + futureList.add(future); + }else{ + Future future=executorService.submit(new ExecByIdsStringThread(mainLatch,threadLatch,rollBack,resultList,StrUtil.join(Constants.SPLIT_COMMA,idList.subList(j*SIMPLE_TIME_COUNT,idList.size())),param.getFunction())); + futureList.add(future); + } + } + } + setResult(executorService,returnList,futureList,resultList, + mainLatch,threadLatch,rollBack,times); + return returnList; + } + public static List execListFun(MultipleThreadListParam ...params){ + List returnList=new ArrayList<>(); + if(ArrayUtil.isEmpty(params)){ + return returnList; + } + List threadCountList=new ArrayList<>(); + for (MultipleThreadListParam param : params) { + if(param.getList().size()0){ + threadCountList.add(param.getList().size()/SIMPLE_TIME_COUNT+1); + }else{ + threadCountList.add(param.getList().size()/SIMPLE_TIME_COUNT); + } + } + } + int times=0; + for (Integer count : threadCountList) { + times+=count; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List> futureList=new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + MultipleThreadListParam param=params[i]; + for (int j = 0; j future=executorService.submit(new ExecThread(mainLatch,threadLatch,rollBack,resultList,param.getList().subList(j*SIMPLE_TIME_COUNT,j*SIMPLE_TIME_COUNT+SIMPLE_TIME_COUNT),param.getFunction())); + futureList.add(future); + }else{ + Future future=executorService.submit(new ExecThread(mainLatch,threadLatch,rollBack,resultList,param.getList().subList(j*SIMPLE_TIME_COUNT,param.getList().size()),param.getFunction())); + futureList.add(future); + } + } + } + setResult(executorService,returnList,futureList,resultList, + mainLatch,threadLatch,rollBack,times); + return returnList; + } + public static List execByIds(Function execFun,String ids){ + List returnList=new ArrayList<>(); + if(StrUtil.isEmpty(ids)){ + return returnList; + } + List idList= Arrays.asList(ids.split(Constants.SPLIT_COMMA)); + if(idList.size()0){ + times++; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List> futureList=new ArrayList<>(); + for (int i = 0; i future=executorService.submit(new ExecByIdsStringThread<>(mainLatch,threadLatch,rollBack,resultList,StrUtil.join(Constants.SPLIT_COMMA,idList.subList(i*SIMPLE_TIME_COUNT,i*SIMPLE_TIME_COUNT+SIMPLE_TIME_COUNT)),execFun)); + futureList.add(future); + }else{ + Future future=executorService.submit(new ExecByIdsStringThread(mainLatch,threadLatch,rollBack,resultList,StrUtil.join(Constants.SPLIT_COMMA,idList.subList(i*SIMPLE_TIME_COUNT,idList.size())),execFun)); + futureList.add(future); + } + } + setResult(executorService,returnList,futureList,resultList, + mainLatch,threadLatch,rollBack,times); + return returnList; + } + + public static List execByIds(Function,List> execFun,List idList){ + List returnList=new ArrayList<>(); + if(CollectionUtil.isEmpty(idList)){ + return returnList; + } + if(idList.size()0){ + times++; + } + CountDownLatch mainLatch=new CountDownLatch(1); + //监控子线程 + CountDownLatch threadLatch=new CountDownLatch(times); + //根据子线程执行结果判断是否需要回滚 + BlockingDeque resultList=new LinkedBlockingDeque<>(); + //必须使用对象,如果使用变量会造成线程之间不能共享变量值 + RollBack rollBack=new RollBack(false); + ExecutorService executorService=Executors.newFixedThreadPool(times); + List>> futureList=new ArrayList<>(); + for (int i = 0; i > future=executorService.submit(new ExecByIdsStringListThread<>(mainLatch,threadLatch,rollBack,resultList,idList.subList(i*SIMPLE_TIME_COUNT,i*SIMPLE_TIME_COUNT+SIMPLE_TIME_COUNT),execFun)); + futureList.add(future); + }else{ + Future> future=executorService.submit(new ExecByIdsStringListThread(mainLatch,threadLatch,rollBack,resultList,idList.subList(i*SIMPLE_TIME_COUNT,idList.size()),execFun)); + futureList.add(future); + } + } + /**存放子线程返回结果*/ + List backUpResult=new ArrayList<>(); + try{ + // + boolean await=threadLatch.await(times*3,TimeUnit.SECONDS); + if(!await){ + rollBack.setRollBack(true); + }else{ + //查看执行情况,如果有存在需要回滚的线程,则全部回滚 + for (int i = 0; i > future : futureList) { + try { + returnList.addAll(future.get()); + } catch (Exception e) { + throw new ServiceException("多线程执行异常"); + } + } + return returnList; + } + + private static void setResult(ExecutorService executorService,List returnList,List> futureList,BlockingDeque resultList + ,CountDownLatch mainLatch,CountDownLatch threadLatch,RollBack rollBack,int times){ + /**存放子线程返回结果*/ + List backUpResult=new ArrayList<>(); + try{ + // + boolean await=threadLatch.await(times*3,TimeUnit.SECONDS); + if(!await){ + rollBack.setRollBack(true); + }else{ + //查看执行情况,如果有存在需要回滚的线程,则全部回滚 + for (int i = 0; i future : futureList) { + try { + returnList.add(future.get()); + } catch (Exception e) { + throw new ServiceException("多线程执行异常"); + } + } + } + + static class QueryThread implements Callable>{ + private String ids; + private Function> execFun; + public QueryThread(String ids,Function> execFun){ + this.ids=ids; + this.execFun=execFun; + } + @Override + public List call(){ + return execFun.apply(ids); + } + } + + static class ExecThread implements Callable{ + /**主线程监控*/ + private CountDownLatch mainLatch; + /**子线程监控*/ + private CountDownLatch threadLatch; + /**是否回滚*/ + private RollBack rollBack; + private BlockingDeque resultList; + private List list; + private Function,R> execFun; + public ExecThread(CountDownLatch mainLatch,CountDownLatch threadLatch,RollBack rollBack,BlockingDeque resultList,List list,Function,R> execFun){ + this.mainLatch=mainLatch; + this.threadLatch=threadLatch; + this.rollBack=rollBack; + this.resultList=resultList; + this.list=list; + this.execFun=execFun; + } + @Override + @Transactional(rollbackFor = Exception.class) + public R call(){ + // 是否回滚 + Boolean result=false; + R r=null; + try{ + // 对数据库进行操作 + r=execFun.apply(list); + }catch (Exception e){ + e.printStackTrace(); + result=true; + } + resultList.add(result); + // 子线程-1,切换到主线程执行 + threadLatch.countDown(); + try{ + // 等待主线程执行 + mainLatch.await(); + }catch (InterruptedException e){ + throw new ServiceException("多线程执行异常"); + } + if(rollBack.getRollBack()){ + throw new ServiceException("多线程执行异常"); + } + return r; + } + } + + static class VoidExecThread implements Runnable{ + /**主线程监控*/ + private CountDownLatch mainLatch; + /**子线程监控*/ + private CountDownLatch threadLatch; + /**是否回滚*/ + private RollBack rollBack; + private BlockingDeque resultList; + private List list; + private VoidFunction> execFun; + public VoidExecThread(CountDownLatch mainLatch,CountDownLatch threadLatch,RollBack rollBack,BlockingDeque resultList,List list,VoidFunction> execFun){ + this.mainLatch=mainLatch; + this.threadLatch=threadLatch; + this.rollBack=rollBack; + this.resultList=resultList; + this.list=list; + this.execFun=execFun; + } + @Override + public void run() { + Boolean result=false; + try{ + execFun.apply(new HashSet<>(list)); + }catch (Exception e){ + e.printStackTrace(); + result=true; + } + resultList.add(result); + threadLatch.countDown(); + try{ + mainLatch.await(); + }catch (InterruptedException e){ + throw new ServiceException("多线程执行异常"); + } + if(rollBack.getRollBack()){ + throw new ServiceException("多线程执行异常"); + } + } + } + + + static class ExecByIdsStringThread implements Callable{ + /**主线程监控*/ + private CountDownLatch mainLatch; + /**子线程监控*/ + private CountDownLatch threadLatch; + /**是否回滚*/ + private RollBack rollBack; + private BlockingDeque resultList; + private String ids; + private Function execFun; + public ExecByIdsStringThread(CountDownLatch mainLatch,CountDownLatch threadLatch,RollBack rollBack,BlockingDeque resultList,String ids,Function execFun){ + this.mainLatch=mainLatch; + this.threadLatch=threadLatch; + this.rollBack=rollBack; + this.resultList=resultList; + this.ids=ids; + this.execFun=execFun; + } + @Override + public R call(){ + Boolean result=false; + R r=null; + try{ + r=execFun.apply(ids); + }catch (Exception e){ + e.printStackTrace(); + result=true; + } + resultList.add(result); + threadLatch.countDown(); + try{ + mainLatch.await(); + }catch (InterruptedException e){ + throw new ServiceException("多线程执行异常"); + } + if(rollBack.getRollBack()){ + throw new ServiceException("多线程执行异常"); + } + return r; + } + } + + + + + static class ExecByIdsStringListThread implements Callable{ + /**主线程监控*/ + private CountDownLatch mainLatch; + /**子线程监控*/ + private CountDownLatch threadLatch; + /**是否回滚*/ + private RollBack rollBack; + private BlockingDeque resultList; + private List ids; + private Function,R> execFun; + public ExecByIdsStringListThread(CountDownLatch mainLatch,CountDownLatch threadLatch,RollBack rollBack,BlockingDeque resultList,List ids,Function,R> execFun){ + this.mainLatch=mainLatch; + this.threadLatch=threadLatch; + this.rollBack=rollBack; + this.resultList=resultList; + this.ids=ids; + this.execFun=execFun; + } + @Override + public R call(){ + Boolean result=false; + R r=null; + try{ + r=execFun.apply(ids); + }catch (Exception e){ + e.printStackTrace(); + result=true; + } + resultList.add(result); + threadLatch.countDown(); + try{ + mainLatch.await(); + }catch (InterruptedException e){ + throw new ServiceException("多线程执行异常"); + } + if(rollBack.getRollBack()){ + throw new ServiceException("多线程执行异常"); + } + return r; + } + } + + @Data + static class RollBack{ + private Boolean rollBack; + public RollBack(Boolean rollBack){ + this.rollBack=rollBack; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/ThreadPoolUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/ThreadPoolUtil.java new file mode 100644 index 0000000..c91b31c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/thread/ThreadPoolUtil.java @@ -0,0 +1,112 @@ +package com.ruoyi.common.utils.thread; + +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/** + * @description 线程池工具类 + * @Author wangqiong + * @Date 2023/11/7 15:41 + * @Version V1.0 + **/ +@Slf4j +public class ThreadPoolUtil { + /** cpu核心数 */ + private static int corePoolSize = (Runtime.getRuntime().availableProcessors()); + /**创建固定大小线程池*/ + private static ExecutorService executors = new ThreadPoolExecutor( + corePoolSize, + corePoolSize, + 0L, + TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>()); + + /** + * 异步任务 + * @param task + */ + public static void execute(Runnable task){ + executors.execute(task); + } + + /** + * 可获取返回结果的任务且可设置超时时间 + * @param task + * @param timeout + * @param + * @return + */ + public static T execute(Callable task, long timeout){ + Future future = executors.submit(task); + T result = null; + try { + result = future.get(timeout, TimeUnit.SECONDS); + } catch (InterruptedException e) { + future.cancel(true); + log.error("ThreadPoolUtil.InterruptedException. e:{}", e); + } catch (ExecutionException e) { + future.cancel(true); + log.error("ThreadPoolUtil.ExecutionException. e:{}", e); + } catch (TimeoutException e) { + future.cancel(true); + log.error("ThreadPoolUtil.TimeoutException. e:{}", e); + } + return result; + } + + /** + * 可获取返回结果的任务 + * @param task + * @return + */ + public static Future submit(Callable task){ + return executors.submit(task); + } + + /** + * 可获取返回结果的任务 + * @param tasks + * @param + * @return + */ + public static List submit(Callable... tasks){ + List> list=new ArrayList<>(); + List resultList=new ArrayList<>(); + if(tasks==null||tasks.length==0){ + return resultList; + } + for(Callable task:tasks){ + list.add(executors.submit(task)); + } + for(Future future:list){ + try { + resultList.add(future.get()); + } catch (InterruptedException e) { + future.cancel(true); + log.error("ThreadPoolUtil.InterruptedException. e:{}", e); + } catch (ExecutionException e) { + future.cancel(true); + log.error("ThreadPoolUtil.ExecutionException. e:{}", e); + } + } + return resultList; + } + + /** + * 执行完所有返回 + * @param tasks + */ + public static void submit(Runnable ...tasks){ + if(tasks==null||tasks.length==0){ + return; + } + List futureList=new ArrayList<>(); + for (Runnable task : tasks) { + futureList.add(CompletableFuture.runAsync(task,executors)); + } + CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java new file mode 100644 index 0000000..2c84427 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java new file mode 100644 index 0000000..bf99611 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java new file mode 100644 index 0000000..a5585d6 --- /dev/null +++ b/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} 的布局。 + *

+ * 变体号具有以下含意: + *

+ * + * @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/ruoyi-common/src/main/java/com/ruoyi/common/websocket/MyWebSocketHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/websocket/MyWebSocketHandler.java new file mode 100644 index 0000000..4da9fcb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/websocket/MyWebSocketHandler.java @@ -0,0 +1,140 @@ +package com.ruoyi.common.websocket; + + +import com.ruoyi.common.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * @author wangqiong + * @description + * @date 2023-11-25 15:16 + */ +@Component +@Slf4j +@ServerEndpoint("/websocket/{userName}") +public class MyWebSocketHandler { + // 接口路径 ws://127.0.0.1:9000/websocket; + private Session session; + + //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。 + private static CopyOnWriteArraySet sessions = new CopyOnWriteArraySet<>(); + // 用来存在线连接数 + private static Map sessionPool = new HashMap<>(); + + /** + * 链接成功调用的方法 + */ + @OnOpen + public void onOpen(Session session, @PathParam(value = "userName") String userName) { + try { + sessions.add(session); + sessionPool.put(userName, session); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 链接关闭调用的方法 + */ + @OnClose + public void onClose(Session session,@PathParam(value = "userName") String userName) { + try { + if(session!=null && session.isOpen()){ + session.close(); + sessions.remove(session); + sessionPool.remove(userName); + } + + log.info("【websocket消息】连接断开,总数为:" + sessions.size()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 收到客户端消息后调用的方法 + * + * @param message + * @param + */ + @OnMessage + public void onMessage(@PathParam(value = "userName") String userName, String message) { + + System.out.println("【websocket消息】收到客户端消息:" + message); + // 将消息广播给其它用户 + for (Session session : sessions) { + if(session!=null && session.isOpen()){ + try { + session.getBasicRemote().sendText(message); + }catch (Exception e){ + throw new ServiceException(e.getMessage()); + } + }else { + try { + session.close(); + } catch (IOException e) { + throw new ServiceException(e.getMessage()); + } + sessions.remove(session); + sessionPool.remove(userName); + } + } + + } + + /** + * 发送错误时的处理 + * + * @param session + * @param error + */ + @OnError + public void onError(Session session, Throwable error) { + + throw new ServiceException(error.getMessage()); + } + + + /** + * 推消息给前端 + * + * @param userId + * @param message + * @return + */ + public static Runnable sendOneMessage(String userId, String message) { + Session session = sessionPool.get(userId); + if (session != null && session.isOpen()) { + try { + log.info("【推给前端消息】 :" + message); + + //高并发下,防止session占用期间,被其他线程调用 + synchronized (session) { + session.getBasicRemote().sendText(message); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + + + + +} + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/websocket/WebSocketConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/websocket/WebSocketConfig.java new file mode 100644 index 0000000..1084cbd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/websocket/WebSocketConfig.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.websocket;//package com.ruoyi.common.websocket; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +/** + * @author wangqiong + * @description + * @date 2023-11-25 15:19 + */ + +@Configuration +public class WebSocketConfig { + + /** + * 注入ServerEndpointExporter, + * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint + */ + + @Bean + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java new file mode 100644 index 0000000..7bfdf04 --- /dev/null +++ b/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/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java new file mode 100644 index 0000000..ed9ec1f --- /dev/null +++ b/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/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml new file mode 100644 index 0000000..3b70537 --- /dev/null +++ b/ruoyi-framework/pom.xml @@ -0,0 +1,64 @@ + + + + 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 + + + + + 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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java new file mode 100644 index 0000000..1bc2f69 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java new file mode 100644 index 0000000..8c2c9f4 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java new file mode 100644 index 0000000..5980eb7 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java new file mode 100644 index 0000000..b720bc1 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java new file mode 100644 index 0000000..46ab4b2 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -0,0 +1,31 @@ +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") +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { +// return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone("Asia/Shanghai"); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java new file mode 100644 index 0000000..43e78ae --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java new file mode 100644 index 0000000..f6abac1 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..4adbb7f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,52 @@ +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; +import com.alibaba.fastjson2.filter.Filter; +import com.ruoyi.common.constant.Constants; + +/** + * Redis使用FastJson序列化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR); + + 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, AUTO_TYPE_FILTER); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java new file mode 100644 index 0000000..bb14c04 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java new file mode 100644 index 0000000..7f8e1d5 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java new file mode 100644 index 0000000..057c941 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java new file mode 100644 index 0000000..3f4f485 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java new file mode 100644 index 0000000..74fb93e --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java new file mode 100644 index 0000000..aa522ae --- /dev/null +++ b/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","/uploadPath/**","/websocket/**").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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java new file mode 100644 index 0000000..b5b7de3 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java new file mode 100644 index 0000000..7840141 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java new file mode 100644 index 0000000..c8a5c8a --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java new file mode 100644 index 0000000..29118fa --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java new file mode 100644 index 0000000..e70b8cf --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..9770af6 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..c49eaf4 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,56 @@ +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 请求信息 + * @param annotation 防重复注解参数 + * @return 结果 + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java new file mode 100644 index 0000000..9dc9511 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java new file mode 100644 index 0000000..7387a02 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java new file mode 100644 index 0000000..e36ca3c --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java new file mode 100644 index 0000000..267e305 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java new file mode 100644 index 0000000..6c776ce --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java new file mode 100644 index 0000000..5472f3d --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..3eb2495 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..93b7032 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..c01f691 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java new file mode 100644 index 0000000..63b03da --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java new file mode 100644 index 0000000..a13a66c --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java new file mode 100644 index 0000000..1fdc6ac --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java new file mode 100644 index 0000000..13eec52 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java new file mode 100644 index 0000000..45d64d9 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java new file mode 100644 index 0000000..1320cde --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..a3ec182 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,138 @@ +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.MissingPathVariableException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +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(MissingPathVariableException.class) + public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName())); + } + + /** + * 请求参数类型不匹配 + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue())); + } + + /** + * 拦截未知的运行时异常 + */ + @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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java new file mode 100644 index 0000000..249c6a0 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java new file mode 100644 index 0000000..67267b7 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java new file mode 100644 index 0000000..6ad91b0 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java new file mode 100644 index 0000000..d1fb4ed --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java new file mode 100644 index 0000000..f2afe31 --- /dev/null +++ b/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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java new file mode 100644 index 0000000..aa112da --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -0,0 +1,231 @@ +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 +{ + private static final Logger log = LoggerFactory.getLogger(TokenService.class); + + // 令牌自定义标识 + @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) + { + log.error("获取用户信息异常'{}'", e.getMessage()); + } + } + 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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..5dcdf90 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java @@ -0,0 +1,66 @@ +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.MessageUtils; +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(MessageUtils.message("user.not.exists")); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new ServiceException(MessageUtils.message("user.password.delete")); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new ServiceException(MessageUtils.message("user.blocked")); + } + + 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/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml new file mode 100644 index 0000000..1180284 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java new file mode 100644 index 0000000..cc4cd14 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java new file mode 100644 index 0000000..2aed686 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java new file mode 100644 index 0000000..269779c --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java new file mode 100644 index 0000000..d1733b6 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java new file mode 100644 index 0000000..951e166 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java new file mode 100644 index 0000000..9b330df --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java new file mode 100644 index 0000000..0679689 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java new file mode 100644 index 0000000..4889f81 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java new file mode 100644 index 0000000..3037f70 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java new file mode 100644 index 0000000..9d53f95 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java new file mode 100644 index 0000000..e7ebc20 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java new file mode 100644 index 0000000..9f69403 --- /dev/null +++ b/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/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java new file mode 100644 index 0000000..7ede02d --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml new file mode 100644 index 0000000..7eae68e --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml new file mode 100644 index 0000000..66109de --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml new file mode 100644 index 0000000..b605e90 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm new file mode 100644 index 0000000..bf88988 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm new file mode 100644 index 0000000..bd51c17 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm new file mode 100644 index 0000000..7e7d7c2 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm new file mode 100644 index 0000000..264882b --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm new file mode 100644 index 0000000..14746e1 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm new file mode 100644 index 0000000..a3f53eb --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/js/api.js.vm b/ruoyi-generator/src/main/resources/vm/js/api.js.vm new file mode 100644 index 0000000..9295524 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-generator/src/main/resources/vm/sql/sql.vm new file mode 100644 index 0000000..0575583 --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm new file mode 100644 index 0000000..4819c2a --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -0,0 +1,505 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm new file mode 100644 index 0000000..6296014 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -0,0 +1,602 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm new file mode 100644 index 0000000..c54d62b --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -0,0 +1,474 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm new file mode 100644 index 0000000..8b25665 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm @@ -0,0 +1,590 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt new file mode 100644 index 0000000..99239bb --- /dev/null +++ b/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/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm new file mode 100644 index 0000000..0ceb3d8 --- /dev/null +++ b/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/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml new file mode 100644 index 0000000..43dcb2f --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java new file mode 100644 index 0000000..a558170 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java new file mode 100644 index 0000000..139361b --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java new file mode 100644 index 0000000..62ecbab --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java new file mode 100644 index 0000000..1f49695 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java new file mode 100644 index 0000000..121c035 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java new file mode 100644 index 0000000..727d916 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java new file mode 100644 index 0000000..20f45db --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java new file mode 100644 index 0000000..8546792 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java new file mode 100644 index 0000000..437ade8 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java new file mode 100644 index 0000000..812eed7 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java new file mode 100644 index 0000000..77fdbb5 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java new file mode 100644 index 0000000..853243b --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java new file mode 100644 index 0000000..731a5eb --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java new file mode 100644 index 0000000..dd53839 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java new file mode 100644 index 0000000..e3dc62c --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java new file mode 100644 index 0000000..5e13558 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java new file mode 100644 index 0000000..e975326 --- /dev/null +++ b/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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java new file mode 100644 index 0000000..21fedae --- /dev/null +++ b/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/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml new file mode 100644 index 0000000..e608e42 --- /dev/null +++ b/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} + + + + + truncate table 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/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml new file mode 100644 index 0000000..5605c44 --- /dev/null +++ b/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/ruoyi-system/pom.xml b/ruoyi-system/pom.xml new file mode 100644 index 0000000..971c071 --- /dev/null +++ b/ruoyi-system/pom.xml @@ -0,0 +1,39 @@ + + + + ruoyi + com.ruoyi + 3.8.6 + + 4.0.0 + + ruoyi-system + + + system系统模块 + + + + + + + com.ruoyi + ruoyi-common + + + + com.ruoyi + pay + 1.0.0-SNAPSHOT + + + com.github.tencentyun + tls-sig-api-v2 + 1.2 + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/ArbitrSignatuVO.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/ArbitrSignatuVO.java new file mode 100644 index 0000000..6210f34 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/ArbitrSignatuVO.java @@ -0,0 +1,51 @@ +package com.ruoyi.bestsign.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ArbitrSignatuVO { + /** + * 用户帐号 + * 任务id + * 文件MD5 + * 文件内容 + * 文件总页数 + * 文件名称 + * 文件类型 + * 合同标题 + * 有效期 + * 合同编号 + * 签署者账号 + * 签名位置页码 + * x坐标 + * y坐标 + */ + private String account; + private String taskId; + + private String fileMd5; + private String fileData; + private String filePages; + private String fileName; + private String fileType; + private String contractTitle; + private String periodValidity; + + private String contractNum; + private String signerAccout; + private String pageNumSigner; + private String pageNumSignerX; + private String pageNumSignerY; + + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/CredentialVO.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/CredentialVO.java new file mode 100644 index 0000000..c9fba91 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/CredentialVO.java @@ -0,0 +1,22 @@ +package com.ruoyi.bestsign.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class CredentialVO { + /** + * 用户证件号 + */ + private String identity; + /** + * 用户证件类型 + * 默认用“0”, "0"表示身份证,会校验18位身份证号格式。0-居民身份证; 1-护照;6-社会保障卡; B-港澳居民往来内地通行证; C-台湾居民来往大陆通行证; E-户口簿; F-临时居民身份证;P-外国人永久居留证;Z-其他证件 + */ + private String identityType; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/PersonRegisterVO.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/PersonRegisterVO.java new file mode 100644 index 0000000..159bcd4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/domain/PersonRegisterVO.java @@ -0,0 +1,29 @@ +package com.ruoyi.bestsign.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PersonRegisterVO { + /** + * 用户帐号 + * 用户名称 + * 用户类型 + * 用户邮箱 + * 用户手机号 + * 用户证件信息对象 + * 是否申请证书 + */ + private String account; + private String name; + private String userType; + private String mail; + private String mobile; + private CredentialVO credential; + private String applyCert; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/ArbitrSignatuService.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/ArbitrSignatuService.java new file mode 100644 index 0000000..d15b083 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/ArbitrSignatuService.java @@ -0,0 +1,12 @@ +package com.ruoyi.bestsign.service; + +import com.ruoyi.bestsign.domain.ArbitrSignatuVO; +import com.ruoyi.common.core.domain.AjaxResult; + +public interface ArbitrSignatuService { + + + AjaxResult selectApplyStatus(ArbitrSignatuVO arbitrSignatuVO); + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/SignRegisterService.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/SignRegisterService.java new file mode 100644 index 0000000..e72b247 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/SignRegisterService.java @@ -0,0 +1,18 @@ +package com.ruoyi.bestsign.service; + +import com.ruoyi.bestsign.domain.PersonRegisterVO; +import com.ruoyi.common.core.domain.AjaxResult; + +public interface SignRegisterService { + /** + * 注册上上签个人用户 + * + * @param personRegisterVO + * @return + */ + AjaxResult registerPerson(PersonRegisterVO personRegisterVO); + /** + * 查询用户认证状态/user/async/applyCert/status/ + */ + AjaxResult queryRegisterStatus(PersonRegisterVO personRegisterVO); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/ArbitrSignatuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/ArbitrSignatuServiceImpl.java new file mode 100644 index 0000000..998de51 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/ArbitrSignatuServiceImpl.java @@ -0,0 +1,29 @@ +package com.ruoyi.bestsign.service.impl; + +import com.ruoyi.bestsign.domain.ArbitrSignatuVO; +import com.ruoyi.bestsign.service.ArbitrSignatuService; +import com.ruoyi.bestsign.utils.BestsignOpenApiClient; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ArbitrSignatuServiceImpl implements ArbitrSignatuService { + @Autowired + BestsignOpenApiClient bestsignOpenApiClient; + + + @Override + public AjaxResult selectApplyStatus(ArbitrSignatuVO arbitrSignatuVO) { + String strRespon = ""; + try { + strRespon = bestsignOpenApiClient.selectApplyStatus(arbitrSignatuVO.getAccount(), + arbitrSignatuVO.getTaskId()); + } catch (Exception e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + return AjaxResult.success(strRespon); + + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/RegisterServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/RegisterServiceImpl.java new file mode 100644 index 0000000..3a731fa --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/service/impl/RegisterServiceImpl.java @@ -0,0 +1,63 @@ +package com.ruoyi.bestsign.service.impl; + + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.bestsign.domain.PersonRegisterVO; +import com.ruoyi.bestsign.service.SignRegisterService; +import com.ruoyi.bestsign.utils.BestsignOpenApiClient; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class RegisterServiceImpl implements SignRegisterService { + @Autowired + BestsignOpenApiClient bestsignOpenApiClient; + + /** + * 注册上上签个人用户 + * + * @param personRegisterVO + * @return + */ + @Override + public AjaxResult registerPerson(PersonRegisterVO personRegisterVO) { + try { + JSONObject jsonObject = bestsignOpenApiClient.userPersonalReg(personRegisterVO.getAccount(), + personRegisterVO.getName(), + personRegisterVO.getMail(), + personRegisterVO.getMobile(), + personRegisterVO.getCredential().getIdentity(), + personRegisterVO.getCredential().getIdentityType(), + null, null, null, null, null, "/user/reg/"); + AjaxResult.success(jsonObject); + } catch (Exception e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + return AjaxResult.success(); + } + + /** + * 查询用户认证状态/user/async/applyCert/status/ + * + * @param personRegisterVO + */ + @Override + public AjaxResult queryRegisterStatus(PersonRegisterVO personRegisterVO) { + try { + JSONObject jsonObject = bestsignOpenApiClient.userPersonalReg(personRegisterVO.getAccount(), + personRegisterVO.getName(), + personRegisterVO.getMail(), + personRegisterVO.getMobile(), + personRegisterVO.getCredential().getIdentity(), + personRegisterVO.getCredential().getIdentityType(), + null, null, null, null, null, "/user/async/applyCert/status/"); + AjaxResult.success(jsonObject); + } catch (Exception e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + return AjaxResult.success(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/BestsignOpenApiClient.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/BestsignOpenApiClient.java new file mode 100644 index 0000000..67594e6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/BestsignOpenApiClient.java @@ -0,0 +1,286 @@ +package com.ruoyi.bestsign.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.bestsign.domain.ArbitrSignatuVO; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.validation.constraints.NotNull; +import java.io.IOException; + +/** + * 上上签混合云SDK客户端 + */ +@Component +@Data +@Slf4j +public class BestsignOpenApiClient { + /** + * 开发者id + */ + @Value("${ssq.developerId}") + private String developerId; + /** + * 开发者私钥 + */ + @Value("${ssq.privateKey}") + private String privateKey; + /** + * Host地址 + */ + @Value("${ssq.serverHost}") + private String serverHost; + /** + * 签名参数 + */ + private static String urlSignParams = "?developerId=%s&rtick=%s&signType=rsa&sign=%s"; + +// public BestsignOpenApiClient(String developerId, String privateKey, +// String serverHost) { +// this.developerId = developerIds; +// this.privateKey = privateKey; +// this.serverHost = serverHost; +// } + + /** + * POST方法示例 + * 个人用户注册 + * + * @param account 用户账号 + * @param name 姓名 + * @param mail 用来接收通知邮件的电子邮箱 + * @param mobile 用来接收通知短信的手机号码 + * @param identity 证件号码 + * @param identityType 枚举值:0-身份证,目前仅支持身份证 + * @param contactMail 电子邮箱 + * @param contactMobile 手机号码 + * @param province 省份 + * @param city 城市 + * @param address 地址 + * @param method 地址 + * @return 异步申请任务单号 + * @throws IOException + */ + public JSONObject userPersonalReg(String account, String name, String mail, + String mobile, String identity, String identityType, + String contactMail, String contactMobile, String province, + String city, String address, @NotNull String method) throws Exception { + //body参数 + JSONObject requestBody = new JSONObject(); + + //用户帐号 + requestBody.put("account", account); + //用户名称 + requestBody.put("name", name); + //用户类型 + requestBody.put("userType", "1"); + //用户邮箱 + requestBody.put("mail", mail); + //用户手机号 + requestBody.put("mobile", mobile); + //用户证件信息对象 + JSONObject credential = new JSONObject(); + //用户证件号 + credential.put("identity", identity); + //用户证件类型 + credential.put("identityType", identityType); + requestBody.put("credential", credential); + + //是否申请证书 + requestBody.put("applyCert", "1"); + // 生成一个时间戳参数 + String rtick = RSAUtils.getRtick(); + // 计算参数签名 + String paramsSign = RSAUtils.calcRsaSign(this.developerId, + this.privateKey, this.serverHost, method, rtick, null, + requestBody.toJSONString()); + // 签名参数追加为url参数 + String fullUrlParams = String.format(urlSignParams, this.developerId, + rtick, paramsSign); + + // 发送POST请求 + String responseBody = HttpClientSender.sendHttpPost(this.serverHost, method, + fullUrlParams, requestBody.toJSONString()); + System.out.println(responseBody); + // 返回结果解析 + JSONObject userObj = JSON.parseObject(responseBody); + System.out.println(JSON.toJSONString(userObj)); + return userObj; + // 返回errno为0,表示成功,其他表示失败 +// if (userObj.getIntValue("errno") == 0) { +// JSONObject data = userObj.getJSONObject("data"); +// if (data != null) { +// //对返回data进行处理 +// String taskId = data.getString("taskId"); +// return taskId; +// } +// return null; +// } else { +// //接口返回异常 +// System.out.println(userObj.getIntValue("errno")); +// System.out.println(userObj.getString("errmsg")); +// throw new Exception(userObj.getIntValue("errno") + ":" +// + userObj.getString("errmsg")); +// } + } + + + /** + * GET方法示例 + * 下载合同PDF文件 + * + * @param contractId 合同编号 + * @return + * @throws Exception + */ + public byte[] contractDownload(String contractId) throws Exception { + String host = this.serverHost; + String method = "/storage/contract/download/"; + + // 组装url参数 + String urlParams = "contractId=" + contractId; + + // 生成一个时间戳参数 + String rtick = RSAUtils.getRtick(); + // 计算参数签名 + String paramsSign = RSAUtils.calcRsaSign(this.developerId, + this.privateKey, host, method, rtick, urlParams, null); + // 签名参数追加为url参数 + urlParams = String.format(urlSignParams, this.developerId, rtick, + paramsSign) + "&" + urlParams; + // 发送请求 + byte[] responseBody = HttpClientSender.sendHttpGet(host, method, + urlParams); + // 返回结果解析 + return responseBody; + } + + public String selectApplyStatus(String account, String taskId) throws Exception { + String methodInvoke = "/user/async/applyCert/status/"; + JSONObject requestParam = new JSONObject(); + + //用户账号 + requestParam.put("account", account); + //任务单号 + requestParam.put("taskId", taskId); + String timestamsParam = RSAUtils.getRtick(); + // 计算参数签名 + String paramsSign = RSAUtils.calcRsaSign(this.developerId, + this.privateKey, this.serverHost, methodInvoke, timestamsParam, null, + requestParam.toJSONString()); + // 签名参数追加为url参数 + String fullUrlParams = String.format(urlSignParams, this.developerId, + timestamsParam, paramsSign); + String responseResult = HttpClientSender.sendHttpPost(this.serverHost, methodInvoke, + fullUrlParams, requestParam.toJSONString()); + JSONObject responseObj = JSON.parseObject(responseResult); + // 返回errno为0,表示成功,其他表示失败 + if (responseObj.getIntValue("errno") == 0) { + JSONObject data = responseObj.getJSONObject("data"); + if (data != null) { + String message = data.getString("message"); + String status = data.getString("status"); + return status; + } + } else { + + log.error("查询申请状态异常:" + responseObj.toJSONString()); + } + return responseObj.toJSONString(); + } + + + + /** + * 获取签署链接 + * + * @param arbitrSignatuVO + * @return + * @throws Exception + */ + public String getSignLink(ArbitrSignatuVO arbitrSignatuVO) throws Exception { + String methodInvoke = "/contract/send/"; + JSONObject requestParam = new JSONObject(); + + requestParam.put("contractId", arbitrSignatuVO.getContractNum()); + requestParam.put("signer", arbitrSignatuVO.getSignerAccout()); + + JSONArray signatureArray = new JSONArray(); + + JSONObject signatuItem = new JSONObject(); + signatuItem.put("pageNum", arbitrSignatuVO.getPageNumSigner()); + //x坐标 + signatuItem.put("x", arbitrSignatuVO.getPageNumSignerX()); + //y坐标 + signatuItem.put("y", arbitrSignatuVO.getPageNumSignerY()); + signatureArray.add(signatuItem); + + requestParam.put("signaturePositions", signatureArray); + + + String timestamsParam = RSAUtils.getRtick(); + // 计算参数签名 + String paramsSign = RSAUtils.calcRsaSign(this.developerId, + this.privateKey, this.serverHost, methodInvoke, timestamsParam, null, + requestParam.toJSONString()); + // 签名参数追加为url参数 + String fullUrlParams = String.format(urlSignParams, this.developerId, + timestamsParam, paramsSign); + String responseResult = HttpClientSender.sendHttpPost(this.serverHost, methodInvoke, + fullUrlParams, requestParam.toJSONString()); + JSONObject responseObj = JSON.parseObject(responseResult); + // 返回errno为0,表示成功,其他表示失败 + if (responseObj.getIntValue("errno") == 0) { + JSONObject data = responseObj.getJSONObject("data"); + if (data != null) { + String signLink = data.getString("url"); + return signLink; + } + } else { + + log.error("获取签署链接异常:" + responseObj.toJSONString()); + } + return responseObj.toJSONString(); + } + + /** + * 完成签署 + * + * @param arbitrSignatuVO + * @return + * @throws Exception + */ + public String finishSign(ArbitrSignatuVO arbitrSignatuVO) throws Exception { + String methodInvoke = "/storage/contract/lock/"; + JSONObject requestParam = new JSONObject(); + requestParam.put("contractId", arbitrSignatuVO.getContractNum()); + String timestamsParam = RSAUtils.getRtick(); + // 计算参数签名 + String paramsSign = RSAUtils.calcRsaSign(this.developerId, + this.privateKey, this.serverHost, methodInvoke, timestamsParam, null, + requestParam.toJSONString()); + // 签名参数追加为url参数 + String fullUrlParams = String.format(urlSignParams, this.developerId, + timestamsParam, paramsSign); + String responseResult = HttpClientSender.sendHttpPost(this.serverHost, methodInvoke, + fullUrlParams, requestParam.toJSONString()); + JSONObject responseObj = JSON.parseObject(responseResult); + // 返回errno为0,表示成功,其他表示失败 + if (responseObj.getIntValue("errno") == 0) { + return "完成签名"; + } else { + + log.error("完成签署异常:" + responseObj.toJSONString()); + } + return responseObj.toJSONString(); + } + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/HttpClientSender.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/HttpClientSender.java new file mode 100644 index 0000000..3a1af73 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/HttpClientSender.java @@ -0,0 +1,390 @@ +package com.ruoyi.bestsign.utils; + +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; + +public class HttpClientSender { + + private static PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null; + private static Map httpClients = new HashMap(); + + private static Object o = new Object(); + + public static String sendHttpPost(String host, String method, String urlParams, String sendData) throws IOException { + + String requestUrl = host + method + urlParams; + + Map response = request("POST", requestUrl, sendData, null); + int responseCode = Integer.parseInt(response.get("responseCode").toString()); + byte[] responseBytes = (byte[]) response.get("responseData"); + String responseString; + try { + responseString = new String(responseBytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + responseString = new String(responseBytes); + } + //请求返回结果无论成功失败,http-status均为200 + if (responseCode == 200) { + //返回结果 + return responseString; + } else { + throw new IOException(responseCode + ":" + responseString); + } + } + + public static byte[] sendHttpGet(String host, String method, String urlParams) throws IOException { + String requestUrl = host + method + urlParams; + Map response = request("GET", requestUrl, null, null); + int responseCode = Integer.parseInt(response.get("responseCode").toString()); + byte[] responseBytes = (byte[]) response.get("responseData"); + //请求返回结果无论成功失败,http-status均为200 + if (responseCode == 200) { + //返回结果 + return responseBytes; + } else { + throw new IOException(responseCode + ""); + } + } + + public static String urlencode(String data) { + return urlencode(data, "UTF-8"); + } + + public static String urlencode(String data, String charset) { + try { + return URLEncoder.encode(data, charset); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static Map request(String method, String url, Object sendData, Map headers) throws IOException { + + + String requestPath; + try { + requestPath = new URL(url).getPath(); + } catch (MalformedURLException e) { + throw new RuntimeException(e.getMessage(), e); + } + CloseableHttpClient httpClient = getHttpClient(requestPath); + + Map response = null; + if ("POST".equals(method)) { + response = sendPost(httpClient, url, headers, sendData); + } else { + response = sendGet(httpClient, url, headers); + } + return response; + } + + private static Map sendPost(CloseableHttpClient httpClient, String url, Map headers, Object sendData) throws IOException { + String tag = "[HttpRequester] [POST " + url + "]"; + int responseCode = -1; + byte[] responseBytes = null; + + HttpPost request = new HttpPost(url); + if (headers != null && headers.size() > 0) { + for (String name : headers.keySet()) { + String value = headers.get(name); + request.setHeader(name, value); + } + } + if (sendData != null) { + StringEntity stringEntity = new StringEntity((String) sendData, "UTF-8"); + stringEntity.setContentType("application/json"); + request.setEntity(stringEntity); + + HttpEntity httpEntity = null; + IOException exception = null; + for (int i = 0; i < 3; i++) { + try { + CloseableHttpResponse response = httpClient.execute(request); + responseCode = response.getStatusLine().getStatusCode(); + httpEntity = response.getEntity(); + + String responseBody = EntityUtils.toString(httpEntity, "utf-8"); + if (responseBody != null) { + responseBytes = responseBody.getBytes(); + } else { + InputStream respStream = null; + try { + respStream = httpEntity.getContent(); + int respBodySize = respStream.available(); + if (respBodySize <= 0) + throw new IOException("Invalid respBodySize: " + respBodySize); + responseBytes = new byte[respBodySize]; + if (respStream.read(responseBytes) != respBodySize) + throw new IOException("Read respBody Error"); + } catch (Exception e) { + } finally { + if (respStream != null) { + respStream.close(); + } + } + } + + exception = null; + break; + } catch (UnsupportedOperationException e) { + try { + EntityUtils.consume(httpEntity); + } catch (IOException e2) { + + } + throw new RuntimeException(e.getMessage(), e); + } catch (IOException e) { + e.printStackTrace(); + exception = e; + try { + EntityUtils.consume(httpEntity); + } catch (IOException e2) { + + } + if (i < 2) { + try { + Thread.sleep(5); + } catch (InterruptedException e2) { + + } + } + } + } + if (exception != null) { + throw exception; + } + + } + Map response = new HashMap(); + response.put("responseCode", responseCode); + response.put("responseData", responseBytes); + String loggerResponseString = getLoggerString(responseBytes, 256); + return response; + } + + private static Map sendGet(CloseableHttpClient httpClient, String url, Map headers) throws IOException { + String tag = "[HttpRequester] [GET " + url + "]"; + int responseCode = -1; + byte[] responseBytes = null; + + HttpGet request = new HttpGet(url); + if (headers != null && headers.size() > 0) { + for (String name : headers.keySet()) { + String value = headers.get(name); + request.setHeader(name, value); + } + } + HttpEntity httpEntity = null; + IOException exception = null; + for (int i = 0; i < 3; i++) { + try { + CloseableHttpResponse response = httpClient.execute(request); + responseCode = response.getStatusLine().getStatusCode(); + httpEntity = response.getEntity(); + + byte[] responseBody = EntityUtils.toByteArray(httpEntity); + if (responseBody != null) { + responseBytes = responseBody; + } else { + InputStream respStream = null; + try { + respStream = httpEntity.getContent(); + int respBodySize = respStream.available(); + if (respBodySize <= 0) + throw new IOException("Invalid respBodySize: " + respBodySize); + responseBytes = new byte[respBodySize]; + if (respStream.read(responseBytes) != respBodySize) + throw new IOException("Read respBody Error"); + } catch (Exception e) { + } finally { + if (respStream != null) { + respStream.close(); + } + } + } + + exception = null; + break; + } catch (UnsupportedOperationException e) { + try { + EntityUtils.consume(httpEntity); + } catch (IOException e2) { + + } + throw new RuntimeException(e.getMessage(), e); + } catch (IOException e) { + e.printStackTrace(); + exception = e; + try { + EntityUtils.consume(httpEntity); + } catch (IOException e2) { + + } + if (i < 2) { + try { + Thread.sleep(5); + } catch (InterruptedException e2) { + + } + } + } + } + if (exception != null) { + throw exception; + } + Map response = new HashMap(); + response.put("responseCode", responseCode); + response.put("responseData", responseBytes); + String loggerResponseString = getLoggerString(responseBytes, 256); + System.out.println(tag + " response " + responseCode + " " + loggerResponseString); + return response; + } + + private static String getLoggerString(final byte[] data, int maxLength) { + String loggerString; + if (data.length > maxLength) { + byte[] shortData = new byte[maxLength]; + System.arraycopy(data, 0, shortData, 0, shortData.length); + try { + loggerString = new String(shortData, "UTF-8") + "..."; + } catch (UnsupportedEncodingException e) { + loggerString = new String(shortData) + "..."; + } + } else { + try { + loggerString = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + loggerString = new String(data); + } + } + + char[] chars = new char[loggerString.length()]; + loggerString.getChars(0, loggerString.length(), chars, 0); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (c == '\n' || c == '\r') { + chars[i] = ' '; + } + } + return new String(chars); + } + + private static CloseableHttpClient getHttpClient(String requestPath) { + if (httpClients.containsKey(requestPath)) { + return httpClients.get(requestPath); + } + if (poolingHttpClientConnectionManager == null) { + synchronized (o) { + if (poolingHttpClientConnectionManager == null) { + poolingHttpClientConnectionManager = HttpClientUtils.createHttpClientConnectionManager(); + } + } + } + synchronized (httpClients) { + if (httpClients.containsKey(requestPath)) { + return httpClients.get(requestPath); + } + CloseableHttpClient httpClient = HttpClientUtils.createHttpClient(poolingHttpClientConnectionManager); + httpClients.put(requestPath, httpClient); + return httpClient; + } + } + + private static class HttpClientUtils { + + // 默认连接超时 + private static int defaultConnectTimeout = 6000; + // 默认读取超时 + private static int defaultReadTimeout = 30000; + + public static CloseableHttpClient createHttpClient(PoolingHttpClientConnectionManager connManager) { + //HttpHost httpHost = new HttpHost("10.211.55.4", 8888); + CloseableHttpClient httpClient = HttpClients.custom() + //.setProxy(httpHost) + .setConnectionManager(connManager) + .disableContentCompression() + .setSSLContext(getSslcontext()) + .setDefaultRequestConfig(getRequestConfig()) + .build(); + return httpClient; + } + + public static PoolingHttpClientConnectionManager createHttpClientConnectionManager() { + SSLConnectionSocketFactory sslConnectionSocketFactory = null; + try { + sslConnectionSocketFactory = new SSLConnectionSocketFactory(getSslcontext(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + Registry socketFactoryRegistry = RegistryBuilder.create() + .register("https", sslConnectionSocketFactory) + .register("http", new PlainConnectionSocketFactory()) + .build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + cm.setMaxTotal(500); + cm.setDefaultMaxPerRoute(500); + return cm; + } + + private static RequestConfig getRequestConfig() { + RequestConfig defaultRequestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(defaultConnectTimeout) + .setSocketTimeout(defaultReadTimeout) + .build(); + return defaultRequestConfig; + } + + private static SSLContext getSslcontext() { + SSLContext sslContext = null; + try { + sslContext = SSLContext.getInstance("TLS"); + TrustManager tm = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + sslContext.init(null, new TrustManager[]{tm}, null); + + } catch (Exception e) { + e.printStackTrace(); + } + return sslContext; + } + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/RSAUtils.java b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/RSAUtils.java new file mode 100644 index 0000000..957e1fb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/bestsign/utils/RSAUtils.java @@ -0,0 +1,281 @@ +package com.ruoyi.bestsign.utils; + +import org.apache.commons.codec.binary.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Date; +import java.util.Map; +import java.util.TreeMap; + +/** + * 参数签名算法工具类 + */ +public class RSAUtils { + + /** + * 获取当前的时间戳参数 + * @return + */ + public static String getRtick(){ + long timestamp = System.currentTimeMillis(); + int rnd = (int)Math.random() * 1000; + String rtick = timestamp + "" + rnd; + return rtick; + } + + /** + * 计算参数签名 + * @param developerId 开发者ID + * @param privateKey 用户私钥 + * @param host 请求的HOST地址(http://ip:port/context) + * @param methodName 请求的接口方法名 + * @param rtick 时间戳参数 + * @param urlParams url参数(param1=value1¶m2=value2¶m3=value3) + * @param requestBody request body 参数(JSON字符串) + * @return + */ + public static String calcRsaSign(String developerId, String privateKey, String host, String methodName, String rtick, String urlParams, String requestBody) { + String url = host+methodName; + + Map mySignedURLParams = new TreeMap(); + mySignedURLParams.put("developerId", developerId); + mySignedURLParams.put("rtick", rtick); + mySignedURLParams.put("signType", "rsa"); + + if(urlParams != null && !"".equals(urlParams)){ + String[] params = urlParams.split("&"); + for(String p1 : params){ + String[] p2 = p1.split("="); + String key = p2[0]; + String value = ""; + if(p2.length == 2){ + value = p2[1]; + } + mySignedURLParams.put(key, value); + } + } + + String requestPath; + try { + requestPath = new URL(url).getPath(); + } + catch (MalformedURLException e) { + throw new RuntimeException(e.getMessage(), e); + } + + StringBuilder signStringBuilder = new StringBuilder(); + for (String name : mySignedURLParams.keySet()) { + String value = mySignedURLParams.get(name); + signStringBuilder.append(name); + signStringBuilder.append("="); + signStringBuilder.append(value); + } + signStringBuilder.append(requestPath); + + if (requestBody != null && !"".equals(requestBody) ) { + String requestMd5 = getRequestMd5(requestBody); + signStringBuilder.append(requestMd5); + } + + String signString = signStringBuilder.toString(); + String rsaSign = calcRsaSign(privateKey, signString); + //rsa算出来的sign,需要urlencode + try { + rsaSign = URLEncoder.encode(rsaSign,"UTF-8"); + } catch (UnsupportedEncodingException e) { + rsaSign = null; + } + return rsaSign; + } + + /** + * 获取request body 的MD5 + * @param requestBody + * @return + */ + private static String getRequestMd5(final String requestBody) { + byte[] data; + + String newRequestBody = convertToUtf8(requestBody); + try { + data = newRequestBody.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + return md5(data); + } + + /** + * 计算参数RSA签名 + * @param privateKey + * @param signData + * @return + */ + private static String calcRsaSign(String privateKey, final String signData) { + byte[] data; + try { + data = signData.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + byte[] sign = null; + // 解密由base64编码的私钥 + byte[] privateKeyBytes = base64decode(privateKey.getBytes()); + + // 构造PKCS8EncodedKeySpec对象 + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); + + // KEY_ALGORITHM 指定的加密算法 + KeyFactory keyFactory; + try { + keyFactory = KeyFactory.getInstance("RSA"); + } + catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } + + // 取私钥匙对象 + PrivateKey priKey; + try { + priKey = keyFactory.generatePrivate(pkcs8KeySpec); + } + catch (InvalidKeySpecException e) { + throw new RuntimeException(e.getMessage(), e); + } + + // 用私钥对信息生成数字签名 + Signature signature; + try { + signature = Signature.getInstance("SHA1withRSA"); + } + catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } + try { + signature.initSign(priKey); + } + catch (InvalidKeyException e) { + throw new RuntimeException(e.getMessage(), e); + } + + try { + signature.update(data); + sign = signature.sign(); + } + catch (SignatureException e) { + throw new RuntimeException(e.getMessage(), e); + } + return new String(base64encode(sign)); + } + + /** + * 转换字符集到utf8 + * + * @param src + * @return + */ + private static String convertToUtf8(String src) { + if (src == null || src.length() == 0) { + return src; + } + if ("UTF-8".equalsIgnoreCase(Charset.defaultCharset().name())) { + return src; + } + + byte[] srcData = src.getBytes(); + try { + return new String(srcData, "UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * md5 + * @param data + * @return + */ + public static String md5(byte[] data) { + char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + byte[] btInput = data; + // 获得MD5摘要算法的 MessageDigest 对象 + MessageDigest mdInst; + try { + mdInst = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } + // 使用指定的字节更新摘要 + mdInst.update(btInput); + // 获得密文 + byte[] md = mdInst.digest(); + // 把密文转换成十六进制的字符串形式 + int j = md.length; + char str[] = new char[j * 2]; + int k = 0; + for (int i = 0; i < j; i++) { + byte byte0 = md[i]; + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } + + /** + * base64编码 + * @param data + * @return + */ + public static byte[] base64encode(byte[] data) { + return Base64.encodeBase64(data); + } + + /** + * base64编码字符串 + * @param data + * @return + */ + public static String base64encodeString(byte[] data) { + return Base64.encodeBase64String(data); + } + + /** + * base64解码 + * @param data + * @return + */ + public static byte[] base64decode(byte[] data) { + try { + return Base64.decodeBase64(data); + } catch (Exception e) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (int i = 0; i < data.length; i++) { + byte c = data[i]; + if (c == 13 || c == 10) { + continue; + } + outputStream.write(c); + } + try { + outputStream.close(); + } catch (IOException e2) { + + } + data = outputStream.toByteArray(); + return Base64.decodeBase64(data); + } + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java new file mode 100644 index 0000000..83f0703 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java new file mode 100644 index 0000000..c54678c --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java new file mode 100644 index 0000000..7fdea30 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java new file mode 100644 index 0000000..8c07a54 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java new file mode 100644 index 0000000..f6761df --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java new file mode 100644 index 0000000..820a13b --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java new file mode 100644 index 0000000..47b21bf --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java new file mode 100644 index 0000000..de10a74 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java new file mode 100644 index 0000000..2bbd318 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java new file mode 100644 index 0000000..6e8c416 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java new file mode 100644 index 0000000..4d15810 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java new file mode 100644 index 0000000..a5d5fdc --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java new file mode 100644 index 0000000..afff8c9 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java new file mode 100644 index 0000000..13d49d6 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java new file mode 100644 index 0000000..4ef0d06 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.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.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); + + List selectUserDeptListByRoleId(@Param("roleId")Long roleId); + + /** + * 批量新增 + * @param sysDepts + * @return + */ + int batchSave(@Param("list")List sysDepts); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..a341f1e --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java new file mode 100644 index 0000000..5fb48fb --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java new file mode 100644 index 0000000..629866f --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java new file mode 100644 index 0000000..99c0c50 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..c34f0a2 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java new file mode 100644 index 0000000..2ae6457 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java new file mode 100644 index 0000000..ffcfb25 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java @@ -0,0 +1,107 @@ +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); + + /** + * 查询岗位为经办人的岗位信息 + * + * @param postCode 岗位编码 + * @return 角色对象信息 + */ + public SysPost selectPostByPostCode(String postCode); + + /** + * 根据用户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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java new file mode 100644 index 0000000..f9d3a2f --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..aed7155 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -0,0 +1,115 @@ +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 roleName + * @return + */ + public Long selectRoleIdByName(String roleName); + + + /** + * 根据用户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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..6602bee --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..e23c18f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -0,0 +1,174 @@ +package com.ruoyi.system.mapper; + +import java.util.List; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +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); + + /** + * 查询仲裁员角色下的用户 + * @return + */ + public List selectUserListByAdRole(Arbitrator arbitrator); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @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 deptId 部门ID + * @return 用户对象信息 + */ + public List selectUserByDeptId(Long deptId); + + /** + * 新增用户信息 + * + * @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); + + List selectUserListByIds(@Param("idList") List idList); + + /** + * 根据身份证号查询用户信息 + * @param identityNo + * @return + */ + SysUser selectUserByIdCard(@Param("idCard")String identityNo); + /** + * 根据手机号查询用户信息 + * @param phone + * @return + */ + SysUser selectUserByPhone(@Param("phone")String phone); + + /** + * 根据部门和角色查询用户 + * @param applicationOrganId + * @param roleName + * @return + */ + List selectByDeptIdAndRole(@Param("deptId")String applicationOrganId, @Param("roleName")String roleName); + + List selectRoleUserByDeptId(@Param("deptId")Long deptId,@Param("roleId") Long roleId ); + + /** + * 批量新增用户 + * @param addUsers + * @return + */ + int batchSave(@Param("list")List addUsers); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java new file mode 100644 index 0000000..e08991d --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..3143ec8 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java new file mode 100644 index 0000000..b307776 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java new file mode 100644 index 0000000..f228208 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java new file mode 100644 index 0000000..9bc4f13 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java new file mode 100644 index 0000000..01c1c1d --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java new file mode 100644 index 0000000..ce3151d --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java new file mode 100644 index 0000000..7d60696 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java new file mode 100644 index 0000000..47ce1b7 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java new file mode 100644 index 0000000..4fd8e5a --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java new file mode 100644 index 0000000..84779bf --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java new file mode 100644 index 0000000..6c29f09 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java new file mode 100644 index 0000000..8eb5448 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java new file mode 100644 index 0000000..8830025 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -0,0 +1,211 @@ +package com.ruoyi.system.service; + +import java.util.List; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; + +/** + * 用户 业务层 + * + * @author ruoyi + */ +public interface ISysUserService +{ + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser user); + public List selectUserListByAdRole(Arbitrator arbitrator); + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @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 AjaxResult insertUser(SysUser user); + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean registerUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public AjaxResult 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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..4d29b22 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..e5c8307 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,341 @@ +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) + { + Long parentId = dept.getParentId(); + if(parentId!=null){ + 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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..fced569 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..7fd9654 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 0000000..216aecb --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..225c280 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..765438b --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 0000000..5489815 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..5e5fe06 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..d6cee80 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java new file mode 100644 index 0000000..f80a877 --- /dev/null +++ b/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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..dcc8cdf --- /dev/null +++ b/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.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Validator; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.system.mapper.*; +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import com.ruoyi.wisdomarbitrate.mapper.CaseApplicationMapper; +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 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.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 用户 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysUserServiceImpl implements ISysUserService { + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); + + @Autowired + private SysUserMapper userMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysDeptMapper sysDeptMapper; + + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + @Autowired + private ISysConfigService configService; + + @Autowired + private CaseApplicationMapper caseApplicationMapper; + + @Autowired + protected Validator validator; + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) { + return userMapper.selectUserList(user); + } + + @Override + public List selectUserListByAdRole(Arbitrator arbitrator) { + List sysUsers = userMapper.selectUserListByAdRole(arbitrator); + if(sysUsers!=null&&sysUsers.size()>0){ + for(SysUser sysUser: sysUsers){ + Long userId = sysUser.getUserId(); + int casenum = caseApplicationMapper.selectCasenum(userId.toString()); + String nickName = sysUser.getNickName(); + String nickNamenew = nickName + "(待办案件数量" + casenum + "个)"; + sysUser.setNickNameAndNum(nickNamenew); + } + + } + + return sysUsers; + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @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 (!SysUser.isAdmin(SecurityUtils.getUserId())) { + 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 AjaxResult insertUser(SysUser user) { + Long deptId = user.getDeptId(); + Long[] postIds = user.getPostIds(); + if (deptId != null) { + SysDept dept = sysDeptMapper.selectDeptById(deptId); + Integer deptType = dept.getDeptType(); + if (deptType!=null && deptType.intValue() == 1) { + SysPost sysPost = postMapper.selectPostByPostCode("jbr"); + Long postId = sysPost.getPostId(); + if (postIds.length > 0) { + boolean isContain = Arrays.asList(postIds).contains(postId); + if (isContain) { + List sysUsers = userMapper.selectUserByDeptId(deptId); + if (sysUsers != null && sysUsers.size() > 0) { + return AjaxResult.error("部门类型为仲裁机构的部门的岗位为经办人的用户只能有一个!"); + } + } + } + } + } + + // 新增用户信息 + int rows = userMapper.insertUser(user); + // 新增用户岗位关联 + insertUserPost(user); + // 新增用户与角色管理 + insertUserRole(user); + return AjaxResult.success("新建用户成功"); + } + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean registerUser(SysUser user) { + return userMapper.insertUser(user) > 0; + } + + /** + * 修改保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional + public AjaxResult updateUser(SysUser user) { + Long deptId = user.getDeptId(); + Long[] postIds = user.getPostIds(); + if (deptId != null) { + SysDept dept = sysDeptMapper.selectDeptById(deptId); + Integer deptType = dept.getDeptType(); + if (deptType != null && deptType.intValue() == 1) { + SysPost sysPost = postMapper.selectPostByPostCode("jbr"); + Long postId = sysPost.getPostId(); + if (postIds.length > 0) { + boolean isContain = Arrays.asList(postIds).contains(postId); + if (isContain) { + List sysUsers = userMapper.selectUserByDeptId(deptId); + if (sysUsers != null && sysUsers.size() > 0) { + return AjaxResult.error("部门类型为仲裁机构的部门的岗位为经办人的用户只能有一个!"); + } + } + } + } + } + + Long userId = user.getUserId(); + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 新增用户与角色管理 + insertUserRole(user); + // 删除用户与岗位关联 + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗位管理 + insertUserPost(user); + userMapper.updateUser(user); + return AjaxResult.success("更新用户成功"); + } + + /** + * 用户授权角色 + * + * @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.isNotEmpty(posts)) { + // 新增用户与岗位管理 + List list = new ArrayList(posts.length); + for (Long postId : posts) { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + userPostMapper.batchUserPost(list); + } + } + + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserRole(Long userId, Long[] roleIds) { + if (StringUtils.isNotEmpty(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(); + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/StringIdsReq.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/StringIdsReq.java new file mode 100644 index 0000000..7e561dd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/StringIdsReq.java @@ -0,0 +1,22 @@ +package com.ruoyi.wisdomarbitrate; + +import lombok.Data; + +import java.util.List; + +@Data +public class StringIdsReq { + private List ids; + /** + * 签署人账号(即仲裁员手机号) + */ + private String psnAccount; + /** + * 签署人id + */ + private String psnId ; + /** + * 机构账户 + */ + private String orgId ; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Adjudication.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Adjudication.java new file mode 100644 index 0000000..75eb96e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Adjudication.java @@ -0,0 +1,188 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import lombok.Data; + +@Data +public class Adjudication { + /** + * 申请人姓名 + */ + private String appName; + /** + * 申请人性别 + */ + private String appSex; + /** + * 申请人身份证号码 + */ + private String appIDNo; + /** + * 申请人住所 + */ + private String appAddress; + + /** + * 申请人代理人姓名 + */ + private String appAgentName; + /** + * 申请人代理人身份证 + */ + private String appAgentIDNo; + /** + * 被申请人姓名 + */ + private String resName; + /** + * 被申请人性别 + */ + private String resSex; + /** + * 被申请人身份证号码 + */ + private String resIDNo; + /** + * 被申请人住所 + */ + private String resAddress; + + /** + * 被申请人代理人姓名 + */ + private String resAgentName; + /** + * 被申请人代理人身份证 + */ + private String resAgentIDNo; + + /** + * 案件名称 + */ + private String caseName; + + /** + * 仲裁员名称 + */ + private String arbitratorName; + /** + * 开庭年 + */ + private String hearYear; + /** + * 开庭月 + */ + private String hearMonths; + /** + * 开庭日 + */ + private String hearDay; + + /** + * 申请人具体仲裁请求 + */ + private String appArbitrationClaims; + + /** + * 申请人证据名称 + */ + private String appEvidenceName; + + /** + * 申请人拟证事实 + */ + private String appProveFacts; + /** + * 被申请人对申请人答辩内容 + */ + private String resDefenseContentToApp; + + /** + * 被申请人具体仲裁请求 + */ + private String resArbitrationClaims; + /** + * 被申请人证据名称 + */ + private String resEvidenceName; + /** + * 被申请人拟证事实 + */ + private String resProveFacts; + /** + * 申请人对被申请人答辩内容 + */ + private String appDefenseContentToRes; + /** + * 第三人答辩内容 + */ + private String thirdDefenseContent; + /** + * 第三人证据名称 + */ + private String thirdEvidenceName; + /** + * 第三人拟证事实 + */ + private String thirdProveFacts; + /** + * 申请人对第三人答辩内容 + */ + private String appDefenseContentToThird; + /** + * 被申请人对第三人答辩内容 + */ + private String resDefenseContentToThird; + /** + * 证据认定 + */ + private String evidenDetermi; + /** + * 认定事实 + */ + private String factDetermi; + /** + * 综上所述 + */ + private String caseSketch; + /** + * 本庭认为 + */ + private String arbitrateThink; + /** + * 裁决如下 + */ + private String rulingFollows; + /** + * 法律条款 + */ + private String legalProvisions; + /** + * 首席仲裁 + */ + private String umpire; + /** + * 仲裁员1 + */ + private String arbitratorName1; + /** + * 仲裁员2 + */ + private String arbitratorName2; + /** + * 年 + */ + private String year; + /** + * 月 + */ + private String months; + /** + * 日 + */ + private String day; + /** + * 书记员 + */ + private String clerk; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ArbitrateRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ArbitrateRecord.java new file mode 100644 index 0000000..eed8844 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ArbitrateRecord.java @@ -0,0 +1,76 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +@Data +public class ArbitrateRecord extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 案件申请id */ + private Long caseAppliId; + /** 证据认定 */ + private String evidenDetermi; + /** 认定事实 */ + private String factDetermi; + /** 综上所述 */ + private String caseSketch; + /** 本庭认为 */ + private String arbitrateThink; + /** 裁决如下 */ + private String rulingFollows; + /** 核验裁决书意见 */ + private String verificaOpinion; + /** 审核裁决书意见 */ + private String checkOpinion; + /** 仲裁员审核裁决书意见 */ + private String arbitraCheckOpinion; + /** 裁决书附件id */ + private Integer annexId; + + /** 被申请人是否缺席 */ + private Integer isAbsence; + /** 被申请人质证意见 */ + private String responCrossOpin; + /** 申请人质证意见 */ + private String applicaCrossOpin; + /** 申请人是否缺席 */ + private Integer appliIsAbsen; + /** 被申请人质证意见 */ + private String responDefenOpini; + /** + * 本案争议焦点 + */ + private String caseFocus; + /** + * 本案事实 + */ + private String caseFacts; + /** + * 被申请人对上述材料的质证意见 + */ + private String respondentOpinion; + /** + * 申请人对上述材料的质证意见 + */ + private String applicantOpinion; + + /** + * 立案审查驳回原因 + */ + private String caseCheckReject; + /** + * 仲裁员确认裁决书驳回 + */ + private String arbitrateReject; + /** + * 部门长确认裁决书驳回 + */ + private String deptorReject; + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Arbitrator.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Arbitrator.java new file mode 100644 index 0000000..4e73c8d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/Arbitrator.java @@ -0,0 +1,123 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.List; + +public class Arbitrator extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 仲裁员姓名 */ + private String arbitratorName; + /** 职称 */ + private String title; + /** 职业 */ + private String career; + /** 专业分类 */ + private String professiClassifi; + /** 学历 */ + private String education; + /** 所在地区 */ + private String area; + /** 联系电话 */ + private String telephone; + + List idList; + + public List getIdList() { + return idList; + } + + public void setIdList(List idList) { + this.idList = idList; + } + + public String getArbitratorName() { + return arbitratorName; + } + + public void setArbitratorName(String arbitratorName) { + this.arbitratorName = arbitratorName; + } + + /** 当前案件数量 */ + private int currentCaseNum; + /** 已结案数量 */ + private int closedCaseNum; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getCareer() { + return career; + } + + public void setCareer(String career) { + this.career = career; + } + + public String getProfessiClassifi() { + return professiClassifi; + } + + public void setProfessiClassifi(String professiClassifi) { + this.professiClassifi = professiClassifi; + } + + public String getEducation() { + return education; + } + + public void setEducation(String education) { + this.education = education; + } + + public String getArea() { + return area; + } + + public void setArea(String area) { + this.area = area; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public int getCurrentCaseNum() { + return currentCaseNum; + } + + public void setCurrentCaseNum(int currentCaseNum) { + this.currentCaseNum = currentCaseNum; + } + + public int getClosedCaseNum() { + return closedCaseNum; + } + + public void setClosedCaseNum(int closedCaseNum) { + this.closedCaseNum = closedCaseNum; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/BatchCaseApplication.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/BatchCaseApplication.java new file mode 100644 index 0000000..72abf5a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/BatchCaseApplication.java @@ -0,0 +1,31 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import lombok.Data; + +import java.util.List; + +/** + * @author wangqiong + * @description 批量操作案件 + * @date 2023-10-20 14:49 + */ +@Data +public class BatchCaseApplication { + private List ids; + /** + * 是否同意,0拒绝,1同意 + */ + private Integer agreeOrNotCheck; + /** + * 1同意,0拒绝 + */ + private Integer opinion; + /** 驳回原因 */ + private String caseCheckReject; + /** + * 批号 + */ + private String batchNumber; + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAffiliate.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAffiliate.java new file mode 100644 index 0000000..6e154e1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAffiliate.java @@ -0,0 +1,353 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +public class CaseAffiliate extends BaseEntity { + private static final long serialVersionUID = 1L; + /** ID */ + @Excel(name = "ID", cellType = Excel.ColumnType.NUMERIC, prompt = "ID") + private Long id; + /** 案件申请id */ + private Long caseAppliId; + /** + * 案件申请日志id + */ + private Long caseAppliLogId; + /** 身份类型 */ + private int identityType; + /** 姓名 */ + @Excel(name = "姓名") + private String name; + /** + * 申请机构id + */ + private String applicationOrganId; + /** + * 申请机构名称 + */ + private String applicationOrganName; + + /** + * 法定代表人 + */ + private String compLegalPerson; + /** + * 邮箱 + */ + private String email; + /** + * 法定代表人职位 + */ + private String compLegalperPost; + /** + * 被申请人性别 + */ + private String responSex; + /** + * 被申请人出生年月日 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date responBirth; + /** + * 版本号 + */ + private Integer version; + /** + * 改变的字段 + */ + private String changeColumn; + + /** + * 代理人邮箱 + */ + private String agentEmail; + + public String getAgentEmail() { + return agentEmail; + } + + public void setAgentEmail(String agentEmail) { + this.agentEmail = agentEmail; + } + + public String getChangeColumn() { + return changeColumn; + } + + public void setChangeColumn(String changeColumn) { + this.changeColumn = changeColumn; + } + + public Long getCaseAppliLogId() { + return caseAppliLogId; + } + + public void setCaseAppliLogId(Long caseAppliLogId) { + this.caseAppliLogId = caseAppliLogId; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Date getResponBirth() { + return responBirth; + } + + public void setResponBirth(Date responBirth) { + this.responBirth = responBirth; + } + + + public String getCompLegalPerson() { + return compLegalPerson; + } + + public void setCompLegalPerson(String compLegalPerson) { + this.compLegalPerson = compLegalPerson; + } + + public String getCompLegalperPost() { + return compLegalperPost; + } + + public void setCompLegalperPost(String compLegalperPost) { + this.compLegalperPost = compLegalperPost; + } + + public String getResponSex() { + return responSex; + } + + public void setResponSex(String responSex) { + this.responSex = responSex; + } + + /** 身份证号 */ + @Excel(name = "身份证号") + private String identityNum; + /** 单位电话 */ + @Excel(name = "单位电话") + private String workTelphone; + /** 联系电话 */ + @Excel(name = "联系电话") + private String contactTelphone; + /** 联系地址 */ + @Excel(name = "联系地址") + private String contactAddress; + /** 住所 */ + @Excel(name = "住所") + private String residenAffili; + /** 申请人代理人职称 */ + @Excel(name = "申请人代理人职称") + private String appliAgentTitle; + + public String getResidenAffili() { + return residenAffili; + } + + public void setResidenAffili(String residenAffili) { + this.residenAffili = residenAffili; + } + + public String getAppliAgentTitle() { + return appliAgentTitle; + } + + public void setAppliAgentTitle(String appliAgentTitle) { + this.appliAgentTitle = appliAgentTitle; + } + + /** 单位地址 */ + @Excel(name = "单位地址") + private String workAddress; + + /** 代理人姓名 */ + @Excel(name = "代理人姓名") + private String nameAgent; + /** 身份证号 */ + @Excel(name = "代理人身份证号") + private String identityNumAgent; + /** 联系电话 */ + @Excel(name = "代理人联系电话") + private String contactTelphoneAgent; + /** 联系地址 */ + @Excel(name = "代理人联系地址") + private String contactAddressAgent; + + /** 送达电子邮件 */ + private String sendEmail; + private String userId; + private String applicantAgentUserId; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getApplicantAgentUserId() { + return applicantAgentUserId; + } + + public void setApplicantAgentUserId(String applicantAgentUserId) { + this.applicantAgentUserId = applicantAgentUserId; + } + + /** 快递单号 */ + private String trackNum; + + public String getApplicationOrganId() { + return applicationOrganId; + } + + public void setApplicationOrganId(String applicationOrganId) { + this.applicationOrganId = applicationOrganId; + } + + public String getApplicationOrganName() { + return applicationOrganName; + } + + public void setApplicationOrganName(String applicationOrganName) { + this.applicationOrganName = applicationOrganName; + } + + public String getSendEmail() { + return sendEmail; + } + + public void setSendEmail(String sendEmail) { + this.sendEmail = sendEmail; + } + + public String getTrackNum() { + return trackNum; + } + + public void setTrackNum(String trackNum) { + this.trackNum = trackNum; + } + + public String getNameAgent() { + return nameAgent; + } + + public void setNameAgent(String nameAgent) { + this.nameAgent = nameAgent; + } + + public String getIdentityNumAgent() { + return identityNumAgent; + } + + public void setIdentityNumAgent(String identityNumAgent) { + this.identityNumAgent = identityNumAgent; + } + + public String getContactTelphoneAgent() { + return contactTelphoneAgent; + } + + public void setContactTelphoneAgent(String contactTelphoneAgent) { + this.contactTelphoneAgent = contactTelphoneAgent; + } + + public String getContactAddressAgent() { + return contactAddressAgent; + } + + public void setContactAddressAgent(String contactAddressAgent) { + this.contactAddressAgent = contactAddressAgent; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCaseAppliId() { + return caseAppliId; + } + + public void setCaseAppliId(Long caseAppliId) { + this.caseAppliId = caseAppliId; + } + + public int getIdentityType() { + return identityType; + } + + public void setIdentityType(int identityType) { + this.identityType = identityType; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIdentityNum() { + return identityNum; + } + + public void setIdentityNum(String identityNum) { + this.identityNum = identityNum; + } + + public String getWorkTelphone() { + return workTelphone; + } + + public void setWorkTelphone(String workTelphone) { + this.workTelphone = workTelphone; + } + + public String getContactTelphone() { + return contactTelphone; + } + + public void setContactTelphone(String contactTelphone) { + this.contactTelphone = contactTelphone; + } + + public String getContactAddress() { + return contactAddress; + } + + public void setContactAddress(String contactAddress) { + this.contactAddress = contactAddress; + } + + public String getWorkAddress() { + return workAddress; + } + + public void setWorkAddress(String workAddress) { + this.workAddress = workAddress; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java new file mode 100644 index 0000000..8239489 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java @@ -0,0 +1,421 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +@Data +public class CaseApplication extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * 查询案件时区分是否待办案件,0待办案件,1已办案件 + */ + private String selectCaseStatus; + + /** ID */ + private Long id; + /** 案件名称 */ + @Excel(name = "案件名称") + private String caseName; + /** 案件编号 */ +// @Excel(name = "案件编号") + private String caseNum; + /** 案件标的 */ + @Excel(name = "案件标的") + private BigDecimal caseSubjectAmount; + /** + * 模板id + */ + private Long templateId; + + + + /** 立案日期 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date registerDate; + /** 仲裁方式 */ + private Integer arbitratMethod; + /** + * 是否导入,0手动录入,1导入,默认0 + */ + private Integer importFlag; + /** 仲裁方式名称 */ + private String arbitratMethodName; + + /** 案件状态 */ + private Integer caseStatus; + + /** 申请人是否书面审理 */ + private Integer applicantIsWrittenHear; + + /** 被申请人是否书面审理 */ + private Integer respondentIsWrittenHear; + /** 开庭方式是否一致 */ + private Integer arbitraMethodIssame; + /** 仲裁方式说明 */ + private String arbitratMethodIllustrate; + + + /** 案件申请表ID */ + private Long caseAppliId; + + /** 开庭日期 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date hearDate; + + /** 借款开始日期 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "借款开始日期") + private Date loanStartDate; + /** 借款结束日期 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "借款结束日期") + private Date loanEndDate; + /** 合同编号 */ + @Excel(name = "合同编号") + private String contractNumber; + /** 申请人主张欠本金 */ + @Excel(name = "申请人主张欠本金") + private BigDecimal claimPrinciOwed; + /** 申请人主张欠利息 */ + @Excel(name = "申请人主张欠利息") + private BigDecimal claimInterestOwed; + /** 申请人主张违约金 */ + @Excel(name = "申请人主张违约金") + private BigDecimal claimLiquidDamag; + /** 申请人请求仲裁庭裁决 */ + @Excel(name = "申请人请求仲裁庭裁决",width = 36) + private String requestRule; + + /** 是否财产保全申请 */ + @Excel(name = "是否财产保全申请",width = 26,combo= {"是","否"},readConverterExp = "0=否,1=是") + private Integer properPreser; + /** 申请人仲裁请求及事实和理由 */ + @Excel(name = "申请人仲裁请求及事实和理由",width = 36) + private String arbitratClaims; + /** 仲裁应缴费用 */ + private BigDecimal feePayable; + + /** 开始在线视频时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date beginVideoDate; + /** 在线视频人员 */ + private String onlineVideoPerson; + + /** 仲裁员id */ + private String arbitratorId; + /** 仲裁员名称 */ + private String arbitratorName; + + /** 案件描述 */ + private String caseDescribe; + /** 裁决书URL */ + private String filearbitraUrl; + + /** 是否同意组庭 */ + private Integer isAgreePendTral; + + /** 是否有异议需要举证 */ + private Integer objectionAddEviden; + /** 是否需要开庭审理 */ + private Integer openCourtHear; + + /** 是否仲裁反请求 */ + private Integer adjudicaCounter; + /** + * 仲裁反请求原因 + */ + private String adjudicaCounterReason; + + /** 被申请人是否缺席 */ + private Integer isAbsence; + /** 是否管辖异议申请 */ + private Integer objectiJuris; + /** 被申请人质证意见 */ + private String responCrossOpin; + /** 被申请人的答辩意见 */ + private String responDefenOpini; + /** 申请人是否缺席 */ + private Integer appliIsAbsen; + + /** 申请人质证意见 */ + private String applicaCrossOpin; + + /** 支付状态 */ + private Integer paymentStatus; + + /** 支付状态描述 */ + private String paymentStatusName; + /** + * 支付方式code,0线上支付,1线下支付 + */ + private Integer payTypeCode; + /** + * 支付方式name,0线上支付,1线下支付 + */ + private String payTypeName; + + + /** + * 缴费凭证 + */ + private List payOrderList; + // 导入校验失败信息 + private StringBuilder errorMsg; + /** + * 是否锁定,0-否,1-是 + */ + private Integer lockStatus; + /** 案件状态名称 */ + private String caseStatusName; + /** 是否同意审核 */ + private Integer agreeOrNotCheck; + /** 申请人名称 */ + private String applicantName; + /** 被申请人名称 */ + private String respondentName; + /** + * 用户身份证号 + */ + private String idCard; + /** + * 用户id + */ + private String userId; + /** + * 登录用户用户名 + */ + private String loginUserName; + private List deptIds; + /** + * 部门长状态 + */ + private List deptHeadStatus; + /** + * 代理人角色有关部门 + */ + private List agentDeptIds; + /** + * 财务状态 + */ + private Integer financeStatus; + /** + * 是否是被申请人,仲裁员,部门长,财务,代理人,0-否,1-是 + */ + private Integer isOtherRole; + /** + * 案件日志id + */ + private Long caseLogId; + /** 仲裁结果 */ + private String caseResult; + /** 是否指派仲裁员 */ + private int pendingAppointArbotrar; + /** 案件关联人信息 */ + private List caseAffiliates; + + /** 案件仲裁员 */ + private List arbitrators; + + private List caseStatusList; + + private List annexTypeList; + + private Integer annexType; + /** + * 案件附件列表 + */ + private List caseAttachList; + + /** 仲裁记录 */ + private ArbitrateRecord arbitrateRecord; + + /** 身份类型 */ +// @Excel(name = "身份类型") + private int identityType; + /** + * 申请人主体信息 + */ + /** 姓名 */ + @Excel(name = "申请人主体信息-申请人(机构)",width = 26) + private String name; + /** 身份证号 */ + @Excel(name = "申请人主体信息-代码",width = 26) + private String identityNum; + /** 申请人主体信息-法定代表人 */ + @Excel(name = "申请人主体信息-法定代表人",width = 26) + private String compLegalPerson; + /** 申请人主体信息-法定代表人 */ + @Excel(name = "申请人主体信息-法定代表人职位",width = 26) + private String compLegalperPost; + /** + * 申请人主体信息-申请人(机构)id + */ + private String nameId; + + /** 联系电话 */ + @Excel(name = "申请人主体信息-联系电话",width = 26) + private String contactTelphone; + /** 联系地址 */ + @Excel(name = "申请人主体信息-联系地址",width = 26) + private String contactAddress; + /** 单位电话 */ + @Excel(name = "申请人主体信息-单位电话",width = 26) + private String workTelphone; + /** 单位地址 */ + @Excel(name = "申请人主体信息-单位地址",width = 26) + private String workAddress; + + /** 申请人住所 */ + @Excel(name = "申请人主体信息-住所",width = 26) + private String residenAffiliAppli; + + /** 申请人邮箱 */ + @Excel(name = "申请人主体信息-邮箱",width = 26) + private String email; + /** 代理人姓名 */ + @Excel(name = "申请人主体信息-代理人姓名",width = 26) + private String nameAgent; + /** 身份证号 */ + @Excel(name = "申请人主体信息-代理人身份证号",width = 26) + private String identityNumAgent; + + /** 联系电话 */ + @Excel(name = "申请人主体信息-代理人联系电话",width = 26) + private String contactTelphoneAgent; + /** 联系地址 */ + @Excel(name = "申请人主体信息-代理人联系地址",width = 26) + private String contactAddressAgent; + /** 申请人代理人职称 */ + @Excel(name = "申请人主体信息-代理人职称",width = 26) + private String appliAgentTitle; + /** + * 被申请人主体信息 + */ + /** 姓名 */ + @Excel(name = "被申请人主体信息-申请人姓名",width = 26) + private String debtorName; + /** 身份证号 */ + @Excel(name = "被申请人主体信息-身份证号",width = 26) + private String debtorIdentityNum; + /** 被申请人主体信息-性别 */ + @Excel(name = "被申请人主体信息-性别",width = 26,combo= {"男","女"},readConverterExp = "0=男,1=女") + private String responSex; + /** 被申请人主体信息-出生年月日 */ + @Excel(name = "被申请人主体信息-出生年月日",width = 26) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date responBirth; + /** 联系电话 */ + @Excel(name = "被申请人主体信息-联系电话",width = 26) + private String debtorContactTelphone; + /** 联系地址 */ + @Excel(name = "被申请人主体信息-联系地址",width = 26) + private String debtorContactAddress; + /** 被申请人住所 */ + @Excel(name = "被申请人主体信息-住所",width = 26) + private String residenAffiliRespon; + /** 单位电话 */ + @Excel(name = "被申请人主体信息-单位电话",width = 26) + private String debtorWorkTelphone; + /** 单位地址 */ + @Excel(name = "被申请人主体信息-单位地址",width = 26) + private String debtorWorkAddress; + /** 邮箱 */ + @Excel(name = "被申请人主体信息-邮箱",width = 26) + private String debtorEmail; + + /** 代理人姓名 */ + @Excel(name = "被申请人主体信息-代理人姓名",width = 26) + private String debtorNameAgent; + /** 身份证号 */ + @Excel(name = "被申请人主体信息-代理人身份证号",width = 26) + private String debtorIdentityNumAgent; + /** 联系电话 */ + @Excel(name = "被申请人主体信息-代理人联系电话",width = 26) + private String debtorContactTelphoneAgent; + /** 联系地址 */ + @Excel(name = "被申请人主体信息-代理人联系地址",width = 26) + private String debtorContactAddressAgent; + /** + * 申请机构id + */ + private String applicationOrganId; + /** + * 版本号 + */ + private Integer version; + /** + * 修改案件的提交状态,0-未提交,1-已提交,2-同意,3-拒绝,4-撤销 + */ + private Integer updateSubmitStatus; + /** 合同名称 */ + private String contractName; + /** + * 事实和理由 + */ + private String facts; + /** + * 合同甲方 + */ + private String partyA; + /** + * 利率 + */ + private String interestRate; + /** + * 待还金额 + */ + private String outstandingMoney; + /** + * 调解达成协议内容 + */ + private String mediationAgreement; + /** + * 金融消费纠纷基本情况 + */ + private String disputes; + /** + * 贷款类型 + */ + private String loanType; + /** + * 贷款期限 + */ + private String loanTerm; + /** + * 本案争议焦点 + */ + private String caseFocus; + /** + * 本案事实 + */ + private String caseFacts; + /** + * 被申请人对上述材料的质证意见 + */ + private String respondentOpinion; + /** + * 申请人对上述材料的质证意见 + */ + private String applicantOpinion; + /** + * 批号 + */ + private Integer batchNumber; + /** + * 自定义字段 + */ + private List columnValues; + /** + * 待办状态,0待办,1已办 + */ + private Integer pendingStatus; + /** e签宝流程id */ + private String signFlowId;; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplicationPay.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplicationPay.java new file mode 100644 index 0000000..7e85b3c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplicationPay.java @@ -0,0 +1,23 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.annotation.Excel; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class CaseApplicationPay { + /** 案件编号 */ + private String caseNum; + /** 案件标的 */ + private BigDecimal caseSubjectAmount; + /** 仲裁应缴费用 */ + private BigDecimal feePayable; + /** 案件状态 */ + private Integer caseStatus; + /**申请人 */ + private String caseAppName; + /**被申请人 */ + private String caseResName; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java new file mode 100644 index 0000000..e39680a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java @@ -0,0 +1,58 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CaseAttach { + /** + * 附件id + */ + private Integer annexId; + /** + * 案件申请id + */ + private Long caseAppliId; + /** + * 案件记录id + */ + private Long caseAppliLogId; + /** + * 附件名称 + */ + private String annexName; + /** + * 附件路径 + */ + private String annexPath; + /** + * 附件类型,立案申请书(1)、申请人证据材料(2)、仲裁文书(3)、案件视频(4)、身份证件(5)、被申请人证据材料 (6)、庭审笔录(7)、缴费凭证(8)' + */ + private Integer annexType; + /** + * 备注 + */ + private String note; + /** + * 用户id + */ + private Long userId; + /** + * 用户账户 + */ + private String userName; + /** + * 印章状态(0未启用,1已启用) + */ + private Integer sealStatus; + /** + * 是否是证据上传,0-否,1-是 + */ + private Integer isBatchUpload; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseEvidenceDirectory.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseEvidenceDirectory.java new file mode 100644 index 0000000..57c29de --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseEvidenceDirectory.java @@ -0,0 +1,60 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CaseEvidenceDirectory extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 父id + */ + private Long parentId; + + /** + * 证据名称 + */ + private String evidenceName; + + /** + * 附件id + */ + private Integer annexId; + + /** + * 级数 + */ + private Integer series; + + /** + * 案件id + */ + private Long caseId; + + /** 子目录 */ + private List children = new ArrayList<>(); + + /** + * 附件名称 + */ + private String annexName; + /** + * 附件路径 + */ + private String annexPath; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseIds.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseIds.java new file mode 100644 index 0000000..f7d9696 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseIds.java @@ -0,0 +1,9 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import lombok.Data; + +import java.util.List; +@Data +public class CaseIds { + private List ids; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java new file mode 100644 index 0000000..0441575 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java @@ -0,0 +1,145 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +public class CaseLogRecord extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 案件申请id */ + private Long caseAppliId; + /** 案件节点 */ + private Integer caseNode; + + /** 案件节点时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date caseNodeTime; + + /** 备注 */ + private String notes; + + /** 案件编号 */ + private String caseNum; + /** + * 展示的内容 + */ + private String content; + /** + * 用户昵称 + */ + private String createNickName; + + /** + * 角色名称 + */ + private String roleName; + /** + * 下一个节点角色名称 + */ + private String nextRoleName; + + public String getNextRoleName() { + return nextRoleName; + } + + public void setNextRoleName(String nextRoleName) { + this.nextRoleName = nextRoleName; + } + + /** + * 节点名称 + */ + private String caseNodeName; + + public String getCaseNodeName() { + return caseNodeName; + } + + public void setCaseNodeName(String caseNodeName) { + this.caseNodeName = caseNodeName; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + + + + public String getCaseNum() { + return caseNum; + } + + public void setCaseNum(String caseNum) { + this.caseNum = caseNum; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCaseAppliId() { + return caseAppliId; + } + + public void setCaseAppliId(Long caseAppliId) { + this.caseAppliId = caseAppliId; + } + + public Integer getCaseNode() { + return caseNode; + } + + public void setCaseNode(int caseNode) { + this.caseNode = caseNode; + } + + public Date getCaseNodeTime() { + return caseNodeTime; + } + + public void setCaseNodeTime(Date caseNodeTime) { + this.caseNodeTime = caseNodeTime; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public void setCaseNode(Integer caseNode) { + this.caseNode = caseNode; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getCreateNickName() { + return createNickName; + } + + public void setCreateNickName(String nickName) { + this.createNickName = nickName; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseNumRule.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseNumRule.java new file mode 100644 index 0000000..327036f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseNumRule.java @@ -0,0 +1,28 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +@Data +public class CaseNumRule extends BaseEntity { + /** ID */ + private Long id; + /** 类型 */ + private Integer ruleType; + /** 前缀 */ + private String prefixstr; + /** 时间格式 */ + private Integer dateFormat; + /** 机构名称 */ + private String deptName; + /** 机构名称首字符拼写 */ + private String deptNameFirchar; + /** 当前编号 */ + private String currentNum; + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java new file mode 100644 index 0000000..74f1f77 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java @@ -0,0 +1,45 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.Date; + +@Data +public class CasePaymentRecord { + private static final long serialVersionUID = 1L; + /** + * 主键 + */ + private Integer id; + /** + * 案件id + */ + private Long caseId; + /** + * 订单号 + */ + private String orderNumber; + /** + * 支付状态(0未支付,1已支付) + */ + private Integer paymentStatus; + /** + * 支付时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date paymentTime; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + /** + * 支付方式 0线上支付,1线下支付 + */ + private Integer payType; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/DeptIdentify.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/DeptIdentify.java new file mode 100644 index 0000000..3f5df95 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/DeptIdentify.java @@ -0,0 +1,61 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.Date; +@Data +public class DeptIdentify extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 部门id */ + private Long deptId; + /** 用户id */ + private Long userId; + /** 机构名称 */ + private String identifyName; + /** 认证状态 */ + private Integer identifyStatus; + /** 认证时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date identifyDate; + /** 是否启用 */ + private Integer isUse; + /** 经办人姓名 */ + private String operName; + /** 经办人用户名 */ + private String operUserName; + /** 经办人手机号 */ + private String operPhone; + + /** 机构账号ID */ + private String orgId; + /** 认证授权流程ID */ + private String authFlowId; + + /** 部门认证链接 */ + private String identifyUrl; + + /** 机构信用代码 */ + private String creditCode; + + /** 法人姓名 */ + private String legalPerName; + + /** 法人手机号 */ + private String legalPerPhone; + + /** 机构类型(1 仲裁机构) */ + private Integer identifyType; + + /** 机构邮箱 */ + private String identifyEmail; + + + /** 删除标志(0代表存在 2代表删除) */ + private Integer delFlag; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/FatchRule.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/FatchRule.java new file mode 100644 index 0000000..34fb7d1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/FatchRule.java @@ -0,0 +1,41 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.Date; + +/** + * 抓取规则 + */ +@Data +public class FatchRule extends BaseEntity { + private static final long serialVersionUID = 1L; + + private Long id; + private String batchNumber; + private String fileName; + private String startContent; + private String endContent; + private String column; + private String columnName; + private Integer isDefault; + + private Long templateId; + private String databaseName; + /** + * 顺序,开始字段重复时,指定抓取第几个 + */ + private Integer startContentRepeatOrder; + /** + * 结束字段重复时指定的顺序,默认1,只能>0填正整数 + */ + private Integer endContentRepeatOrder; + /** + * 抓取方向,默认0,0-从前往后抓取,1-从后往前抓取 + */ + private Integer fatchOrder; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/IdentityAuthentication.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/IdentityAuthentication.java new file mode 100644 index 0000000..441e2f2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/IdentityAuthentication.java @@ -0,0 +1,148 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.Date; +@Data +public class IdentityAuthentication extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 姓名 */ + private String name; + /** 身份证号 */ + private String identityNo; + /** + * 短信验证码 + */ + private String VerifyCode; + private String passWord; + private String phone; + /** + * 邮箱 + */ + private String email; + /** + * 身份证地址 + */ + private String idAddress; + /** 认证时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date certificationTime; + /** 认证状态 */ + private Integer certificationStatus; + + public Integer getCertificationStatus() { + return certificationStatus; + } + + public void setCertificationStatus(Integer certificationStatus) { + this.certificationStatus = certificationStatus; + } + + /** 认证状态名称 */ + private String certificationStatusName; + + public String getCertificationStatusName() { + return certificationStatusName; + } + + public void setCertificationStatusName(String certificationStatusName) { + this.certificationStatusName = certificationStatusName; + } + + /** 用户ID */ + private Long userId; + /** 用户账号 */ + private String userName; + /** + * 用户昵称 + */ + private String nickName; + + /** EID商户id */ + private String merchantId; + + /** EidToken */ + private String eidToken; + /** 请求 ID */ + private String requestId; + + public String getMerchantId() { + return merchantId; + } + + public void setMerchantId(String merchantId) { + this.merchantId = merchantId; + } + + public String getEidToken() { + return eidToken; + } + + public void setEidToken(String eidToken) { + this.eidToken = eidToken; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIdentityNo() { + return identityNo; + } + + public void setIdentityNo(String identityNo) { + this.identityNo = identityNo; + } + + public Date getCertificationTime() { + return certificationTime; + } + + public void setCertificationTime(Date certificationTime) { + this.certificationTime = certificationTime; + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ReservedConference.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ReservedConference.java new file mode 100644 index 0000000..fad99e3 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/ReservedConference.java @@ -0,0 +1,63 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * @author wangqiong + * @description 预定会议 + * @Version 1.0 + * @date 2023-11-09 16:51 + */ +@Data +public class ReservedConference { + /** + * id + */ + private Long id; + /** + * 用户id + */ + private Long userId; + /** + * 用户名 + */ + private String userName; + /** + * 案件id + */ + private Long caseId; + /** + * 房间号 + */ + private long roomId; + /** + * 预定会议开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleStartTime; + /** + * 预定会议结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleEndTime; + /** + * 是否超过5分钟 + */ + private Boolean isBeforeFiveMinutes; + + + public ReservedConference() { + } + + public ReservedConference(Long caseId, Long userId, long roomId, Date scheduleStartTime, Date scheduleEndTime) { + this.caseId = caseId; + this.userId = userId; + this.roomId = roomId; + this.scheduleStartTime = scheduleStartTime; + this.scheduleEndTime = scheduleEndTime; + + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealManage.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealManage.java new file mode 100644 index 0000000..3b835d8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealManage.java @@ -0,0 +1,48 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +@Data +public class SealManage extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * ID + */ + private Long id; + + /** + * 机构关联id + */ + private Long identifyId; + + /** + * 印章名称 + */ + private String sealName; + + + /** + * 印章id + */ + private String sealId; + /** + * 附件id + */ + private Integer annexId; + + /** + * 印章审核状态(0未通过,1通过) + */ + private Integer sealStatus; + /** + * 印章使用状态(0禁用,1启用) + */ + private Integer isUse; + + /** + * 附件路径 + */ + private String annexPath; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealSignRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealSignRecord.java new file mode 100644 index 0000000..e4e0267 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SealSignRecord.java @@ -0,0 +1,64 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SealSignRecord extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + /** 文件id */ + private String fileid; + /** 文件名称 */ + private String filename; + /** 流程id */ + private String signFlowid; + /** 签名人账户 */ + private String pensonAccount; + /** 签名人姓名 */ + private String pensonName; + /** 机构名称 */ + private String orgnizeName; + /** 机构经办人 */ + private String orgnizeNamePsnAccount; + /** 机构经办人名称 */ + private String orgnizeNamepsnName; + + String fileDownloadUrl; + /** 流程状态 */ + private Integer signFlowStatus; + /** 签名状态 */ + private Integer psnsignStatus; + /** 用印状态 */ + private Integer orgsignStatus; + + /** 签名链接 */ + private String signUrl; + + /** 用印链接 */ + private String sealUrl; + + private Long caseAppliId; + + /** 签名位置页数 */ + private String positionPagepsn; + /** 签名位置x坐标 */ + private double positionXpsn; + /** 签名位置y坐标 */ + private double positionYpsn; + /** 印章位置页数 */ + private String positionPageorg; + /** 印章位置x坐标 */ + private double positionXorg; + /** 印章位置y坐标 */ + private double positionYorg; + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SendMailRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SendMailRecord.java new file mode 100644 index 0000000..de3e11e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SendMailRecord.java @@ -0,0 +1,115 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +public class SendMailRecord extends BaseEntity { + private static final long serialVersionUID = 1L; + + private Long id; + /** 案件申请id */ + private Long caseId; + + /** + * 邮件名称 + */ + private String mailName; + /** + * 邮件内容 + */ + private String mailContent; + /** + * 邮件地址 + */ + private String mailAddress; + /** + * 发送时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date sendTime; + + /** 案件编号 */ + private String caseNum; + + + + /** 发送状态 */ + private Integer sendStatus; + + + + public Integer getSendStatus() { + return sendStatus; + } + + public void setSendStatus(Integer sendStatus) { + this.sendStatus = sendStatus; + } + + + public String getCaseNum() { + return caseNum; + } + + public void setCaseNum(String caseNum) { + this.caseNum = caseNum; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCaseId() { + return caseId; + } + + public void setCaseId(Long caseId) { + this.caseId = caseId; + } + + public String getMailName() { + return mailName; + } + + public void setMailName(String mailName) { + this.mailName = mailName; + } + + public String getMailContent() { + return mailContent; + } + + public void setMailContent(String mailContent) { + this.mailContent = mailContent; + } + + public String getMailAddress() { + return mailAddress; + } + + public void setMailAddress(String mailAddress) { + this.mailAddress = mailAddress; + } + + public Date getSendTime() { + return sendTime; + } + + public void setSendTime(Date sendTime) { + this.sendTime = sendTime; + } + + + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SmsSendRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SmsSendRecord.java new file mode 100644 index 0000000..9c36063 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/SmsSendRecord.java @@ -0,0 +1,45 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SmsSendRecord extends BaseEntity { + /** + * ID + */ + private Long id; + /** + * 案件申请id + */ + private Long caseId; + /** + * 案件编号 + */ + private String caseNum; + /** + * 手机号 + */ + private String phone; + /** + * 发送时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date sendTime; + /** + * 发送内容 + */ + private String sendContent; + + /** + * 发送状态 + */ + private Integer sendStatus; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManage.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManage.java new file mode 100644 index 0000000..5f342ed --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManage.java @@ -0,0 +1,57 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.List; + +@Data +public class TemplateManage extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * ID + */ + private Long id; + + /** + * 机构关联id + */ + private Long identifyId; + + /** + * 模板名称 + */ + private String temName; + + /** + * 模板类型(1裁决书) + */ + private Integer temType; + /** + * 模板格式 + */ + private String temFormat; + /** + * 文件名 + */ + private String fileName; + /** + * 原模板路径 + */ + private String temOrigPath; + /** + * 修订后模板路径 + */ + private String temRevisPath; + /** + * 删除标志(0代表存在 2代表删除) + */ + private Integer delFlag; + /** + * 机构关联id + */ + private String identifyName; + + List fatchRules; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManual.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManual.java new file mode 100644 index 0000000..82fa6e4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/TemplateManual.java @@ -0,0 +1,33 @@ +package com.ruoyi.wisdomarbitrate.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; + +@Data +public class TemplateManual { + /** + * ID + */ + private Long id; + + /** + * 模板名称 + */ + private String name; + + /** + * 模板内容,用{}作为占位符动态替换其内容 + */ + private String content; + + /** + * 模板类型,1-裁决内容,2-调解协议,3-金融消费纠纷基本情况 + */ + private Integer type; + + /** + * 删除标志(0代表存在 2代表删除) + */ + private Integer delFlag; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseApplicationLogDTO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseApplicationLogDTO.java new file mode 100644 index 0000000..b66aa79 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseApplicationLogDTO.java @@ -0,0 +1,255 @@ +package com.ruoyi.wisdomarbitrate.domain.dto; + +import lombok.Data; + +import java.util.Date; + +/** + * @author wangqiong + * @description 案件日志 + * @date 2023-11-17 14:01 + */ +@Data +public class CaseApplicationLogDTO { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 案件编号 + */ + private String caseNum; + + /** + * 案件标的 + */ + private Double caseSubjectAmount; + + /** + * 立案日期 + */ + private Date registerDate; + + /** + * 仲裁方式,视频仲裁(1)、书面仲裁(2) + */ + private Long arbitratMethod; + + /** + * 案件状态,立案申请(0)、待立案审查(1)、 待缴费(2)、待缴费确认(3)、 待案件质证(4)、 + */ + private Integer caseStatus; + + /** + * 开庭日期 + */ + private Date hearDate; + + /** + * 申请人仲裁请求及事实和理由 + */ + private String arbitratClaims; + + /** + * 借款开始日期 + */ + private Date loanStartDate; + + /** + * 借款结束日期 + */ + private Date loanEndDate; + + /** + * 申请人主张欠本金 + */ + private Double claimPrinciOwed; + + /** + * 申请人主张欠利息 + */ + private Double claimInterestOwed; + + /** + * 申请人主张违约金 + */ + private Double claimLiquidDamag; + + /** + * 仲裁应缴费用 + */ + private Double feePayable; + + /** + * 开始在线视频时间 + */ + private Date beginVideoDate; + + /** + * 在线视频人员 + */ + private String onlineVideoPerson; + + /** + * 合同编号 + */ + private String contractNumber; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新者 + */ + private String updateBy; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 创建者 + */ + private String createBy; + + /** + * 仲裁员id + */ + private String arbitratorId; + + /** + * 仲裁员名称 + */ + private String arbitratorName; + + /** + * 已确认组庭的仲裁员id + */ + private String pendedTrialArbitorid; + + /** + * 是否指派仲裁员,1是,2否 + */ + private Integer pendingAppointArbotrar; + + /** + * 案件名称 + */ + private String caseName; + + /** + * 案件描述 + */ + private String caseDescribe; + + /** + * 仲裁结果 + */ + private String caseResult; + + /** + * 是否同意组庭,0否,1是 + */ + private Integer isAgreePendTral; + + /** + * 是否有异议需要举证,1是,0否 + */ + private Integer objectionAddEviden; + + /** + * 是否需要开庭审理,1是,0否 + */ + private Integer openCourtHear; + + /** + * paid_expenses + */ + private Double paidExpenses; + + /** + * 裁决书URL + */ + private String filearbitraUrl; + + /** + * 支付方式(0线上支付,1线下支付) + */ + private String payType; + + /** + * 申请人请求仲裁庭裁决 + */ + private String requestRule; + + /** + * 是否仲裁反请求,1是,0否 + */ + private Integer adjudicaCounter; + + /** + * 是否财产保全申请,1是,0否 + */ + private Integer properPreser; + + /** + * 是否管辖异议申请,1是,0否 + */ + private Integer objectiJuris; + + /** + * 被申请人是否缺席,1是,0否 + */ + private Integer isAbsence; + + /** + * 被申请人质证意见 + */ + private String responCrossOpin; + + /** + * 申请人质证意见 + */ + private String applicaCrossOpin; + + /** + * 被申请人的答辩意见 + */ + private String responDefenOpini; + + /** + * 申请人是否缺席,1是,0否 + */ + private Integer appliIsAbsen; + + /** + * 是否锁定,0-否,1-是 + */ + private Integer lockStatus; + + /** + * 视频会议房间号id,多个用逗号拼接 + */ + private String roomId; + + /** + * 是否导入,0手动录入,1导入,默认0 + */ + private Integer importFlag; + + /** + * 版本号 + */ + private Long version; + + /** + * 修改案件的提交状态,0-未提交,1-已提交,2-同意,3,拒绝 + */ + private Integer updateSubmitStatus; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseConfirmPayDTO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseConfirmPayDTO.java new file mode 100644 index 0000000..ae00cb0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseConfirmPayDTO.java @@ -0,0 +1,29 @@ +package com.ruoyi.wisdomarbitrate.domain.dto; + +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 案件确认缴费传入对象 + */ +@Data +public class CaseConfirmPayDTO { + /** + * 案件ids + */ + @NotNull(message = "案件id不能为空") + private List caseIds; + + /** + * 支付方式 0线上支付,1线下支付 + */ + private Integer payType; + /** + * 缴费凭证 + */ + private List payOrderList; + +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseEvidenceDTO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseEvidenceDTO.java new file mode 100644 index 0000000..b412ede --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CaseEvidenceDTO.java @@ -0,0 +1,49 @@ +package com.ruoyi.wisdomarbitrate.domain.dto; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import lombok.Data; + +import java.util.List; + +/** + * 案件质证传入对象 + */ +@Data +public class CaseEvidenceDTO { + /** + * 案件id + */ + private Long caseId; + + /** + * 是否有异议需要举证,1是,0否 + */ + private Integer objectionAddEviden; + + /** + * 是否需要开庭审理,1是,0否 + */ + private Integer openCourtHear; + + /** + * 是否指派仲裁员,1是,2否 + */ + private Integer pendingAppointArbotrar; + /** 是否仲裁反请求 */ + private Integer adjudicaCounter; + /** + * 仲裁反请求原因 + */ + private String adjudicaCounterReason; + /** 是否管辖异议申请 */ + private Integer objectiJuris; + + /** 被申请人是否书面审理 */ + private Integer respondentIsWrittenHear; + + + /** + * 案件仲裁员 + */ + private List arbitrators; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java new file mode 100644 index 0000000..0c92a68 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java @@ -0,0 +1,42 @@ +package com.ruoyi.wisdomarbitrate.domain.dto; + +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import lombok.Data; + +import java.util.List; + +/** + * 案件缴费传入对象 + */ +@Data +public class CasePayDTO { + /** + * 案件id + */ + private List caseIds; + + /** + * 订单金额 单位:分 + */ + private int totalFee; + /** + * 交易类型 native(扫码) / jsapi(小程序) / app / h5 + */ + private String tradeType; + /** + * 支付方式 wxpay(微信) alipay(支付宝) + */ + private String platform; + /** + * 支付方式 0线上支付,1线下支付 + */ + private Integer payType; + /** + * 缴费凭证 + */ + private List payOrderList; + /** + * 批号 + */ + private String batchNumber; +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ArchivesDetailVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ArchivesDetailVO.java new file mode 100644 index 0000000..dfe4abc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ArchivesDetailVO.java @@ -0,0 +1,24 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.mapper.CaseLogRecordMapper; +import lombok.Data; + +import java.util.List; + +@Data +public class ArchivesDetailVO { + /** + * 案件信息 + */ + private CaseApplication caseApplication; + /** + * 案件日志信息 + */ + private List caseLogRecordList; + /** + * 快递信息 + */ + private List logisticsInfoVOList; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/BookSendVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/BookSendVO.java new file mode 100644 index 0000000..790e705 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/BookSendVO.java @@ -0,0 +1,26 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BookSendVO { + /** + * 案件id + * 申请人邮箱 + * 被申请人邮箱 + * 申请人快递编号 + * 被申请人快递编号 + */ + private Long id; + private String appEmail; + private String resEmail; + private String apptrackingNum; + private String restrackingNum; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java new file mode 100644 index 0000000..b67c73f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java @@ -0,0 +1,67 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CaseDetailVO { + /** + * ID + */ + private Long id; + /** + * 案件编号 + */ + private String caseNum; + /** + * 申请人姓名 + */ + private String applicantName; + /** + * 被申请人姓名 + */ + private String respondentName; + /** + * 借款开始日期 + */ + private Date loanStartDate; + /** + * 借款结束日期 + */ + private Date loanEndDate; + /** + * 案件标的 + */ + private BigDecimal caseSubjectAmount; + /** + * 申请人主张欠本金 + */ + private BigDecimal claimPrinciOwed; + /** + * 申请人主张欠利息 + */ + private BigDecimal claimInterestOwed; + /** + * 申请人主张违约金 + */ + private BigDecimal claimLiquidDamag; + + /** + * 证据材料 + */ + private List evidenceMaterialList; + /** + * 当前登录人身份类型 + */ + private Integer identityType; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceDirectoryVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceDirectoryVO.java new file mode 100644 index 0000000..51e0d62 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceDirectoryVO.java @@ -0,0 +1,200 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.wisdomarbitrate.domain.CaseEvidenceDirectory; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 目录查询返回类 + */ +public class CaseEvidenceDirectoryVO implements Serializable { + private static final long serialVersionUID = 1L; + /** + * id + */ + private Long id; + /** + * 父id + */ + private Long parentId; + + /** + * 证据名称 + */ + private String evidenceName; + + /** + * 附件id + */ + private Integer annexId; + + /** + * 级数 + */ + private Integer series; + + /** + * 案件id + */ + private Long caseId; + + /** 子目录 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + /** + * 附件名称 + */ + private String annexName; + /** + * 附件路径 + */ + private String annexPath; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date createTime; + /** + * 创建者 + */ + private String createBy; + /** + * 更新者 + */ + private String updateBy; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date updateTime; + public CaseEvidenceDirectoryVO(){ + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public String getEvidenceName() { + return evidenceName; + } + + public void setEvidenceName(String evidenceName) { + this.evidenceName = evidenceName; + } + + public Integer getAnnexId() { + return annexId; + } + + public void setAnnexId(Integer annexId) { + this.annexId = annexId; + } + + public Integer getSeries() { + return series; + } + + public void setSeries(Integer series) { + this.series = series; + } + + public Long getCaseId() { + return caseId; + } + + public void setCaseId(Long caseId) { + this.caseId = caseId; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + 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 getAnnexName() { + return annexName; + } + + public void setAnnexName(String annexName) { + this.annexName = annexName; + } + + + public void setAnnexPath(String annexPath) { + this.annexPath = annexPath; + } + + + public CaseEvidenceDirectoryVO(CaseEvidenceDirectory caseEvidenceDirectory) { + this.id = caseEvidenceDirectory.getId(); + this.parentId = caseEvidenceDirectory.getParentId(); + this.evidenceName = caseEvidenceDirectory.getEvidenceName(); + this.annexId = caseEvidenceDirectory.getAnnexId(); + this.series = caseEvidenceDirectory.getSeries(); + this.caseId = caseEvidenceDirectory.getCaseId(); + this.children = caseEvidenceDirectory.getChildren(); + this.createTime = caseEvidenceDirectory.getCreateTime(); + this.createBy = caseEvidenceDirectory.getCreateBy(); + this.updateBy = caseEvidenceDirectory.getUpdateBy(); + this.updateTime = caseEvidenceDirectory.getUpdateTime(); + this.annexName = caseEvidenceDirectory.getAnnexName(); + this.annexPath = caseEvidenceDirectory.getAnnexPath(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java new file mode 100644 index 0000000..da1e6f2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java @@ -0,0 +1,40 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +@Data +public class CaseEvidenceVO { + /** + * 案件id + */ + private Long id; + /** + * 案件编号 + */ + private String caseNum; + /** + * 申请人姓名 + */ + private String applicantName; + /** + * 被申请人姓名 + */ + private String respondentName; + /** + * 案件状态 + */ + private Integer caseStatus; + /** + * 房间号 + */ + private Long roomId; + /** + * 开庭时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleStartTime; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CasePayListVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CasePayListVO.java new file mode 100644 index 0000000..6c6263e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CasePayListVO.java @@ -0,0 +1,26 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplicationPay; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Data +public class CasePayListVO { + /** + * 订单总金额 + */ + private BigDecimal totalFee; + + /** + * 案件总条数 + */ + private int CaseTotal; + + /** + * 案件订单列表 + */ + private List caseApplicationList; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ColumnValue.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ColumnValue.java new file mode 100644 index 0000000..16bb0c1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ColumnValue.java @@ -0,0 +1,45 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.Data; + +/** + * 动态配置字段表 + */ +@Data +public class ColumnValue { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 字段,同一个批号,column不可重复 + */ + private String column; + + /** + * 字段名 + */ + private String name; + + /** + * 字段值 + */ + private String value; + + /** + * 案件id + */ + private Long caseId; + /** + * 是否为自定义字段,0-否,1-是 + */ + private Integer isDefault; + /** + * 案件日志表id + */ + private Long caseAppliLogId; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CompareCaseVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CompareCaseVO.java new file mode 100644 index 0000000..496318f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CompareCaseVO.java @@ -0,0 +1,37 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 案件前后对比 + * @author wangqiong + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CompareCaseVO { + /** + * 该版本前的案件 + */ + private CaseApplication beforeCase; + /** + * 该版本后的案件 + */ + private CaseApplication afterCase; + /** + * 变化字段,多个用,拼接 + */ + private String changeColumn; + /** + * 自定义字段变化字段,多个用,拼接 + */ + private String columnValueChangeColumn; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/LogisticsInfoVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/LogisticsInfoVO.java new file mode 100644 index 0000000..480a96a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/LogisticsInfoVO.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.Data; + +@Data +public class LogisticsInfoVO { + /** + * 案件关联人身份类型 + */ + private Integer identityType; + + /** + * 物流信息 + */ + private String logisticsInfo; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ReservedConferenceVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ReservedConferenceVO.java new file mode 100644 index 0000000..75851a9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ReservedConferenceVO.java @@ -0,0 +1,47 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * @author wangqiong + * @description 预约会议 + * @date 2023-11-08 11:05 + */ +@Data +public class ReservedConferenceVO { + /** + * 用户id + */ + + private String ownerId; + /** + * 房间号id + */ + private Long roomId; + /** + * 会议开始时间 + */ + @NotNull(message = "会议开始时间不能为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleStartTime; + /** + * 会议结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleEndTime; + /** + * 案件id + */ + @NotNull(message = "案件id不能为空") + private Long caseId; + /** + * html内容 + */ + private String htmlContent; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SealListVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SealListVO.java new file mode 100644 index 0000000..785e10a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SealListVO.java @@ -0,0 +1,35 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +@Data +public class SealListVO { + /** 主键 */ + private Long id; + /** 印章id */ + private String sealId; + /** 印章名称 */ + private String sealName; + /** + * 印章审核状态(0未通过,1通过) + */ + private Integer sealStatus; + /** + * 印章使用状态(0禁用,1启用) + */ + private Integer isUse; + /** + * 附件id + */ + private Integer annexId; + /** + * 附件路径 + */ + private String annexPath; + /** + * 附件类型 + */ + private Integer annexType; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SendRoomNoMessageVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SendRoomNoMessageVO.java new file mode 100644 index 0000000..d39332a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/SendRoomNoMessageVO.java @@ -0,0 +1,29 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @author wangqiong + * @description 发送房间号短信入参类 + * @date 2023-10-10 15:20 + */ +@Data +public class SendRoomNoMessageVO implements Serializable { + private static final long serialVersionUID = 1L; + @NotNull(message = "案件id不能为空") + private Long id; + @NotEmpty(message = "房间号不能为空") + private String roomNo; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleStartTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduleEndTime; + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/TemplateFatchRule.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/TemplateFatchRule.java new file mode 100644 index 0000000..b194085 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/TemplateFatchRule.java @@ -0,0 +1,17 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.Data; + +/** + * 模板抓取规则关联表 + */ +@Data +public class TemplateFatchRule { + private static final long serialVersionUID = 1L; + private Long id; + private Long templateId; + private Long fatchRuleId; + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ToDoCount.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ToDoCount.java new file mode 100644 index 0000000..7817936 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/ToDoCount.java @@ -0,0 +1,34 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.Data; + +/** + * @author wangqiong + * @description 待办数量 + * @date 2023-10-17 09:48 + */ +@Data +public class ToDoCount { + + private int caseApply=0; // 立案申请 + private int caseApplyCheck=0; // 待立案审查 + private int caseApplyPay=0; // 待缴费 + private int caseApplyPayCheck=0; // 待缴费确认 + private int caseApplyEvidence=0; //待案件质证 + private int caseApplyGroupCheck=0; // 待组庭审核 + private int caseApplyGroupConfirm=0; // 待组庭确定 +// private int caseApplyGroupNotice; + private int caseApplyArbitrateWay=0; // 待审核仲裁方式 + private int caseApplyGroupOnline=0; // 待开庭审理 + private int caseApplyGroupOffline=0; // 待书面审理 + private int caseApplyAward=0; // 待生成仲裁文书 + private int caseApplyAwardCheck=0; // 待核验仲裁文书 + private int caseApplyAwardConfirm=0; // 待审核仲裁文书 + private int caseApplyAwardSign=0; // 待仲裁文书签名 + private int caseApplyAwardSeal=0; // 待仲裁文书用印 + private int caseApplyAwardSend=0; // 待仲裁文书送达 + private int caseApplyStored=0; // 待案件归档 + private int caseApplyArchived=0; // 已归档 + private int updateOnlineHearDate=0; // 待修改开庭时间 + private int arbitratorApplyAwardConfirm=0; // 待仲裁员审核仲裁文书 +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/UpdateSubmitVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/UpdateSubmitVO.java new file mode 100644 index 0000000..5c64d69 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/UpdateSubmitVO.java @@ -0,0 +1,38 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 修改案件提交至秘书 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UpdateSubmitVO { + /** + * 案件id + */ + private Long caseId; + /** + * 版本号 + */ + private Integer version; + /** + * 修改案件的提交状态,0-未提交,1-已提交,2-撤销,3-同意已修改的案件,4-拒绝已修改的案件,5-同意撤销,6-拒绝撤销 + */ + private Integer updateSubmitStatus; + /** + * 是否同意,0-否,1-是 + */ + private Integer isAgree; + /** + * 拒絕原因 + */ + private String reason; + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/WeChatUserVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/WeChatUserVO.java new file mode 100644 index 0000000..a2b20cc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/WeChatUserVO.java @@ -0,0 +1,63 @@ +package com.ruoyi.wisdomarbitrate.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * 微信小程序用户注册登录 + */ +@Data +public class WeChatUserVO { + /** + * id + */ + private Long id; + /** + * 微信用户唯一标识 + */ + private String openId; + /** + * 微信授权的code,用户登录凭证 + */ + private String wxCode; + + /** + * 姓名 + */ + @NotEmpty(message = "姓名不能为空") + private String name; + /** 身份证号 */ + @NotEmpty(message = "身份证号不能为空") + private String identityNo; + /** 认证时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date certificationTime; + /** 认证状态 */ + private Integer certificationStatus; + private String password; + /** + * 电话 + */ + @NotEmpty(message = "电话不能为空") + private String phone; + /** + * 验证码 + */ + private String verifyCode; + /** + * 邮箱 + */ + @NotEmpty(message = "邮箱不能为空") + private String email; + /** + * 创建人 + */ + private String createBy; + private String updateBy; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitrateRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitrateRecordMapper.java new file mode 100644 index 0000000..c4aaa18 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitrateRecordMapper.java @@ -0,0 +1,17 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.ArbitrateRecord; +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; + +import java.util.List; + +public interface ArbitrateRecordMapper { + int insertArbitrateRecord(ArbitrateRecord arbitrateRecord); + + int updataArbitrateRecord(ArbitrateRecord arbitrateRecord); + + ArbitrateRecord selectArbitrateRecord(ArbitrateRecord arbitrateRecord); + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitratorMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitratorMapper.java new file mode 100644 index 0000000..3cfece2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ArbitratorMapper.java @@ -0,0 +1,12 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface ArbitratorMapper { + List selectArbitratorList(Arbitrator arbitrator); + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateLogMapper.java new file mode 100644 index 0000000..7e5affd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateLogMapper.java @@ -0,0 +1,25 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +@Repository +public interface CaseAffiliateLogMapper { + + + int batchCaseAffiliate(List caseAffiliates); + + + void deletecaseAffiliate(CaseApplication caseApplication); + void batchDeletecaseAffiliate(@Param("ids") List ids); + + + List selectCaseAffiliate(@Param("caseAppliLogId") Long caseAppliLogId); + CaseAffiliate selectCaseAffiliateByIdentityType(@Param("caseAppliLogId") Long caseAppliLogId, @Param("identityType")int identityType); + + int updataCaseAffiliate(CaseAffiliate caseAffiliate); + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateMapper.java new file mode 100644 index 0000000..97eca71 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAffiliateMapper.java @@ -0,0 +1,45 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.vo.BookSendVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface CaseAffiliateMapper { + + + int batchCaseAffiliate(List caseAffiliates); + + + void deletecaseAffiliate(CaseApplication caseApplication); + void batchDeletecaseAffiliate(@Param("ids") List ids); + + + List selectCaseAffiliate(CaseAffiliate caseAffiliate); + List selectCaseAffiliateByCaseIds(@Param("ids") List ids); + CaseAffiliate selectCaseAffiliateByIdentityType(@Param("caseAppliId") Long caseAppliId, @Param("identityType")int identityType); + + int updataCaseAffiliate(CaseAffiliate caseAffiliate); + + /** + * 根据案件查询邮箱 + * @param id + * @return + */ + List emailByCaseId(@Param("caseAppliId")Long id); + + /** + * 批量修改 + * @param affiliateLogList + */ + void updateCaseAffiliateByCaseId(@Param("caseAppliId")Long caseAppliId,@Param("list") List affiliateLogList); + + /** + * 根据案件id删除 + * @param caseId + */ + void deleteByCaseId(@Param("caseAppliId") Long caseId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationLogMapper.java new file mode 100644 index 0000000..ca49a36 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationLogMapper.java @@ -0,0 +1,56 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.vo.UpdateSubmitVO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author wangqiong + * @description 案件日志 + * @date 2023-11-17 14:05 + */ +@Repository +public interface CaseApplicationLogMapper { + int insert(CaseApplication caseApplicationLog); + + int deleteById(Long id); + + + + CaseApplication selectByCaseIdAndVersion(@Param("caseAppliId")long caseAppliId,@Param("version") int version); + + Integer selectMaxVersionByCaseId(@Param("caseAppliId")long caseAppliId); + + /** + * 修改日志表状态 + * @param vo + */ + void updateStatus(UpdateSubmitVO vo); + + /** + * 根据案件id查询秘书角色最新版本号 + * @param id + * @return + */ + Integer selectMaxVersionBySecret(@Param("caseAppliId")Long id); + + /** + * 删除日志 + * @param ids + */ + void batchDeleteLog(@Param("ids") List ids); + + CaseApplication selectBeforeCase(@Param("caseId") Long caseId, @Param("version")Integer version); + + Integer batchSave(@Param("list")List caseApplications); + + /** + * 根据案件id查询所有的日志id + * @param ids + * @return + */ + List selectLogsByCaseIds(@Param("ids")List ids); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationMapper.java new file mode 100644 index 0000000..3145ff4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseApplicationMapper.java @@ -0,0 +1,140 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseConfirmPayDTO; +import com.ruoyi.wisdomarbitrate.domain.vo.ToDoCount; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface CaseApplicationMapper { + List selectCaseApplicationList(CaseApplication caseApplication); + List selectCaseApplicationList1(CaseApplication caseApplication); + + int selectCaseApplicationCount(CaseApplication caseApplication); + + /** + * 查询超级管理员案件 + * @param caseApplication + * @return + */ + List selectAdminCaseApplicationList(CaseApplication caseApplication); + + int insertCaseApplication(CaseApplication caseApplication); + + + int updataCaseApplication(CaseApplication caseApplication); + + int submitCaseApplication(CaseApplication caseApplication); + + int deletecaseApplication(CaseApplication caseApplication); + + CaseApplication selectCaseApplication(CaseApplication caseApplication); + + /** + * 根据案件id查询案件信息 + * @param ids + * @return + */ + List listCaseApplicationByIds(@Param("ids")List ids); + + CaseApplication selectCaseApplicationConfirm(CaseApplication caseApplication); + + /** + * 查询最大编号 + * @param caseNum + * @param length + * @return + */ + Integer selectCaseNumLike(@Param("caseNum") String caseNum, @Param("length") int length); + + /** + * 查询仲裁员根据案件id + * @param id + * @return + */ + String selectArbitratorList(@Param("id") String id); + + /** + * 修改支付方式 + * @param payDTO + */ + void updatePayType(CaseConfirmPayDTO payDTO); + + + ToDoCount selectAdminCaseToDoCount(); + + + ToDoCount selectTodoCountByRole(CaseApplication caseApplication); + + /** + * 修改案件锁定状态 + * @param id + * @param lockStatus + * @return + */ + int updateCaseLockStatus(@Param("id")Long id,@Param("lockStatus") Integer lockStatus); + + /** + * 批量删除案件 + * @param ids + * @return + */ + int batchDeletecaseApplication(@Param("ids") List ids); + + /** + * 绑定房间号 + * @param caseId + * @param roomId + */ + void bindCaseId(@Param("caseId")Long caseId,@Param("roomId") String roomId); + + /** + * 根据房间号查询案件id + * @param roomId + * @return + */ + Long selectCaseIdByRoomId(@Param("roomId")String roomId); + + /** + * 查询已办案件 + * @param caseApplication + * @return + */ + List selectHandledCase(CaseApplication caseApplication); + /** + * 查询最大房间号 + * @return + */ + Long selectMaxRoomId(); + + /** + * 修改案件版本号 + * @param id + * @param version + */ + void updateVersionById(@Param("id")Long id, @Param("version")Integer version); + + + /** + * 查询最大批号 + * @return + */ + Integer selectBatchNumberLike(); + + /** + * 批量新增案件 + * @param caseApplications + * @return + */ + int batchSave(@Param("list")List caseApplications); + + int selectCasenum(@Param("userId") String userId); + + List selectAdminCaseApplicationListBatch(CaseApplication caseApplication); + + List listCaseApplicationByBatchNumber(CaseApplication caseApplication); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachLogMapper.java new file mode 100644 index 0000000..b5d1ca9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachLogMapper.java @@ -0,0 +1,31 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface CaseAttachLogMapper { + int save(CaseAttach caseAttach); + + List queryAnnexPathByCaseId(Long id); + + List queryCaseAttachList(CaseApplication caseApplication); + + + int updateCaseAttach(CaseAttach caseAttach); + + int updateCaseAttachBycaseid(CaseAttach caseAttach); + + int deleteByFileIds(@Param("ids") List fileIds); + + List getCaseAttachByCaseIdAndType(CaseAttach caseAttach); + + CaseAttach queryAnnexById(Integer annexId); + + + Integer batchSave(@Param("list")List caseAttaches); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java new file mode 100644 index 0000000..ca3bb75 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java @@ -0,0 +1,38 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface CaseAttachMapper { + int save(CaseAttach caseAttach); + int batchSave(@Param("list") List caseAttach); + + List queryAnnexPathByCaseId(Long id); + + List queryCaseAttachList(CaseApplication caseApplication); + + + int updateCaseAttach(CaseAttach caseAttach); + + int updateCaseAttachBycaseid(CaseAttach caseAttach); + + int deleteByFileIds(@Param("ids") List fileIds); + + List getCaseAttachByCaseIdAndType(CaseAttach caseAttach); + + CaseAttach queryAnnexById(Integer annexId); + + /** + * 根据案件id和附件类型删除和上传类型 + * @param caseAppliId + * @param annexType + */ + void deleteByCasedIdAndType(@Param("caseAppliId")Long caseAppliId,@Param("annexType") int annexType,@Param("isBatchUpload") int isBatchUpload); + + void deleteCaseAttachByCasedIdAndType(@Param("caseAppliId")Long caseAppliId,@Param("annexType") int annexType); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceDirectoryMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceDirectoryMapper.java new file mode 100644 index 0000000..e0528ba --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceDirectoryMapper.java @@ -0,0 +1,29 @@ +package com.ruoyi.wisdomarbitrate.mapper; + + +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.wisdomarbitrate.domain.CaseEvidenceDirectory; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface CaseEvidenceDirectoryMapper { + + int save(CaseEvidenceDirectory caseEvidenceDirectory); + /** + * 查询证据目录信息 + * + * @param caseEvidenceDirectory 目录信息 + * @return 目录信息集合 + */ + List selectList(CaseEvidenceDirectory caseEvidenceDirectory); + + /** + * 根据证据名称查询证据目录树信息 + * @param evidenceName 证据名称 + * @param deptCheckStrictly 目录树选择项是否关联显示 + */ + List selectDeptListByEvidenceName(@Param("evidenceName") String evidenceName, @Param("deptCheckStrictly") boolean deptCheckStrictly); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java new file mode 100644 index 0000000..5f0a4a2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface CaseEvidenceMapper { + List getCaseListByRespondent(@Param(value = "identityNum" ) String identityNum + , @Param(value = "caseStatusList") List caseStatusList + , @Param(value = "identityType" ) Integer identityType + ); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseLogRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseLogRecordMapper.java new file mode 100644 index 0000000..af2d85a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseLogRecordMapper.java @@ -0,0 +1,19 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +@Mapper +public interface CaseLogRecordMapper { + + + List selectCaseLogRecordList(CaseLogRecord caseLogRecord); + + int insertCaseLogRecord(CaseLogRecord caseLogRecord); + + void batchInsertRecord(@Param("list")List list); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseNumRuleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseNumRuleMapper.java new file mode 100644 index 0000000..26a2a84 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseNumRuleMapper.java @@ -0,0 +1,20 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseNumRule; + +import java.util.List; + +public interface CaseNumRuleMapper { + int insertCaseNumRule(CaseNumRule caseNumRule); + + + int updateCaseNumRule(CaseNumRule caseNumRule); + + int deleteCaseNumRule(CaseNumRule caseNumRule); + + List selectCaseNumRules(CaseNumRule caseNumRule); + + int countCaseNumRule(CaseNumRule caseNumRule); + + CaseNumRule selectCaseNumRule(CaseNumRule caseNumRule); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java new file mode 100644 index 0000000..fd5549c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CasePaymentRecord; + +import java.util.List; + +public interface CasePaymentRecordMapper { + int saveRecord(CasePaymentRecord casePaymentRecord); + + List queryRecord(String orderNumber); + + void update(CasePaymentRecord casePaymentRecord); + + CasePaymentRecord selectRecordByCaseId(Long id); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueLogMapper.java new file mode 100644 index 0000000..9c257e0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueLogMapper.java @@ -0,0 +1,29 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 动态配置字段表 + */ +@Repository +public interface ColumnValueLogMapper { + + /** + * 批量新增 + */ + int batchSave(@Param("list") List list); + void batchUpdate(@Param("list") List list); + + /** + * 根据案件id查询字段及值 + * @param caseAppliLogId + * @return + */ + List listBycaseAppliLogId(@Param("caseAppliLogId") Long caseAppliLogId); + + List queryColumnValueList(ColumnValue columnValue); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueMapper.java new file mode 100644 index 0000000..a08899e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ColumnValueMapper.java @@ -0,0 +1,37 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.FatchRule; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 动态配置字段表 + */ +@Repository +public interface ColumnValueMapper { + + /** + * 批量新增 + */ + int batchSave(@Param("list") List list); + + /** + * 根据案件id查询字段及值 + * @param caseId + * @return + */ + List listByCaseId(@Param("caseId") Long caseId); + + List queryColumnValueList(ColumnValue columnValue); + /** + * 批量修改 + */ + void batchUpdate(@Param("list") List list); + + int updateColumnValue(ColumnValue columnValue); + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/DeptIdentifyMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/DeptIdentifyMapper.java new file mode 100644 index 0000000..cf78b09 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/DeptIdentifyMapper.java @@ -0,0 +1,20 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.DeptIdentify; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DeptIdentifyMapper { + + /* + 查询仲裁机构信息 + */ + List selectDeptIdentify(DeptIdentify deptIdentify); + + int insertDeptIdentify(DeptIdentify deptIdentify); + + int updateDeptIdentify(DeptIdentify deptIdentify); + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/FatchRuleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/FatchRuleMapper.java new file mode 100644 index 0000000..b331854 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/FatchRuleMapper.java @@ -0,0 +1,32 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.FatchRule; +import com.ruoyi.wisdomarbitrate.domain.TemplateManage; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface FatchRuleMapper { + +/** + * 根据批次查询 + */ + List listByTemplateId(@Param("templateId")Long templateId); + + List selectFatchRuleList(FatchRule fatchRule); + + + List selectFatchRuleListIsDefault(FatchRule fatchRule); + + void deletebatchFatchRule(@Param("fatchRuleIds") List fatchRuleIds); + + int insertFatchRule(FatchRule fatchRule); + + List selectColumnandComment(FatchRule fatchRuleselect); + + FatchRule selectColumnbycomment(FatchRule fatchRule); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/IdentityAuthenticationMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/IdentityAuthenticationMapper.java new file mode 100644 index 0000000..ae6d869 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/IdentityAuthenticationMapper.java @@ -0,0 +1,12 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.ArbitrateRecord; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; + +public interface IdentityAuthenticationMapper { + int insertIdentityAuthentication(IdentityAuthentication identityAuthentication); + IdentityAuthentication selectIdentityAuthentication(IdentityAuthentication identityAuthentication); + + + void updateIdentityAuthentication(IdentityAuthentication ientityAuthentication); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ReservedConferenceMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ReservedConferenceMapper.java new file mode 100644 index 0000000..2dac90b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/ReservedConferenceMapper.java @@ -0,0 +1,40 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.ReservedConference; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + + +import java.util.List; + + +/** + * @author wangqiong + * @description 预约会议Mapper接口 + * @Version 1.0 + * @date 2023-11-09 16:51 + */ +@Repository +public interface ReservedConferenceMapper { + /** + * 根据案件id查询预约会议列表 + * @param caseId + * @return + */ + List selectListByCaseId(@Param("caseId")Long caseId); + + /** + * 新增 + * @param reservedConference + */ + void insert(ReservedConference reservedConference); + + /** + * 根据房间号删除 + * @param roomId + */ + Integer deleteByRoomId(@Param("roomId")String roomId); + + + void batchDeleteByIds(@Param("ids") List ids); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealManageMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealManageMapper.java new file mode 100644 index 0000000..a071eaf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealManageMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.SealManage; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface SealManageMapper { + + List selectSealList(SealManage sealManage); + + int insertSealManage(SealManage sealManage); + + int updateSealManage(SealManage sealManage1); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealSignRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealSignRecordMapper.java new file mode 100644 index 0000000..13d2cba --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SealSignRecordMapper.java @@ -0,0 +1,32 @@ +package com.ruoyi.wisdomarbitrate.mapper; + + + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.SealSignRecord; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface SealSignRecordMapper { + List selectSealSignRecord(SealSignRecord sealSignRecord); + + /** + * 查询已签署和签署中的文件 + * @param sealSignRecord + * @return + */ + List selectSealSignRecordbyStat(SealSignRecord sealSignRecord); + + /** + * 差询等待签署,签署中的案件 + * @param penSonAccount 签署人员 + * @return + */ + List selectSealSigning(@Param("penSonAccount") String penSonAccount, @Param("caseStatus") Integer caseStatus); + + int updataSealSignRecord(SealSignRecord sealSignRecord); + + + void insertSealSignRecord(SealSignRecord sealSignRecord); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SendMailRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SendMailRecordMapper.java new file mode 100644 index 0000000..1efd2eb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SendMailRecordMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.SendMailRecord; + +import java.util.List; + +public interface SendMailRecordMapper { + int saveSendMailRecord(SendMailRecord sendMailRecord); + + List selectSendMailRecord(SendMailRecord sendMailRecord); + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SmsRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SmsRecordMapper.java new file mode 100644 index 0000000..e8c4740 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/SmsRecordMapper.java @@ -0,0 +1,22 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.SmsSendRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SmsRecordMapper { + + int saveSmsSendRecord(SmsSendRecord smsSendRecord); + + List getSmsSendRecord(SmsSendRecord smsSendRecord); + + /** + * 批量新增 + * @param smsSendRecordList + * @return + */ + int batchSaveSmsSendRecord(@Param("list") List smsSendRecordList); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateFatchRuleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateFatchRuleMapper.java new file mode 100644 index 0000000..71c7b31 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateFatchRuleMapper.java @@ -0,0 +1,19 @@ +package com.ruoyi.wisdomarbitrate.mapper; + + +import com.ruoyi.wisdomarbitrate.domain.vo.TemplateFatchRule; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface TemplateFatchRuleMapper { + int selectTemplateFatchRulecount(TemplateFatchRule templateFatchRule); + + + List selectTemplateFatchRuleList(TemplateFatchRule templateFatchRule); + + void deleteTemplateFatchRule(Long id); + + int insertTemplateFatchRule(TemplateFatchRule templateFatchRule); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManageMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManageMapper.java new file mode 100644 index 0000000..1789a90 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManageMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.SealManage; +import com.ruoyi.wisdomarbitrate.domain.TemplateManage; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface TemplateManageMapper { + List selectTemplateList(TemplateManage templateManage); + + int insertTemplateManage(TemplateManage templateManage); + + int updateTemplateManage(TemplateManage templateManage); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManualMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManualMapper.java new file mode 100644 index 0000000..6927105 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/TemplateManualMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.TemplateManual; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface TemplateManualMapper { + + int insertTemplateManual(TemplateManual templateManual); + + int updateTemplateManual(TemplateManual templateManual); + + List selectTemplateManual(TemplateManual templateManual); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/WeChatUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/WeChatUserMapper.java new file mode 100644 index 0000000..21bdd5c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/WeChatUserMapper.java @@ -0,0 +1,21 @@ +package com.ruoyi.wisdomarbitrate.mapper; + +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author wangqiong + * @description 微信小程序用户注册登录 + * @date 2023-10-16 11:45 + */ +@Repository +public interface WeChatUserMapper { + int insertUser(WeChatUserVO userVO); + int updateUser(WeChatUserVO userVO); + List selectIdentityAuthentication(WeChatUserVO userVO); + + WeChatUserVO selectUserByOppenId(@Param("oppenId") String openId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/CaseApplicationLogService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/CaseApplicationLogService.java new file mode 100644 index 0000000..246bcd2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/CaseApplicationLogService.java @@ -0,0 +1,58 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.vo.UpdateSubmitVO; + +/** + * @author wangqiong + * @description 案件日志 + * @date 2023-11-17 13:58 + */ +public interface CaseApplicationLogService { + /** + * 新增案件日志 + * @param caseApplicationLog + * @return + */ + int insert(CaseApplication caseApplicationLog); + + /** + * 根据案件日志id删除案件日志 + * @param id + * @return + */ + int delete(Long id); + + /** + * 根据案件id和版本号查询案件日志 + * @param id + * @param version + * @return + */ + CaseApplication selectByCaseIdAndVersion(Long id, int version); + + /** + * 修改的案件提交到秘书 + * @param vo + * @return + */ + AjaxResult submit(UpdateSubmitVO vo); + + /** + * 修改撤销申请 + * @param vo + * @return + */ + AjaxResult revoke(UpdateSubmitVO vo); + + /** + * 秘书审核修改的案件 + * @param vo + * @return + */ + AjaxResult updateAudit(UpdateSubmitVO vo); + + + AjaxResult selectCompareCase(UpdateSubmitVO vo); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IAdjudicationService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IAdjudicationService.java new file mode 100644 index 0000000..5fa26f4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IAdjudicationService.java @@ -0,0 +1,60 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.StringIdsReq; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.SealSignRecord; +import com.ruoyi.wisdomarbitrate.domain.vo.LogisticsInfoVO; + +import java.util.List; + +public interface IAdjudicationService { + AjaxResult createDocument(CaseApplication caseApplication); + + AjaxResult sendDocumentByEmail(Long id,String appEmail,String resEmail ,String apptrackingNum,String restrackingNum); + + List getLogisticsInfo(CaseApplication caseApplication); + + AjaxResult signature(CaseApplication caseApplication); + + AjaxResult caseFile( List ids); + + AjaxResult service(Long id, String appEmail, String resEmail, String apptrackingNum, String restrackingNum); + + AjaxResult stamp(CaseApplication caseApplication); + + AjaxResult getArchivesDetail(Long id); + + AjaxResult regenerationDocument(CaseApplication caseApplication); + + /** + * 根据案件id查询邮箱 + * @param id + * @return + */ + AjaxResult emailByCaseId(Long id); + + /** + * 批量生成裁决书 + * @param ids + * @return + */ + AjaxResult batchDocument(List ids); + + /** + * 根据签署流程id查询批量签名链接 + * @param idsReq + * @return + */ + SealSignRecord selectBatchSignUrl( StringIdsReq idsReq); + + /** + * 根据仲裁员手机号分页查询等待签署,签署中的裁决书 + * @param personAccount + * @return + */ + List selectSealSigning(String personAccount,Integer caseStatus); + + SealSignRecord selectBatchSealUrl(StringIdsReq idsReq); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IArbitratorService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IArbitratorService.java new file mode 100644 index 0000000..ee7a8ab --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IArbitratorService.java @@ -0,0 +1,12 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; + +import java.util.List; + +public interface IArbitratorService { + List selectArbitratorList(Arbitrator arbitrator); + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseApplicationService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseApplicationService.java new file mode 100644 index 0000000..03c5eec --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseApplicationService.java @@ -0,0 +1,154 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO; +import com.ruoyi.wisdomarbitrate.domain.vo.ToDoCount; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Map; + +public interface ICaseApplicationService { + List selectCaseApplicationList(CaseApplication caseApplication); + List selectCaseApplicationListByRole(CaseApplication caseApplication); + + + int insertcaseApplication(CaseApplication caseApplication); + + int selectCaseApplicationCount(CaseApplication caseApplication); + + AjaxResult editCaseApplication(CaseApplication caseApplication); + + int submitCaseApplication( List ids); + + int deletecaseApplicationByIds(List ids); + + CaseApplication selectCaseApplication(CaseApplication caseApplication); + + String importCaseApplication(List caseApplicationList, String operName); + + int pendTral(CaseApplication caseApplication); + + int pendingAppointArbotrar(CaseApplication caseApplication); + + int pendTralCheck(CaseApplication caseApplication); + + int pendTralSure(CaseApplication caseApplication); + + int verificationArbitrateRecord(CaseApplication caseApplication); + + AjaxResult checkArbitrateRecord(CaseApplication caseApplication); + + int submitCaseApplicationCheck(List ids, Integer agreeOrNotCheck,String caseCheckReject); + + CaseApplication selectCaseApplicationConfirm(CaseApplication caseApplication); + + String sendRoomNoMessage(SendRoomNoMessageVO messageVO); + + SealSignRecord selectSignUrl(CaseApplication caseApplication) throws EsignDemoException; + + SealSignRecord selectSealUrl(CaseApplication caseApplication) throws EsignDemoException; + + AjaxResult creatTrialRecord(ArbitrateRecord arbitrateRecord); + + CaseApplication selectSignSealUrl(CaseApplication caseApplication) throws EsignDemoException; + + /** + * 查询待办数量 + * @return + */ + ToDoCount selectToDoCount(); + + AjaxResult selectCaseProgress(CaseApplication caseApplication); + + int updateHeardate(CaseApplication caseApplication); + + /** + * 修改案件锁定状态 + * @param caseApplication + * @return + */ + int updateCaseLockStatus(CaseApplication caseApplication); + + AjaxResult uploadZipFile(MultipartFile file, Long id, String username, Long userId); + /** + * 查询短信发送记录 + * @param smsSendRecord + * @return + */ + List getSmsSendRecord(SmsSendRecord smsSendRecord); + + /** + * 获取userSign + * @param userId + * @return + */ + String generateUserSign(String userId); + + /** + * 预约会议 + * @param reservedConferenceVO + * @return + * @throws Exception + */ + AjaxResult reservedConference(ReservedConferenceVO reservedConferenceVO) throws Exception; + + /** + * 腾讯云销毁房间回调 + * @return + */ + long createRoomId(Long caseId); + + /** + * 根据案件id查询已预约的会议 + * @param caseId + * @return + */ + List reserveConferenceList(Long caseId); + + AjaxResult deleteRoom( String roomId); + + AjaxResult uploadCaseZipFile(MultipartFile file,Long templateId); + + /** + * 根据附件id修改案件id + * @param caseAttach + * @return + */ + AjaxResult updateCaseIdByAnnexId(CaseAttach caseAttach); + + /** + * 仲裁员审核裁决书 + * @param caseApplication + * @return + */ + AjaxResult arbitratorCheckArbitrateRecord(CaseApplication caseApplication); + + AjaxResult creatTrialRecordnew(ArbitrateRecord arbitrateRecord); + + AjaxResult editCaseApplicationDefineval(CaseApplication caseApplication); + + CaseAttach downloadCaseZipFile(CaseApplication caseApplication); + + List selectCaseApplicationListBatchByRole(CaseApplication caseApplication); + + int submitCaseApplicationBatch(String batchNumber); + + int submitCaseApplicationCheckBatch(String batchNumber, Integer agreeOrNotCheck, String caseCheckReject); + + int pendTralCheckBatch(CaseApplication caseApplication); + + int pendTralSureBatch(CaseApplication caseApplication); + + int verificationArbitrateRecordBatch(CaseApplication caseApplication); + + AjaxResult arbitratorCheckArbitrateRecordBatch(CaseApplication caseApplication); + + AjaxResult checkArbitrateRecordBatch(CaseApplication caseApplication); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java new file mode 100644 index 0000000..98bafbb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java @@ -0,0 +1,17 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.ArbitrateRecord; +import com.ruoyi.wisdomarbitrate.domain.BatchCaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseIds; + +import java.util.List; + +public interface ICaseArbitrateService { + + + AjaxResult writtenHear(CaseIds caseIds); + + AjaxResult examineArbitrateMethod(CaseApplication caseApplication, Integer opinion, Integer arbitratMethod); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java new file mode 100644 index 0000000..1e8d4d1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java @@ -0,0 +1,70 @@ +package com.ruoyi.wisdomarbitrate.service; + + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseEvidenceDirectory; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseEvidenceDTO; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceDirectoryVO; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface ICaseEvidenceService { + + AjaxResult getCaseDetailsById(Long id,String userName); + + AjaxResult uploadEvidence(MultipartFile file, Integer annexType, Long id,String userName,Long userId); + + List getCaseListAll(Integer caseStatus); + + AjaxResult evidenceConfirmation(CaseApplication caseApplication); + + AjaxResult caseCrossexamination(CaseEvidenceDTO caseEvidenceDTO); + + /** + * 批量上传文件 + * @param file + * @param annexType + * @param id + * @param username + * @param userId + * @return + */ + AjaxResult batchUpload(MultipartFile[] file, Integer annexType, Long id, String username, Long userId); + + AjaxResult fileList(Long caseAppliId, List annexTypeList); + + int deleteFile( List fileIds); + + List selectEvidenceTreeList(CaseEvidenceDirectory caseEvidenceDirectory); + + + /** + * 查询证据目录数据 + * + * @param caseEvidenceDirectory 证据目录信息 + * @return 证据目录信息集合 + */ + List selectCaseEvidenceList(CaseEvidenceDirectory caseEvidenceDirectory); + + + /** + * 构建前端所需要树结构 + * + * @param caseEvidenceDirectorys 证据列表 + * @return 树结构列表 + */ + List buildCaseEvidenceTree(List caseEvidenceDirectorys); + + /** + * 构建前端所需要下拉树结构 + * + * @param caseEvidenceDirectorys 证据目录列表 + * @return 下拉树结构列表 + */ + List buildCaseEvidenceTreeSelect(List caseEvidenceDirectorys); + + AjaxResult uploadRecord(MultipartFile file, Integer annexType, Long id, String username, Long userId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseLogRecordService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseLogRecordService.java new file mode 100644 index 0000000..f4fcf77 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseLogRecordService.java @@ -0,0 +1,17 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; + +import java.util.List; + +public interface ICaseLogRecordService { + + + List selectCaseLogRecordList(CaseLogRecord caseLogRecord); + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseNumRuleService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseNumRuleService.java new file mode 100644 index 0000000..67b26bf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseNumRuleService.java @@ -0,0 +1,20 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.CaseNumRule; + +import java.util.List; + +public interface ICaseNumRuleService { + AjaxResult insertCaseNumRule(CaseNumRule caseNumRule); + + + AjaxResult updateCaseNumRule(CaseNumRule caseNumRule); + + + AjaxResult deleteCaseNumRule(CaseNumRule caseNumRule); + + List selectCaseNumRule(CaseNumRule caseNumRule); + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java new file mode 100644 index 0000000..9b4e911 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java @@ -0,0 +1,36 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.dto.PayRequest; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseConfirmPayDTO; +import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO; + +import java.util.List; + +public interface ICasePaymentService { + /** + * 案件缴费 + */ + AjaxResult casePay(CasePayDTO casePayDTO); + + AjaxResult confirmPayment( List ids); + + /** + * 确认缴费 + * @param payDTO + * @return + */ + AjaxResult confirmPay(CaseConfirmPayDTO payDTO); + + + AjaxResult casePayList(CasePayDTO casePayDTO); + + AjaxResult confirmPayBatch(CasePayDTO payDTO); + + AjaxResult casePayListBatch(CasePayDTO casePayDTO); + + AjaxResult confirmPaymentBatch(String batchNumber); + + AjaxResult casePayBatch(CasePayDTO casePayDTO); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IDeptIdentifyService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IDeptIdentifyService.java new file mode 100644 index 0000000..93f8d09 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IDeptIdentifyService.java @@ -0,0 +1,69 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.wisdomarbitrate.domain.DeptIdentify; +import com.ruoyi.wisdomarbitrate.domain.FatchRule; +import com.ruoyi.wisdomarbitrate.domain.SealManage; +import com.ruoyi.wisdomarbitrate.domain.TemplateManage; +import com.ruoyi.wisdomarbitrate.domain.vo.SealListVO; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface IDeptIdentifyService { + + + List selectDeptIdentify(DeptIdentify deptIdentify); + + + DeptIdentify selectDeptIndefiUrl(DeptIdentify deptIdentify) throws EsignDemoException; + + AjaxResult enableDept(DeptIdentify deptIdentify); + + AjaxResult sealUpload(Long id,String sealName ,MultipartFile file); + + + AjaxResult receiveNotify(String body); + + List getSealList(DeptIdentify deptIdentify); + + AjaxResult updateSealLockStatus(SealManage sealManage); + + + AjaxResult insertDeptIdentify(DeptIdentify deptIdentify); + + AjaxResult deleteDeptIdentify(Long id); + + AjaxResult updateDeptIdentify(DeptIdentify deptIdentify); + + AjaxResult insertTemplate(TemplateManage templateManage , MultipartFile file); + + AjaxResult updateTemplate(TemplateManage templateManage, MultipartFile file); + + AjaxResult deleteTemplate(Long id); + + List getTemplateList(DeptIdentify deptIdentify); + + + List selectPostUserByDeptId(DeptIdentify deptIdentify); + + + AjaxResult bindHandler(DeptIdentify deptIdentify); + + List getFatchRuleByTemplateid(TemplateManage templateManage); + + AjaxResult saveFatchRules(TemplateManage templateManage); + + List selectColumnandComment(); + + FatchRule selectColumnbycomment(FatchRule fatchRule); + + /** + * 根据模板id查询模板字段列表 + * @param templateManage + * @return + */ + List getTemplateInfoById(TemplateManage templateManage); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ISendMailRecordService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ISendMailRecordService.java new file mode 100644 index 0000000..b0564a6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ISendMailRecordService.java @@ -0,0 +1,15 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.wisdomarbitrate.domain.SendMailRecord; + +import java.util.List; + +public interface ISendMailRecordService { + + + List selectSendMailRecordList(SendMailRecord sendMailRecord); + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ITemplateService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ITemplateService.java new file mode 100644 index 0000000..fb80219 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ITemplateService.java @@ -0,0 +1,16 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.TemplateManual; + +import java.util.List; + +public interface ITemplateService { + AjaxResult insertTemplate(TemplateManual templateManual); + + AjaxResult deleteTemplate(Long id); + + AjaxResult updateTemplate(TemplateManual templateManual); + + List selectTemplate(TemplateManual templateManual); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IdentityAuthenticationService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IdentityAuthenticationService.java new file mode 100644 index 0000000..1ae0f29 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/IdentityAuthenticationService.java @@ -0,0 +1,34 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; + +public interface IdentityAuthenticationService { + + + IdentityAuthentication selectIdentityAuthentication(IdentityAuthentication identityAuthentication); + + /** + * 检查是否已经认证的用户 + * + * @param identityAuthentication + * @return + */ + String checkIsAuthentication(IdentityAuthentication identityAuthentication); + + /** + * 获取Eidtoken + * + * @return + */ + JSONObject selectIdentityAuthenticaEIDtoken(); + + /** + * 小程序人脸核身后查询身份认证结果 + * + * @param ientityAuthentication + * @return + */ + AjaxResult selectIdentityAuthenticaRespon(IdentityAuthentication ientityAuthentication); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/VideoService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/VideoService.java new file mode 100644 index 0000000..c1c8c71 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/VideoService.java @@ -0,0 +1,58 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; + +import javax.servlet.http.HttpServletRequest; + +/** + * 视频录制 + */ +public interface VideoService { + + + void videoRollBack(String body, HttpServletRequest request) ; + + AjaxResult bindCaseId(Long caseId, String roomId); + + AjaxResult videoList(Long caseId); + + /** + * 开启腾讯云录制 + * @param roomId + * @return + */ + AjaxResult openCloudRecording(long caseId,long roomId); + + AjaxResult closeDeleteCloudRecording(String taskId); + + /** + * 解散房间 + * @param roomId + * @return + */ + AjaxResult dissolveRoom( Long roomId); + /** + * 根据userId查询该用户是否是秘书 + * @param userId + * @return + */ + AjaxResult secretaryRoleByUserId(Long userId); + + /** + * 根据html字符串转pdf并和案件关联 + * @param reservedConferenceVO + * @return + */ + AjaxResult htmlToPDF(ReservedConferenceVO reservedConferenceVO); + + /** + * 根据案件id和类型查询附件 + * @param caseAppliId + * @param annexType + * @return + */ + AjaxResult attachListByCaseId(Long caseAppliId, Integer annexType); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/WeChatUserService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/WeChatUserService.java new file mode 100644 index 0000000..9d9735f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/WeChatUserService.java @@ -0,0 +1,18 @@ +package com.ruoyi.wisdomarbitrate.service; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; + +/** + * 微信小程序用户注册登录 + */ +public interface WeChatUserService { + + + AjaxResult sendCode(WeChatUserVO userVO); + + + AjaxResult registerUser(IdentityAuthentication ientityAuthentication); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/AdjudicationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/AdjudicationServiceImpl.java new file mode 100644 index 0000000..af495a9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/AdjudicationServiceImpl.java @@ -0,0 +1,1513 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.deepoove.poi.data.PictureRenderData; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.*; +import com.ruoyi.common.utils.thread.MultipleThreadListParam; +import com.ruoyi.common.utils.thread.MultipleThreadWorkUtil; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.wisdomarbitrate.StringIdsReq; +import com.ruoyi.wisdomarbitrate.domain.vo.BookSendVO; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.utils.CaseLogUtils; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.ArchivesDetailVO; +import com.ruoyi.wisdomarbitrate.domain.vo.LogisticsInfoVO; +import com.ruoyi.wisdomarbitrate.service.IAdjudicationService; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +import com.ruoyi.wisdomarbitrate.service.ICaseLogRecordService; +import com.ruoyi.wisdomarbitrate.utils.SignAward; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.MailSendException; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.*; +import java.math.BigDecimal; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static com.ruoyi.common.utils.PageUtils.startPage; +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +@Service +@Slf4j +public class AdjudicationServiceImpl implements IAdjudicationService { + private final String apiUrl = "http://api.cainiaoapi.com/api/exp/v1/index"; + + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private ArbitrateRecordMapper arbitrateRecordMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private EmailOutUtil emailOutUtil; + @Autowired + private ICaseApplicationService caseApplicationService; + @Autowired + private ICaseLogRecordService caseLogRecordService; + @Autowired + private RedisCache redisCache; + @Autowired + private SendMailRecordMapper sendMailRecordMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + @Autowired + private TemplateManageMapper templateManageMapper; + @Autowired + private ColumnValueMapper columnValueMapper; + @Autowired + private FatchRuleMapper fatchRuleMapper; + @Autowired + private SysDictDataMapper dictDataMapper; + @Autowired + private SealManageMapper sealManageMapper; + @Autowired + private SealSignRecordMapper sealSignRecordMapper; + + + // 仲裁反请求模板内容 + private final String counterclaim = "在《2022年版仲裁规则》第十八条第(一)项规定的期限内,被申请人向秘书处提交了" + + "《仲裁反请求申请书》及证据材料。仲裁委依据《2022年版仲裁规则》第十八条的规定受理了该仲裁反请求案申请。" + + "仲裁反请求案件受理后,秘书处向被申请人发送了仲裁反请求通知书及附件,向申请人发送了仲裁反请求通知书及附件、仲裁反请求申请书及附件。"; + // 财产保全内容 + String preservation = "本案受理后,申请人向仲裁委提交了财产保全申请,仲裁委根据《中华人民共和国仲裁法》" + + "第二十八条之规定,将该申请提交至法院。"; + // 管辖权异议 + String jurisdictionalObjection = "本案受理后,被申请人向仲裁委提交了《管辖异议申请书》,认为" + + ",仲裁委经审理,当庭驳回了被申请人的管辖异议申请,并告知被申请人具体的事实和理由将在裁决书中一并列明。"; + // 线上开庭时+线上仲裁 + String onLineDate = "{{onLineDate}}"; + String onLine = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于" + onLineDate + "通过仲裁委智慧仲裁平台开庭审理了本案。"; + // 开庭+线下仲裁 + String offLineDate = "{{offLineDate}}"; + String offLine = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于 " + offLineDate + "在仲裁委所在地开庭审理了本案。"; + //书面仲裁时 + String writtenDate = "{{writtenDate}}"; + String written = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于" + writtenDate + "在仲裁委所在地开庭审理了本案。仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,根据《2022年版仲裁规则》第五十八条的规定对本案进行了书面审理。 "; + //开庭+缺席审理 + String absent = "申请人的特别授权委托代理人{{agentName}}" + "出席了庭审。被申请人经依法送达开庭通知,无正当理由未出席庭审,故仲裁庭依据" + + "《2022年版仲裁规则》第四十条第(二)项的规定,对本案进行了缺席审理。庭审中,申请人陈述了仲裁请求事项及事实与理由,出示了证据材料并进行了说明,\" +\n" + + " \"发表了意见,回答了仲裁庭的提问,并作了最后陈述。因被申请人缺席庭审,故仲裁庭无法组织调解。" + "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第四十条第(二)项、第五十一条的规定,缺席裁决如下:"; + // 开庭+出席 + String attend = "申请人的特别授权委托代理人{{agentName}}和被申请人本人出席了庭审。 "; + // 开庭+出席+被申提供证据 + String onLineAttendFile = "庭审中,申请人陈述了仲裁请求事项及所依据的事实与理由,被申请人进行了答辩;双方当事人均出示了证据材料并对对方的证据材料进行了质证;双方当事人均回答了仲裁庭的提问,进行了辩论,并分别作了最后陈述。双方当事人在仲裁庭的主持下进行了调解,但未能达成调解协议。 "; + // 开庭+出席+被申未提供证据 + String onLineAttend = "庭审中,申请人陈述了仲裁请求事项及所依据的事实与理由,被申请人进行了答辩;申请人出示了证据材料,被申请人对对方的证据材料进行了质证; 双方当事人均回答了仲裁庭的提问,进行了辩论,并分别作了最后陈述。双方当事人在仲裁庭的主持下进行了调解,但未能达成调解协议。 "; + // 被申请人出席答辩意见 + String resAttendOpinion = "\n(二)被申请人的答辩意见 \n(三)当事人提供的证据材料及对方的质证意见\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:\n{{applicantFile}}\n被申请人对上述材料的质证意见为:{{respondentOpinion}}\n"; + // 被申请人出席+被申请人提供了资料 + String resFile = "被申请人向仲裁庭提交了如下证据材料:\n{{resFile}}" + + "申请人对上述材料的质证意见为:{{applicantOpinion}}"; + // 被申请人缺席 + String resAbsent = "(二)当事人提供的证据材料\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:\n{{applicantFile}}"; + // 日期格式化年月日 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); + + @Override + @Transactional + public AjaxResult createDocument(CaseApplication caseApplicationReq) { + String templatePath = ""; + String templateName = ""; + String agentName = ""; + String resName = ""; + try { + Map datas = new HashMap<>(); + Long id = caseApplicationReq.getId(); + //获取案件详细信息 + CaseApplication caseApplicationById = caseApplicationService.selectCaseApplication(caseApplicationReq); + if (caseApplicationById == null) { + return AjaxResult.error("案件不存在"); + } + + if (caseApplicationById.getTemplateId() == null) { + return AjaxResult.error("请先指定裁决书模板"); + } + // 根据模板id查找对应的模板 + TemplateManage templateManage = new TemplateManage(); + templateManage.setId(caseApplicationById.getTemplateId()); + List templateManages = templateManageMapper.selectTemplateList(templateManage); + if (CollectionUtil.isEmpty(templateManages)) { + return AjaxResult.error("请先指定裁决书模板"); + } + templatePath = templateManages.get(0).getTemOrigPath(); + if (StrUtil.isEmpty(templatePath)) { + return AjaxResult.error("未找到该模板"); + } + + // todo 部署放开 + if (templatePath != null) { + templatePath = "/home/ruoyi/" + templatePath; + } + try { + File file = new File(templatePath); + } catch (Exception e) { + return AjaxResult.error("未找到该模板"); + } + templateName = templateManages.get(0).getFileName(); + // 查询案件相关表信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + //获取仲裁记录表里的相关信息 + ArbitrateRecord arbitrateRecord = new ArbitrateRecord(); + arbitrateRecord.setCaseAppliId(id); + ArbitrateRecord arbitrateRecordSelect = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecord); + // 在系统表中查询案件内置字段 + SysDictData sysDictData = new SysDictData(); + sysDictData.setDictType("case_built_type"); + List dictDataList = dictDataMapper.selectDictDataList(sysDictData); + // 根据模板id查询抓取规则,判断从主表取值还是从columnValue值取 + List fatchRuleList = fatchRuleMapper.listByTemplateId(caseApplicationById.getTemplateId()); + // 抓取规则,0-内置字段,1-自定义字段 + Map> fatchRuleMap = new HashMap<>(); + // 裁决书需要的字段和内容,占位符需要配置成中文 + Map valueMap = new HashMap<>(); + // 如果未设置抓取规则,则从主表取数据,设置内置字段值 + if (CollectionUtil.isNotEmpty(fatchRuleList)) { + fatchRuleMap = fatchRuleList.stream().collect(Collectors.groupingBy(FatchRule::getIsDefault)); + } + // 自定义字段,从columnValue值取 + if (fatchRuleMap.size() > 0 && fatchRuleMap.containsKey(1)) { + // 根据案件id查询key-value表 + List columnValueList = columnValueMapper.listByCaseId(caseApplicationReq.getId()); + if (CollectionUtil.isNotEmpty(columnValueList)) { + columnValueList.forEach(columnValue -> valueMap.put(columnValue.getName(), columnValue.getValue())); + } + } + // 组装内置字段,在主表中查出内容 + buildDefaultColumnValue(dictDataList, caseAffiliates, valueMap, caseApplicationById); + + // 获取模板中的占位符key + List bookmarkList = getBookmarkByDocx(templatePath); + if (CollectionUtil.isEmpty(bookmarkList)) { + return AjaxResult.success("请检查模板是否配置正确,未获取到占位符"); + } + // 遍历书签,给书签赋值 + replaceBookmark(bookmarkList, datas, valueMap); + // 根据条件替换书签 + conditionReplaceBookmark(caseApplicationById, datas, agentName, resName, arbitrateRecordSelect); + // 裁决书生成时间 + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + datas.put("裁决书生成时间", year); + //生成编码 + String equipmentNo = getNewEquipmentNo(); + // 裁决书编号 + datas.put("裁决书编号", equipmentNo); + // 仲裁费 + datas.put("仲裁费", caseApplicationById.getFeePayable() != null ? caseApplicationById.getFeePayable().toString() : ""); + // 案件创建时间 + Date createTime = caseApplicationById.getCreateTime(); + // 将日期格式化为字符串 + String createTimeStr = sdf.format(createTime); + datas.put("案件创建时间", createTimeStr); + // 立案日期 + Date registerDate = caseApplicationById.getRegisterDate(); + String registerDateStr = sdf.format(registerDate); + datas.put("立案日期", registerDateStr); + + + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + // todo + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; +// String saveFolderPath = "D:/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".docx"; + // todo + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; +// String saveName = "D:/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day + "/" + fileName; + // 将word中的标签替换掉,生成新的word + String docFilePath = wordChangeText(templatePath, datas, saveFolderPath, fileName); + + String savePath = docFilePath.substring(0, docFilePath.indexOf("/upload/") + 8); + // 保存裁决书附件 + saveArbitorFile(id, saveName, savePath, caseApplicationById, arbitrateRecordSelect); + + return AjaxResult.success("裁决书已生成"); + } catch (IOException e) { + return AjaxResult.error(e + "请检查文件路径是否有误"); + } + } + + /** + * 将word中的标签替换掉,生成新的word + * + * @param modalFilePath 裁决书模板路径 + * @param datas 替换标签的内容 + * @param saveFolderPath 保存路径 + * @param fileName 保存文件名 + * @return + * @throws IOException + */ + private String wordChangeText(String modalFilePath, Map datas, String saveFolderPath, String fileName) throws IOException { + String resultFilePath = saveFolderPath + "/" + fileName; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + Path sourcePath = new File(modalFilePath).toPath(); + Path destinationPath = new File(resultFilePath).toPath(); + Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + String docFilePath = WordUtil.getDocFilePath(datas, modalFilePath, resultFilePath); + File file = new File(docFilePath); + if (file.exists()) { + InputStream in = new FileInputStream(file); + XWPFDocument xwpfDocument = new XWPFDocument(in); + WordUtil.changeText(xwpfDocument); + } + return docFilePath; + } + + /** + * 根据条件判断裁决书中是否需要该内容 + * + * @param caseApplicationById 案件信息 + * @param datas 替换标签值 + * @param agentName 代理人名称 + * @param resName 被申请人名称 + * @param arbitrateRecordSelect 仲裁记录 + */ + private void conditionReplaceBookmark(CaseApplication caseApplicationById, Map datas, String agentName, String resName, ArbitrateRecord arbitrateRecordSelect) { + // 如果有仲裁反请求,该字段设置值 + Integer adjudicaCounter = caseApplicationById.getAdjudicaCounter(); + if (adjudicaCounter != null && adjudicaCounter == 1) { + datas.put("仲裁反请求", counterclaim); + } + //财产保全 + Integer properPreser = caseApplicationById.getProperPreser(); + if (properPreser != null && properPreser == 1) { + datas.put("财产保全", preservation); + } + //管辖权异议 + Integer objectiJuris = caseApplicationById.getObjectiJuris(); + if (objectiJuris != null && objectiJuris == 1) { + datas.put("管辖权异议", jurisdictionalObjection); + } + + // 出席庭审人员角色名称 + String attendName = "秘书、"; + boolean isAbsenceFlag = caseApplicationById.getIsAbsence() != null && caseApplicationById.getIsAbsence().equals(0); + boolean appIsAbsenceFlag = caseApplicationById.getAppliIsAbsen() != null && caseApplicationById.getAppliIsAbsen().equals(0); + if (isAbsenceFlag || appIsAbsenceFlag) { + if (isAbsenceFlag) { + attendName += "申请代理人" + agentName + "、"; + } + if (appIsAbsenceFlag) { + attendName += "被申请人" + resName; + } + if (attendName.endsWith("、")) { + attendName = attendName.replace("、", ""); + } + datas.put("出席庭审人员", attendName); + } + + // 仲裁员名称 + datas.put("仲裁员姓名", caseApplicationById.getArbitratorName()); + // 审理方式 + Integer arbitratMethod = caseApplicationById.getArbitratMethod(); + Date hearDate = caseApplicationById.getHearDate(); + String hearDateStr = ""; + if (hearDate != null) { + // 审理日期 + hearDateStr = sdf.format(hearDate); + datas.put("审理日期", hearDateStr); + } + // todo 线上仲裁/线下仲裁方式未选择 + //线上开庭时+线上仲裁 + if (arbitratMethod != null && arbitratMethod == 1) { + String replace = onLine.replace(onLineDate, Optional.of(hearDateStr).orElse("")); + datas.put("线上开庭并线上仲裁", replace); + // 所有附件 + List caseAttachList = caseApplicationById.getCaseAttachList(); + Map> caseAttachMap = new HashMap<>(); + if (caseAttachList != null && caseAttachList.size() > 0) { + caseAttachMap = caseAttachList.stream().collect(Collectors.groupingBy(CaseAttach::getAnnexType)); + } + // 被申请人是否缺席 + Integer isAbsence = caseApplicationById.getIsAbsence(); + if (isAbsence != null && isAbsence == 1) { + // 被申请人缺席,开庭+缺席审理 + String absentReplace = absent.replace("{{agentName}}", Optional.of(agentName).orElse("")); + + // 被申请人缺席 + String resAbsentReplace = resAbsent; + if (caseAttachMap != null && CollectionUtil.isNotEmpty(caseAttachMap.get(2))) { + List caseAttaches = caseAttachMap.get(2); + StringBuilder stringBuilder = new StringBuilder(); + for (CaseAttach caseAttach : caseAttaches) { + stringBuilder.append(caseAttach.getAnnexName()).append("\n"); + } + resAbsentReplace = resAttendOpinion.replace("{{applicantFile}}", stringBuilder.toString()); + } + datas.put("开庭并缺席", absentReplace + resAbsentReplace); + } else { + // 被申出席 + String attendReplace = attend.replace("{{agentName}}", Optional.ofNullable(agentName).orElse("")); + datas.put("开庭并出席", attendReplace); + // 被申请人证据 + if (caseAttachMap != null && CollectionUtil.isNotEmpty(caseAttachMap.get(6))) { + // 开庭+出席+被申提供证据 + + // 开庭+出席+被申提供证据 + String resFileReplace = resFile; + if (CollectionUtil.isNotEmpty(caseAttachMap.get(6))) { + List caseAttaches = caseAttachMap.get(6); + StringBuilder stringBuilder = new StringBuilder(); + for (CaseAttach caseAttach : caseAttaches) { + stringBuilder.append(caseAttach.getAnnexName()).append("\n"); + } + resFileReplace = resFile.replace("{{resFile}}", stringBuilder.toString()).replace("{{applicantOpinion}}", (arbitrateRecordSelect == null || arbitrateRecordSelect.getApplicantOpinion() == null ? "" : arbitrateRecordSelect.getApplicantOpinion())); + } + datas.put("开庭并出席并被申提供证据", onLineAttendFile + resFileReplace); + } else { + // 开庭+出席+被申未提供证据 + datas.put("开庭并出席并被申未提供证据", onLineAttend); + } + // 被申请人出席答辩意见 + String resAttendOpinionReplace = resAttendOpinion; + if (caseAttachMap != null && CollectionUtil.isNotEmpty(caseAttachMap.get(2))) { + List caseAttaches = caseAttachMap.get(2); + StringBuilder stringBuilder = new StringBuilder(); + for (CaseAttach caseAttach : caseAttaches) { + stringBuilder.append(caseAttach.getAnnexName()).append("\n"); + } + resAttendOpinionReplace = resAttendOpinion.replace("{{applicantFile}}", stringBuilder.toString()).replace("{{respondentOpinion}}", (arbitrateRecordSelect == null || arbitrateRecordSelect.getRespondentOpinion() == null) ? "" : arbitrateRecordSelect.getRespondentOpinion()); + } + + datas.put("被申请人出席答辩意见", resAttendOpinionReplace); + } + + } else { + //书面仲裁时 + String replace = written.replace(writtenDate, Optional.of(hearDateStr).orElse("")); + datas.put("书面仲裁", replace); + + } + + } + + /** + * 给模板中的占位符赋值 + * + * @param bookmarkList 书签 + * @param datas 书签赋值 + * @param valueMap 案件内容 + */ + private void replaceBookmark(List bookmarkList, Map datas, Map valueMap) { + for (String bookmark : bookmarkList) { + if (valueMap.containsKey(bookmark)) { + if (bookmark.equals("仲裁请求")) { + // 请求仲裁庭裁决 + String arbitratClaims = valueMap.get(bookmark); + if (StrUtil.isNotEmpty(arbitratClaims)) { + String replace = arbitratClaims.replace("甲方", "被申请人").replace("乙方", "申请人"); + datas.put(bookmark, replace); + + } else { + datas.put(bookmark, ""); + } + } else if (bookmark.equals("本案事实")) { + // 查询本案事实如下 + String mediationAgreement = valueMap.get(bookmark); + if (StrUtil.isNotEmpty(mediationAgreement)) { + String replace = mediationAgreement.replace("甲方", "被申请人").replace("乙方", "申请人"); + datas.put(bookmark, replace); + + } else { + datas.put(bookmark, ""); + } + } else { + datas.put(bookmark, valueMap.get(bookmark)); + } + } + } + } + + /** + * 组装案件内置字段值,即主表和相关人员表信息 + * + * @param dictDataList 内置字段 + * @param caseAffiliates 关联人员 + * @param valueMap 组装的值 + */ + private void buildDefaultColumnValue(List dictDataList, List caseAffiliates, Map valueMap, CaseApplication caseApplication) { + if (CollectionUtil.isNotEmpty(dictDataList)) { + Map affiliateMap = caseAffiliates.stream().collect(Collectors.toMap(CaseAffiliate::getIdentityType, Function.identity(), (n1, n2) -> n2)); + for (SysDictData dictData : dictDataList) { + if (StrUtil.isNotEmpty(dictData.getDictLabel())) { + if (dictData.getDictLabel().contains("被申请人")) { + CaseAffiliate affiliate = affiliateMap.get(2); + if (affiliate == null) { + continue; + } + // 被申请人 + switch (dictData.getDictLabel()) { + case "被申请人姓名": + valueMap.put(dictData.getDictLabel(), affiliate.getName()); + break; + case "被申请人身份证号": + valueMap.put(dictData.getDictLabel(), affiliate.getIdentityNum()); + break; + case "被申请人住所": + valueMap.put(dictData.getDictLabel(), affiliate.getResidenAffili()); + break; + case "被申请人联系地址": + valueMap.put(dictData.getDictLabel(), affiliate.getContactAddress()); + break; + case "被申请人联系电话": + valueMap.put(dictData.getDictLabel(), affiliate.getContactTelphone()); + break; + case "被申请人电子邮件": + valueMap.put(dictData.getDictLabel(), affiliate.getEmail()); + break; + case "被申请人性别": + String responSex = affiliate.getResponSex(); + if (responSex.equals("0")) { + valueMap.put(dictData.getDictLabel(), "男"); + } else { + valueMap.put(dictData.getDictLabel(), "女"); + } + break; + case "被申请人出生年月日": + Date responBirth = affiliate.getResponBirth(); + if (responBirth != null) { + valueMap.put(dictData.getDictLabel(), sdf.format(responBirth)); + } else { + valueMap.put(dictData.getDictLabel(), ""); + } + break; + default: + break; + } + } else if (dictData.getDictLabel().contains("申请人") || dictData.getDictLabel().contains("统一社会信用代码") + || dictData.getDictLabel().contains("法定代表人") || dictData.getDictLabel().contains("法定代表人职位") + || dictData.getDictLabel().contains("代理人")) { + CaseAffiliate affiliate = affiliateMap.get(1); + if (affiliate == null) { + continue; + } + // 申请人 + switch (dictData.getDictLabel()) { + case "申请人姓名": + valueMap.put(dictData.getDictLabel(), affiliate.getName()); + break; + case "统一社会信用代码": + valueMap.put(dictData.getDictLabel(), affiliate.getIdentityNum()); + break; + case "法定代表人": + valueMap.put(dictData.getDictLabel(), affiliate.getCompLegalPerson()); + break; + case "法定代表人职位": + valueMap.put(dictData.getDictLabel(), affiliate.getCompLegalperPost()); + break; + case "申请人住所": + valueMap.put(dictData.getDictLabel(), affiliate.getResidenAffili()); + break; + case "申请人联系地址": + valueMap.put(dictData.getDictLabel(), affiliate.getContactAddress()); + break; + case "委托代理人姓名": + valueMap.put(dictData.getDictLabel(), affiliate.getNameAgent()); + break; + case "委托代理人联系电话": + valueMap.put(dictData.getDictLabel(), affiliate.getContactTelphoneAgent()); + break; + case "委托代理人电子邮件": + valueMap.put(dictData.getDictLabel(), affiliate.getAgentEmail()); + break; + default: + break; + } + } else { + valueMap.put(dictData.getDictLabel(), ObjectFieldUtils.getValue(caseApplication, dictData.getDictValue())); + } + } else { + valueMap.put(dictData.getDictLabel(), ObjectFieldUtils.getValue(caseApplication, dictData.getDictValue())); + } + + } + } + } + + /** + * 保存裁决书附件 + * + * @param id 案件id + * @param saveName 保存的文件名 + * @param savePath 保存路径 + * @param caseApplicationById 案件基本信息 + * @param arbitrateRecordSelect 出裁决书生成记录 + */ + private void saveArbitorFile(Long id, String saveName, String savePath, CaseApplication caseApplicationById, ArbitrateRecord arbitrateRecordSelect) { + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(3) + .build(); + //保存到附件表里,先判断之前有没有,有的话更新,没有的话新增 + List caseAttachList = caseAttachMapper.getCaseAttachByCaseIdAndType(caseAttach); + if (caseAttachList != null && caseAttachList.size() > 0) { + //之前已经生成过了,更新 + int i = caseAttachMapper.updateCaseAttachBycaseid(caseAttach); + } else { + //之前没生成过,新增 + int i = caseAttachMapper.save(caseAttach); + if (i > 0) { + if (arbitrateRecordSelect != null) { + Integer annexId = caseAttach.getAnnexId(); + //将附件id保存到仲裁记录表里面 + arbitrateRecordSelect.setAnnexId(annexId); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordSelect); + } + } + } + //修改案件状态 + caseApplicationById.setCaseStatus(CaseApplicationConstants.VERPRIF_ARBITRATION); + caseApplicationMapper.submitCaseApplication(caseApplicationById); + } + + @Override + @Transactional + public AjaxResult sendDocumentByEmail(Long id, String appEmail, String resEmail, String apptrackingNum, String restrackingNum) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 == null) { + return AjaxResult.error("未查询到相关案件"); + } + + //根据案件id查询裁决书 + try { + List fileList = new ArrayList<>(); + CaseApplication caseApplication2 = caseApplicationService.selectCaseApplication(caseApplication); + List caseAttachList = caseApplication2.getCaseAttachList(); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + if (caseAttach.getAnnexType() == 3) { + String annexPath = caseAttach.getAnnexPath(); + //File file = new File("/home/ruoyi/" + annexPath); + String path = "/home/ruoyi" + annexPath; + System.out.println("原文件路径是:" + path); + String newpath = path.replace("/", "\\"); + System.out.println("新文件路径是:" + newpath); + File file = new File(newpath); + System.out.println("新文件是:" + file); + fileList.add(file); + } + } + } + if (fileList.size() < 1) { + return AjaxResult.error("未查询到裁决书"); + } + File file = fileList.get(0); + //电子邮件送达 + JavaMailSender javaMailSender = emailOutUtil.rebuildMailSender(); + if (appEmail != null) { + emailOutUtil.sendMessageCarryFile(appEmail, "案件裁决书", "您的裁决书已送达,详情请查阅附件", file + , "hjbjava@163.com", javaMailSender); + } + if (resEmail != null) { + emailOutUtil.sendMessageCarryFile(resEmail, "案件裁决书", "您的裁决书已送达,详情请查阅附件", file + , "hjbjava@163.com", javaMailSender); + + } + //修改案件状态 + caseApplication1.setCaseStatus(CaseApplicationConstants.CASE_FILING); + caseApplicationMapper.submitCaseApplication(caseApplication1); + //保存邮箱信息和快递单号到关联人表 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + if (affiliate.getIdentityType() == 1) { //申请人 + affiliate.setSendEmail(appEmail); + affiliate.setTrackNum(apptrackingNum); + caseAffiliateMapper.updataCaseAffiliate(affiliate); + } else { + affiliate.setSendEmail(resEmail); + affiliate.setTrackNum(restrackingNum); + caseAffiliateMapper.updataCaseAffiliate(affiliate); + } + } + } + + return AjaxResult.success("仲裁文书送达成功"); + } catch (MailSendException e) { + return AjaxResult.error("发送失败,请检查文件路径"); + } + } + + @Override + public List getLogisticsInfo(CaseApplication caseApplication) { + try { + //快递单号查询 + String key = "729437f92468910aee6c12dbfeaee3c1"; + String com = "auto"; + //根据案件id查询单号信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List logisticsInfoVOList = new ArrayList<>(); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + LogisticsInfoVO logisticsInfoVO = new LogisticsInfoVO(); + String trackNum = affiliate.getTrackNum(); + if (trackNum != null) { + // 构造查询字符串参数 + String queryParameters = String.format("key=%s&com=%s&no=%s&phone=%d", + URLEncoder.encode(key, "UTF-8"), + URLEncoder.encode(com, "UTF-8"), + URLEncoder.encode(trackNum, "UTF-8"), null); + // 拼接到API URL中 + String fullUrl = apiUrl + "?" + queryParameters; + URL url = new URL(fullUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String line; + StringBuilder response = new StringBuilder(); + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + // 处理返回的响应数据\ + JSONObject jsonObject = JSON.parseObject(response.toString()); + // 提取 "data" 字段并转换为字符串 + String data = jsonObject.getString("data"); + if (data != null) { + logisticsInfoVO.setIdentityType(affiliate.getIdentityType()); + logisticsInfoVO.setLogisticsInfo(data); + logisticsInfoVOList.add(logisticsInfoVO); + } + } else { + // 请求失败 + return null; + } + } + } + return logisticsInfoVOList; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public AjaxResult signature(CaseApplication caseApplication) { + //更改案件状态(暂时) + caseApplication.setCaseStatus(CaseApplicationConstants.ARBITRATED_SEAL); + caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.ARBITRATED_SEAL, ""); + + return AjaxResult.success("签名成功,案件状态已改为待仲裁文书用印"); + } + + @Override + public AjaxResult caseFile(List ids) { + try { + for (Long id : ids) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + //更改案件状态(暂时) + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_ARCHIVED); + caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_ARCHIVED, ""); + } + } catch (Exception e) { + return AjaxResult.error(e.getMessage()); + } + + return AjaxResult.success("归档成功,案件状态已改为已归档"); + } + + @Override + @Transactional + public AjaxResult service(Long id, String appEmail, String resEmail, String apptrackingNum, String restrackingNum) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 == null) { + return AjaxResult.error("未查询到相关案件"); + } + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication1); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + if (caseAttach.getAnnexType() == 3) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile/upload/"; + int startIndex = prefix.length(); + String path = caseAttach.getAnnexPath() + annexName.substring(startIndex); + File file = new File(path); + // todo 部署放开 + if (!file.exists()) { + return AjaxResult.error("未生成裁决书"); + } + + } + } + } + //修改案件状态 + caseApplication1.setCaseStatus(CaseApplicationConstants.CASE_FILING); + caseApplicationMapper.submitCaseApplication(caseApplication1); + //保存邮箱信息和快递单号到关联人表 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + if (affiliate.getIdentityType() == 1) { //申请人 + affiliate.setSendEmail(appEmail); + affiliate.setTrackNum(apptrackingNum); + caseAffiliateMapper.updataCaseAffiliate(affiliate); + } else { + affiliate.setSendEmail(resEmail); + affiliate.setTrackNum(restrackingNum); + caseAffiliateMapper.updataCaseAffiliate(affiliate); + } + } + } + //申请人发送邮件 + boolean appEmailFlag = sendCaseEmail(caseApplication1, appEmail, caseAttachList); + SendMailRecord sendMailRecord = new SendMailRecord(); + sendMailRecord.setCaseId(id); + sendMailRecord.setMailAddress(appEmail); + sendMailRecord.setMailContent("您好,审核后的裁决书在附件中请查阅"); +// sendMailRecord.setMailContent("您好,您的{"+caseApplication1.getCaseNum()+"}案件,审核后的裁决书在附件中请查阅"); + sendMailRecord.setMailName("签署后的裁决书"); + sendMailRecord.setSendTime(new Date()); + sendMailRecord.setCreateBy(getUsername()); + if (appEmailFlag) { + sendMailRecord.setSendStatus(1); + } else { + sendMailRecord.setSendStatus(0); + } + sendMailRecordMapper.saveSendMailRecord(sendMailRecord); + // 被申请人发送邮件 + boolean resEmailFlag = sendCaseEmail(caseApplication1, resEmail, caseAttachList); + + SendMailRecord sendMailRecord1 = new SendMailRecord(); + sendMailRecord1.setCaseId(id); + sendMailRecord1.setMailAddress(resEmail); +// sendMailRecord.setMailContent("您好,您的{"+caseApplication1.getCaseNum()+"}案件,审核后的裁决书在附件中请查阅"); + sendMailRecord1.setMailContent("您好,审核后的裁决书在附件中请查阅"); + sendMailRecord1.setMailName("签署后的裁决书"); + sendMailRecord1.setSendTime(new Date()); + sendMailRecord1.setCreateBy(getUsername()); + if (resEmailFlag) { + sendMailRecord1.setSendStatus(1); + }else { + sendMailRecord1.setSendStatus(0); + } + sendMailRecordMapper.saveSendMailRecord(sendMailRecord1); + if(!appEmailFlag&&!resEmailFlag){ + throw new ServiceException("裁决书发送失败"); + } + if(!appEmailFlag){ + throw new ServiceException("申请人裁决书发送失败"); + } + if(!resEmailFlag){ + throw new ServiceException("被申请人裁决书发送失败"); + } + // 发送短信 + if (appEmailFlag||resEmailFlag) { + + if (CollectionUtil.isNotEmpty(caseAffiliates)) { + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1990362"); + for (CaseAffiliate affiliate : caseAffiliates) { + String telphone=null; + if(appEmailFlag&&affiliate.getIdentityType()==1){ + telphone = affiliate.getContactTelphone(); + }else if(resEmailFlag&&affiliate.getIdentityType()==2){ + telphone = affiliate.getContactTelphone(); + } + if(StrUtil.isEmpty(telphone)){ + continue; + } + + request.setPhone(telphone); +// if(affiliate.getIdentityType() == 1) { +// request.setTemplateParamSet(new String[]{caseAffiliate.getName(), caseApplication1.getCaseNum(), appEmail}); +// }else { +// request.setTemplateParamSet(new String[]{caseAffiliate.getName(), caseApplication1.getCaseNum(), resEmail}); +// } + request.setTemplateParamSet(new String[]{affiliate.getName(), caseApplication1.getCaseNum()}); + Boolean aBoolean = SmsUtils.sendSms(request); + + // 保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseAffiliate.getCaseAppliId()); + + smsSendRecord.setCaseNum(caseApplication1.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); +// // 尊敬的{1}用户,您的{2}仲裁案件,裁决书已送达,请知晓,如非本人操作,请忽略本短信。 +// if(affiliate.getIdentityType() == 1) { +// smsSendRecord.setSendContent("尊敬的" + caseAffiliate.getName() + "用户,您的" + caseApplication1.getCaseNum() + "仲裁案件,裁决书已送达至" +appEmail+"邮箱,请知晓,如非本人操作,请忽略本短信。"); +// }else { +// smsSendRecord.setSendContent("尊敬的" + caseAffiliate.getName() + "用户,您的" + caseApplication1.getCaseNum() + "仲裁案件,裁决书已送达至" +resEmail+"邮箱,请知晓,如非本人操作,请忽略本短信。"); +// } + smsSendRecord.setSendContent("尊敬的" + affiliate.getName() + "用户,您的" + caseApplication1.getCaseNum() + "仲裁案件,裁决书已送达,请知晓,如非本人操作,请忽略本短信。"); + + + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + + + } + + } + + } + + + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_FILING, ""); + + return AjaxResult.success("仲裁文书送达成功"); + } + + /** + * 通过邮件发送裁决书文件 + * + * @param caseApplication1 + */ + private boolean sendCaseEmail(CaseApplication caseApplication1, String email, List caseAttachList) { + List fileList = new ArrayList<>(); + File file = null; + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + if (caseAttach.getAnnexType() == 3) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile/upload/"; + int startIndex = prefix.length(); + String path = caseAttach.getAnnexPath() + annexName.substring(startIndex); + // todo 部署放开 + file = new File(path); +// file = new File("D:\\home\\ruoyi\\uploadPath\\upload\\2023\\09\\b10b20d66cfa44df8995c3999e3b6266.pdf"); + fileList.add(file); + System.out.println("文件长度==================:" + file.length()); + } + } + } + + if (file != null && file.exists()) { + try { + Boolean aBoolean = emailOutUtil.sendEmil(email, "您好,审核后的裁决书在附件中请查阅", "签署后的裁决书", fileList, null); + +// String appUid = UUID.randomUUID().toString(); +// Boolean aBoolean = emailOutUtil.sendEmil(email, "您好,您的{"+caseApplication1.getCaseNum()+"}案件,审核后的裁决书在附件中请查阅", appUid +"裁决书", fileList, null); +// // Thread.sleep(20); + // 收到退信的所有id,即发送失败的uuid + // emailOutUtil.receiverMail(); + // Thread.sleep(3); + // List messageIds = emailOutUtil.receiverMail(); +// if (aBoolean&&(CollectionUtil.isEmpty(messageIds)||!messageIds.contains(appUid))) { +// return Boolean.TRUE; +// } + if (aBoolean) { + return Boolean.TRUE; + } + } catch (Exception e) { + System.out.println("邮件发送失败++++++++++++++++++++++++++++++++"); + System.out.println(e.toString()); + return Boolean.FALSE; + } + } + return Boolean.FALSE; + } + + @Override + public AjaxResult stamp(CaseApplication caseApplication) { + //更改案件状态(暂时) + caseApplication.setCaseStatus(CaseApplicationConstants.ARBITRATION_DELIVERY); + caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.ARBITRATION_DELIVERY, ""); + + return AjaxResult.success("用印成功,案件状态已改为待仲裁文书送达"); + } + + @Override + public AjaxResult getArchivesDetail(Long id) { + ArchivesDetailVO archivesDetailVO = new ArchivesDetailVO(); + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + //查询案件信息 +// CaseApplication caseApplication1 = caseApplicationService.selectCaseApplication(caseApplication); +// if (caseApplication1 != null) { +// archivesDetailVO.setCaseApplication(caseApplication1); +// } + //查询案件日志信息 +// CaseLogRecord caseLogRecord = new CaseLogRecord(); +// caseLogRecord.setCaseAppliId(id); +// List caseLogRecords = caseLogRecordService.selectCaseLogRecordList(caseLogRecord); +// if (caseLogRecords != null && caseLogRecords.size() > 0) { +// archivesDetailVO.setCaseLogRecordList(caseLogRecords); +// } + //查询快递信息 + List logisticsInfo = this.getLogisticsInfo(caseApplication); + if (logisticsInfo != null && logisticsInfo.size() > 0) { + archivesDetailVO.setLogisticsInfoVOList(logisticsInfo); + } + return AjaxResult.success(archivesDetailVO); + } + + @Override + @Transactional + public AjaxResult regenerationDocument(CaseApplication caseApplication) { + try { + Map datas = new HashMap<>(); + Long id = caseApplication.getId(); + if (id == null) { + return null; + } + //获取案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + //生成编码 + String equipmentNo = getNewEquipmentNo(); + datas.put("num", equipmentNo); + //获取仲裁记录相关信息 + ArbitrateRecord arbitrateRecord1 = caseApplication.getArbitrateRecord(); + + //获取案件关联人信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + List nameAgentList = new ArrayList<>(); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + if (identityType == 1) { //申请人 + datas.put("appName", affiliate.getName()); + datas.put("appAddress", affiliate.getResidenAffili()); + datas.put("appContactAddress", affiliate.getContactAddress()); + datas.put("appLegalPerson", affiliate.getCompLegalPerson()); + datas.put("appLegalPersonTitle", affiliate.getCompLegalperPost()); + datas.put("appAgentName", affiliate.getNameAgent()); + datas.put("appAgentTitle", affiliate.getAppliAgentTitle()); + nameAgentList.add(affiliate.getNameAgent()); + } else if (identityType == 2) { //被申请人 + datas.put("resName", affiliate.getName()); + datas.put("resAddress", affiliate.getResidenAffili()); + String responSex = affiliate.getResponSex(); + if (responSex.equals("0")) { + datas.put("resSex", "男"); + } else { + datas.put("resSex", "女"); + } + Date responBirth = affiliate.getResponBirth(); + if (responBirth != null) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String responBirthStr = sdf.format(responBirth); + datas.put("resDateOfBirth", responBirthStr); + } + datas.put("resContactAddress", affiliate.getContactAddress()); + nameAgentList.add(affiliate.getNameAgent()); + } + } + } + Date createTime = caseApplication1.getCreateTime(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + // 将日期格式化为字符串 + String createTimeStr = sdf.format(createTime); + datas.put("submissionDate", createTimeStr); + Date registerDate = caseApplication1.getRegisterDate(); + String registerDateStr = sdf.format(registerDate); + datas.put("acceptDate", registerDateStr); + //反请求 + Integer adjudicaCounter = caseApplication1.getAdjudicaCounter(); + String counterclaim = "在《2022年版仲裁规则》第十八条第(一)项规定的期限内,被申请人向秘书处提交了" + + "《仲裁反请求申请书》及证据材料。仲裁委依据《2022年版仲裁规则》第十八条的规定受理了该仲裁反请求案申请。" + + "仲裁反请求案件受理后,秘书处向被申请人发送了仲裁反请求通知书及附件,向申请人发送了仲裁反请求通知书及附件、仲裁反请求申请书及附件。"; + if (adjudicaCounter == null) { + datas.put("counterclaim", null); + } else if (adjudicaCounter == 1) { + datas.put("counterclaim", counterclaim); + } else { + datas.put("counterclaim", null); + } + //财产保全 + Integer properPreser = caseApplication1.getProperPreser(); + String preservation = "本案受理后,申请人向仲裁委提交了财产保全申请,仲裁委根据《中华人民共和国仲裁法》" + + "第二十八条之规定,将该申请提交至法院。"; + if (properPreser == null) { + datas.put("preservation", null); + } else if (properPreser == 1) { + datas.put("preservation", preservation); + } else { + datas.put("preservation", null); + } + //管辖权异议 + Integer objectiJuris = caseApplication1.getObjectiJuris(); + String jurisdictionalObjection = "本案受理后,被申请人向仲裁委提交了《管辖异议申请书》,认为" + + ",仲裁委经审理,当庭驳回了被申请人的管辖异议申请,并告知被申请人具体的事实和理由将在裁决书中一并列明。"; + if (objectiJuris == null) { + datas.put("jurisdictionalObjection", null); + } else if (objectiJuris == 1) { + datas.put("jurisdictionalObjection", jurisdictionalObjection); + } else { + datas.put("jurisdictionalObjection", null); + } + String arbitratorName = caseApplication1.getArbitratorName(); + datas.put("arbitratorName", arbitratorName); + Integer arbitratMethod = caseApplication1.getArbitratMethod(); + Date hearDate = caseApplication1.getHearDate(); + String hearDateStr = ""; + if (hearDate != null) { + hearDateStr = sdf.format(hearDate); + } + //线上开庭时 + if (arbitratMethod == 1) { + String onLine1 = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于"; + String onLine2 = "通过仲裁委智慧仲裁平台开庭审理了本案。"; + datas.put("onLine1", onLine1); + datas.put("hearDate", hearDateStr); + datas.put("onLine2", onLine2); + } else { + //书面仲裁时 + String written1 = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于"; + String written2 = "在仲裁委所在地开庭审理了本案。"; + datas.put("written1", written1); + datas.put("hearDate1", hearDateStr); + datas.put("written2", written2); + } + Integer isAbsence = caseApplication1.getIsAbsence(); + if (isAbsence == null) { + datas.put("absent1", null); + datas.put("absent2", null); + datas.put("absent3", null); + datas.put("absent4", null); + datas.put("absent5", null); + datas.put("attend1", null); + datas.put("attend2", null); + datas.put("attend3", null); + datas.put("attend4", null); + datas.put("attend5", null); + datas.put("attend6", null); + datas.put("attend7", null); + datas.put("appAgentName1", null); + datas.put("appAgentName2", null); + datas.put("resAgentName", null); + } else if (isAbsence == 1) { + //缺席审理 + String absent1 = "申请人的特别授权委托代理人"; + String absent2 = "出席了庭审。被申请人经依法送达开庭通知,无正当理由未出席庭审,故仲裁庭依据" + + "《2022年版仲裁规则》第四十条第(二)项的规定,对本案进行了缺席审理。"; + String absent3 = "庭审中,申请人陈述了仲裁请求事项及事实与理由,出示了证据材料并进行了说明," + + "发表了意见,回答了仲裁庭的提问,并作了最后陈述。因被申请人缺席庭审,故仲裁庭无法组织调解。"; + String absent4 = "(二/三)当事人提供的证据材料\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:"; + String absent5 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第四十条第(二)项、第五十一条的规定,缺席裁决如下:"; + datas.put("absent1", absent1); + datas.put("absent2", absent2); + datas.put("absent3", absent3); + datas.put("absent4", absent4); + datas.put("absent5", absent5); + datas.put("appAgentName1", nameAgentList.get(0)); + } else { + //出席审理 + String attend1 = "申请人的特别授权委托代理人"; + String attend2 = "和被申请人本人/的特别授权委托代理人"; + String attend3 = "出席了庭审。"; + String attend4 = "庭审中,申请人陈述了仲裁请求事项及所依据的事实与理由,被申请人进行了答辩;" + + "双方当事人均出示了证据材料并对对方的证据材料进行了质证;申请人出示了证据材料," + + "被申请人对对方的证据材料进行了质证;双方当事人均回答了仲裁庭的提问,进行了辩论," + + "并分别作了最后陈述。双方当事人在仲裁庭的主持下进行了调解,但未能达成调解协议。"; + String attend5 = "(二)被申请人的答辩意见"; + String attend6 = "(二/三)当事人提供的证据材料及对方的质证意见\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:"; + String attend7 = "被申请人对上述材料的质证意见为:"; + datas.put("attend1", attend1); + datas.put("attend2", attend2); + datas.put("attend3", attend3); + datas.put("attend4", attend4); + datas.put("attend5", attend5); + datas.put("attend6", attend6); + datas.put("attend7", attend7); + datas.put("responCrossOpin", caseApplication1.getResponCrossOpin()); + datas.put("appAgentName2", nameAgentList.get(0)); + datas.put("resAgentName", nameAgentList.get(1)); + if (arbitratMethod == 1) { + //被申出席+开庭 + String attend8 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第五十一条的规定,裁决如下:"; + datas.put("attend8", attend8); + } else { + //被申出席+书面 + String attend9 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第五十一条、第五十八条的规定,裁决如下:"; + datas.put("attend9", attend9); + } + } + datas.put("claims", caseApplication1.getArbitratClaims()); + datas.put("request", caseApplication1.getRequestRule()); + CaseApplication caseApplication2 = caseApplicationService.selectCaseApplication(caseApplication); + List caseAttachList1 = caseApplication2.getCaseAttachList(); + if (caseAttachList1 != null && caseAttachList1.size() > 0) { + for (CaseAttach caseAttach : caseAttachList1) { + if (caseAttach.getAnnexType() == 6) { //被申请人证据材料 + String annexName = caseAttach.getAnnexName(); + boolean isImageFile = Pattern.matches(".*\\.(jpg|png|gif|bmp)$", annexName); + if (isImageFile) { + String annexPath = "/home/ruoyi" + caseAttach.getAnnexPath(); + System.out.println("路径是===========" + annexPath); + PictureRenderData pictureRenderData = WordUtil + .rebuildImageContent(100, 100, null, annexPath); + datas.put("resEvidenceMaterial", pictureRenderData); + } + } else if (caseAttach.getAnnexType() == 2) { //申请人证据材料 + String annexName = caseAttach.getAnnexName(); + boolean isImageFile = Pattern.matches(".*\\.(jpg|png|gif|bmp)$", annexName); + if (isImageFile) { + String annexPath = "/home/ruoyi" + caseAttach.getAnnexPath(); + System.out.println("路径是===========" + annexPath); + PictureRenderData pictureRenderData = WordUtil + .rebuildImageContent(100, 100, null, annexPath); + //申请人证据材料 + datas.put("appEvidenceMaterial", pictureRenderData); + } + } + } + } + datas.put("applicaCrossOpin", "被申请人证据不足,无法说明事实"); + + datas.put("factDetermi", "被申请人欠款属实"); + datas.put("arbitrateThink", "被申请人应按约定还款"); + datas.put("rulingFollows", "被申请人依法偿还申请人欠款"); + + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + datas.put("year", year); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String modalFilePath = "/data/arbitrate-document/template/新裁决书模板.docx"; +// String modalFilePath = "D:/develop/新裁决书模板.docx"; + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; +// String saveFolderPath = "D:/data/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".docx"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String resultFilePath = saveFolderPath + "/" + fileName; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + Path sourcePath = new File(modalFilePath).toPath(); + Path destinationPath = new File(resultFilePath).toPath(); + Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + String docFilePath = WordUtil.getDocFilePath(datas, modalFilePath, resultFilePath); + String savePath = docFilePath.substring(0, docFilePath.indexOf("/upload/") + 8); + + + //将裁决书更新到附件表里 + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(3) + .build(); + int i = caseAttachMapper.updateCaseAttachBycaseid(caseAttach); + + + if (i > 0) { + if (arbitrateRecord1 != null) { + //将仲裁记录更新到仲裁记录表 + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord1); + } + } + + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + return AjaxResult.success(caseAttach); + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error("重新生成裁决书异常"); + } + } + + @Override + public AjaxResult emailByCaseId(Long id) { + List list = caseAffiliateMapper.emailByCaseId(id); + BookSendVO bookSendVO = new BookSendVO(); + if (CollectionUtil.isNotEmpty(list)) { + for (CaseAffiliate caseAffiliate : list) { + // 申请人邮箱 + if (caseAffiliate.getIdentityType() == 1) { + bookSendVO.setAppEmail(caseAffiliate.getEmail()); + } else { + // 被申请人邮箱 + bookSendVO.setResEmail(caseAffiliate.getEmail()); + } + } + } + return AjaxResult.success(bookSendVO); + } + + private void setExecList(List execList, List columnValueList) { + if (CollectionUtil.isNotEmpty(columnValueList)) { + Function, Integer> function = columnValueMapper::batchSave; + execList.add(new MultipleThreadListParam(function, columnValueList)); + } + + } + + @Transactional + @Override + public AjaxResult batchDocument(List ids) { + // todo 多线程生成裁决书 +// List execList=new ArrayList<>(); +// if(CollectionUtil.isNotEmpty(columnValueList)) { +// setExecList(execList, columnValueList); +// } +// +// if(CollectionUtil.isNotEmpty(execList)){ +// MultipleThreadWorkUtil.execListFun(execList.toArray(new MultipleThreadListParam[execList.size()])); +// } + for (Long id : ids) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + createDocument(caseApplication); + } + + return AjaxResult.success(); + } + + /** + * 根据签署流程id查询批量签名链接 + * + * @param idsReq + * @return + */ + @Override + public SealSignRecord selectBatchSignUrl(StringIdsReq idsReq) { + SealSignRecord signRecord = new SealSignRecord(); + + try { + EsignHttpResponse identityInfo = SignAward.identityInfo(idsReq); + + Gson gson = new Gson(); + if (StrUtil.isNotEmpty(identityInfo.getBody())) { + JsonObject identityInfoJsonObject = gson.fromJson(identityInfo.getBody(), JsonObject.class); + if (identityInfoJsonObject != null && !identityInfoJsonObject.get("data").isJsonNull()) { + JsonObject identityInfoData = identityInfoJsonObject.getAsJsonObject("data"); + if (identityInfoData != null && !identityInfoData.get("psnId").isJsonNull()) { + idsReq.setPsnId(identityInfoData.get("psnId").getAsString()); + } + } + } + if (StrUtil.isEmpty(idsReq.getPsnId())) { + throw new ServiceException("该用户未认证"); + } + EsignHttpResponse batchSignUrl = SignAward.batchSignUrl(idsReq); + if (StrUtil.isNotEmpty(batchSignUrl.getBody())) { + JsonObject signUrlJsonObject = gson.fromJson(batchSignUrl.getBody(), JsonObject.class); + if (signUrlJsonObject != null && !signUrlJsonObject.get("data").isJsonNull()) { + JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); + if (signUrlData != null && !signUrlData.get("batchSignUrlWithoutLogin").isJsonNull()) { + // 免登录批量签链接(链接有效期2小时) + String url = signUrlData.get("batchSignUrlWithoutLogin").getAsString(); + // batchSignUrl 需登录批量签链接(链接有效期2小时),batchSignShortUrl需登录批量签短链接(链接有效期2小时),batchSignShortUrlWithoutLogin免登录批量签短链接(链接有效期2小时) + signRecord.setSignUrl(url); + } + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } + + return signRecord; + } + + @Override + public SealSignRecord selectBatchSealUrl(StringIdsReq idsReq) { + SealSignRecord signRecord = new SealSignRecord(); + + try { + EsignHttpResponse identityInfo = SignAward.identityInfo(idsReq); + + Gson gson = new Gson(); + if (StrUtil.isNotEmpty(identityInfo.getBody())) { + JsonObject identityInfoJsonObject = gson.fromJson(identityInfo.getBody(), JsonObject.class); + if(identityInfoJsonObject!=null&&!identityInfoJsonObject.get("data").isJsonNull()) { + JsonObject identityInfoData = identityInfoJsonObject.getAsJsonObject("data"); + if (identityInfoData != null && !identityInfoData.get("psnId") .isJsonNull()) { + idsReq.setPsnId(identityInfoData.get("psnId").getAsString()); + } + } + } + if (StrUtil.isEmpty(idsReq.getPsnId())) { + throw new ServiceException("该用户未认证"); + } + EsignHttpResponse batchSignUrl = SignAward.batchSignUrl(idsReq); + if (StrUtil.isNotEmpty(batchSignUrl.getBody())) { + JsonObject signUrlJsonObject = gson.fromJson(batchSignUrl.getBody(), JsonObject.class); + if (signUrlJsonObject != null && !signUrlJsonObject.get("data").isJsonNull()) { + JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); + if (signUrlData != null&& !signUrlData.get("batchSignUrlWithoutLogin").isJsonNull()) { + // 免登录批量签链接(链接有效期2小时) + String url = signUrlData.get("batchSignUrlWithoutLogin").getAsString(); + // batchSignUrl 需登录批量签链接(链接有效期2小时),batchSignShortUrl需登录批量签短链接(链接有效期2小时),batchSignShortUrlWithoutLogin免登录批量签短链接(链接有效期2小时) + signRecord.setSignUrl(url); + } + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } + + return signRecord; + } + + /** + * 根据仲裁员手机号分页查询等待签署,签署中的裁决书 + * + * @param personAccount 仲裁员手机号 + * @return + */ + @Override + public List selectSealSigning(String personAccount, Integer caseStatus) { + return sealSignRecordMapper.selectSealSigning(personAccount, caseStatus); + } + + + public String getNewEquipmentNo() { + Object awardNum = redisCache.getCacheObject("awardNum"); + if (awardNum == null) { + redisCache.setCacheObject("awardNum", "00001"); + String s = redisCache.getCacheObject("awardNum").toString(); + // 字符串数字解析为整数 + int no = Integer.parseInt(s); + // 最新设备编号自增1 + int newEquipment = ++no; + // 将整数格式化为5位数字 + s = String.format("%05d", newEquipment); + redisCache.setCacheObject("awardNum", s); + return s; + } else { + String s = awardNum.toString(); + // 字符串数字解析为整数 + int no = Integer.parseInt(s); + // 最新设备编号自增1 + int newEquipment = ++no; + // 将整数格式化为5位数字 + s = String.format("%05d", newEquipment); + redisCache.setCacheObject("awardNum", s); + return s; + } + } + + /** + * 根据裁决书模板获取所有的占位符,占位符必须是{{name}}格式 + * + * @param path + * @return + */ + public List getBookmarkByDocx(String path) { + XWPFDocument xwpfDocument = null; + try { + log.error("path====" + path); + FileInputStream fileInputStream = new FileInputStream(path); + log.error("fileInputStream===="); + xwpfDocument = new XWPFDocument(fileInputStream); + log.error("xwpfDocument====" + xwpfDocument); + } catch (IOException e) { + e.printStackTrace(); + } + if (xwpfDocument == null) { + return new ArrayList<>(); + } + List paragraphs = xwpfDocument.getParagraphs(); + if (CollectionUtil.isEmpty(xwpfDocument.getParagraphs())) { + return new ArrayList<>(); + } + String regex = "\\{\\{.*?\\}\\}"; // 定义占位符的正则表达式 + Pattern pattern = Pattern.compile(regex); + List bookmarkList = new ArrayList<>(); + for (XWPFParagraph paragraph : paragraphs) { + String text = paragraph.getText(); + if (StrUtil.isNotEmpty(text)) { + Matcher matcher = pattern.matcher(text); + + while (matcher.find()) { + String placeholder = matcher.group(); + String keyword = placeholder.substring(2, placeholder.length() - 2); + bookmarkList.add(keyword); + } + } + } + return bookmarkList; + } + + +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/ArbitratorServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/ArbitratorServiceImpl.java new file mode 100644 index 0000000..78f9e4b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/ArbitratorServiceImpl.java @@ -0,0 +1,28 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import com.ruoyi.wisdomarbitrate.domain.Arbitrator; +import com.ruoyi.wisdomarbitrate.mapper.ArbitratorMapper; +import com.ruoyi.wisdomarbitrate.service.IArbitratorService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ArbitratorServiceImpl implements IArbitratorService { + @Autowired + private ArbitratorMapper arbitratorMapper; + + + @Override + public List selectArbitratorList(Arbitrator arbitrator) { + return arbitratorMapper.selectArbitratorList(arbitrator); + + } + + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java new file mode 100644 index 0000000..dfa8aca --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java @@ -0,0 +1,36 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import com.ruoyi.CallBackService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 业务回调处理 + */ +@Component +@Slf4j +public class CallBackHandleServiceImpl implements CallBackService { + @Autowired + private CasePaymentServiceImpl casePaymentService; + + @Override + public void successPay(String orderSn) { + casePaymentService.callback(orderSn); + } + + @Override + public void failPay(String orderSn) { + log.info("支付失败回调!"+orderSn); + } + + @Override + public void successRefund(String orderSn) { + log.info("退款成功回调!"+orderSn); + } + + @Override + public void failRefund(String orderSn) { + log.info("退款失败回调!"+orderSn); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationLogServiceImpl.java new file mode 100644 index 0000000..d879caf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationLogServiceImpl.java @@ -0,0 +1,512 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.enums.UpdateSubmitStatus; +import com.ruoyi.common.enums.YesOrNoEnum; +import com.ruoyi.common.utils.ObjectFieldUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import com.ruoyi.wisdomarbitrate.domain.SmsSendRecord; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import com.ruoyi.wisdomarbitrate.domain.vo.CompareCaseVO; +import com.ruoyi.wisdomarbitrate.domain.vo.UpdateSubmitVO; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.CaseApplicationLogService; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +/** + * @author wangqiong + * @description 案件日志 + * @date 2023-11-17 14:05 + */ +@Service +public class CaseApplicationLogServiceImpl implements CaseApplicationLogService { + @Autowired + private CaseApplicationLogMapper caseApplicationLogMapper; + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private CaseAffiliateLogMapper caseAffiliateLogMapper; + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private CaseAttachLogMapper caseAttachLogMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + @Autowired + private ICaseApplicationService caseApplicationService; + @Autowired + private ColumnValueLogMapper columnValueLogMapper; + // 对比两个版本修改的字段,基本字段对比 + private static final String[] columns = {"caseName","caseSubjectAmount","loanStartDate", "loanEndDate","contractNumber","claimInterestOwed","claimLiquidDamag", + "claimPrinciOwed","arbitratClaims","properPreser","requestRule","facts"}; + // 人员字段对比 + private static final String[] affiliateColumns = {"name", "identityNum","contactTelphone","contactAddress","workTelphone","workAddress","email", + "nameAgent", "identityNumAgent","contactTelphoneAgent","contactAddressAgent","residenAffili","compLegalPerson", + "compLegalperPost","responSex","responBirth"}; + @Override + public int insert(CaseApplication caseApplicationLog) { + return caseApplicationLogMapper.insert(caseApplicationLog); + } + + @Override + public int delete(Long id) { + return caseApplicationLogMapper.deleteById(id); + } + + + + @Override + public CaseApplication selectByCaseIdAndVersion(Long id, int version) { + return caseApplicationLogMapper.selectByCaseIdAndVersion(id,version); + } + /** + * 修改的案件提交到秘书 + * @param vo + * @return + */ + @Override + public AjaxResult submit(UpdateSubmitVO vo) { + vo.setUpdateSubmitStatus(UpdateSubmitStatus.COMMITTED.getCode()); + // 修改日志表提交状态 + caseApplicationLogMapper.updateStatus(vo); + return AjaxResult.success(); + } + @Transactional + @Override + public AjaxResult revoke(UpdateSubmitVO vo) { + // 根据案件id和版本号查询改案件 + CaseApplication caseApplication = caseApplicationLogMapper.selectByCaseIdAndVersion(vo.getCaseId(), vo.getVersion()); + if(caseApplication == null){ + return AjaxResult.error("案件不存在"); + } + // 如果秘书没有审核,将撤销状态改为同意撤销,否则改为撤销 + if(caseApplication.getUpdateSubmitStatus()!=null && !caseApplication.getUpdateSubmitStatus().equals(UpdateSubmitStatus.AGREE.getCode())){ + agreeRevoke(vo); + + }else { + vo.setUpdateSubmitStatus(UpdateSubmitStatus.REVOKE.getCode()); + // 修改日志表提交状态 + caseApplicationLogMapper.updateStatus(vo); + } + + return AjaxResult.success(); + } + + /** + * 秘书审核修改的案件 + * @param vo + * @return + */ + @Transactional + @Override + public AjaxResult updateAudit(UpdateSubmitVO vo) { + if (Objects.equals(vo.getUpdateSubmitStatus(), UpdateSubmitStatus.COMMITTED.getCode())) { + // 审核修改提交状态 + if (Objects.equals(vo.getIsAgree(), YesOrNoEnum.YES.getCode())) { + // 如果版本号为1,则直接返回 + if(vo.getVersion() <= 1){ + vo.setUpdateSubmitStatus(UpdateSubmitStatus.AGREE.getCode()); + caseApplicationLogMapper.updateStatus(vo); + return AjaxResult.success(); + } + // 同意,查询日志记录表本版本数据,将数据更新到主表,并将日志表改版本的状态改为同意 + // 查询日志记录表本版本数据 + CaseApplication caseApplicationLog = caseApplicationLogMapper.selectByCaseIdAndVersion(vo.getCaseId(), vo.getVersion()); + if (caseApplicationLog == null) { + return AjaxResult.error("未找到该案件"); + } + // 将日志表改版本的状态改为同意 + vo.setUpdateSubmitStatus(UpdateSubmitStatus.AGREE.getCode()); + caseApplicationLogMapper.updateStatus(vo); + // 根据caseLogId查询相关人员表 + List affiliateLogList = caseAffiliateLogMapper.selectCaseAffiliate(caseApplicationLog.getCaseLogId()); + // 更新案件主表 + caseApplicationMapper.updataCaseApplication(caseApplicationLog); + + // 更新相关人员主表 + if(CollectionUtil.isNotEmpty(affiliateLogList)){ + caseAffiliateMapper.deleteByCaseId(vo.getCaseId()); + for (CaseAffiliate caseAffiliate : affiliateLogList) { + caseAffiliate.setCaseAppliId(vo.getCaseId()); + + } + caseAffiliateMapper.batchCaseAffiliate(affiliateLogList); + } + // // 根据caseLogId查询案件记录附件表 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setCaseLogId(caseApplicationLog.getCaseLogId()); + caseApplication.setAnnexType(2); + List attachLogList = caseAttachLogMapper.queryCaseAttachList(caseApplication); + // 更新记录附件表 + if(CollectionUtil.isNotEmpty(attachLogList)){ + for (CaseAttach caseAttach : attachLogList) { + caseAttach.setCaseAppliId(vo.getCaseId()); + caseAttachMapper.updateCaseAttach(caseAttach); + } + } + // 更新自定义字段表 + // 根据caseLogId查询自定义字段表 + List columnValueList = columnValueLogMapper.listBycaseAppliLogId(caseApplicationLog.getCaseLogId()); + if(CollectionUtil.isNotEmpty(columnValueList)){ + for (ColumnValue columnValue : columnValueList) { + columnValue.setCaseAppliLogId(vo.getCaseId()); + + } + columnValueLogMapper.batchUpdate(columnValueList); + } + } else { + // 拒绝,将日志表改版本的状态改为拒绝 + vo.setUpdateSubmitStatus(UpdateSubmitStatus.REFUSE.getCode()); + caseApplicationLogMapper.updateStatus(vo); + return sendAuditMessage(vo); + } + return AjaxResult.success(); + } else if (Objects.equals(vo.getUpdateSubmitStatus(), UpdateSubmitStatus.REVOKE.getCode())) { + // 审核修改撤销状态 + if (Objects.equals(vo.getIsAgree(), YesOrNoEnum.YES.getCode())) { + // 同意撤销 + agreeRevoke(vo); + } else { + // 拒绝撤销,将日志表改版本的状态改为拒绝撤销 + vo.setUpdateSubmitStatus(UpdateSubmitStatus.REFUSE_REVOKE.getCode()); + caseApplicationLogMapper.updateStatus(vo); + return sendAuditMessage(vo); + } + return AjaxResult.success(); + } + return AjaxResult.success(); + } + + /** + * 给申请人发送短信 + * @param vo + * @return + */ + private AjaxResult sendAuditMessage(UpdateSubmitVO vo) { + // 查询申请人 + CaseApplication logCase = caseApplicationLogMapper.selectByCaseIdAndVersion(vo.getCaseId(), vo.getVersion()); + if(logCase == null){ + return AjaxResult.success(); + } + CaseAffiliate caseAffiliate = caseAffiliateLogMapper.selectCaseAffiliateByIdentityType(logCase.getCaseLogId(), 1); + if(caseAffiliate == null){ + return AjaxResult.success(); + } + + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1996949"); + request.setPhone(caseAffiliate.getContactTelphone()); + request.setTemplateParamSet(new String[]{caseAffiliate.getName(), logCase.getCaseNum(),vo.getReason()}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseAffiliate.getCaseAppliId()); + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseAffiliate.getCaseAppliId()); + caseApplication = caseApplicationMapper.selectCaseApplication(caseApplication); + smsSendRecord.setCaseNum(caseApplication.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + // 1996949 审核案件结果通知 尊敬的{1}用户,您的{2}仲裁案件,审核未通过,理由为{3},请知晓,如非本人操作,请忽略本短信 + String content = "尊敬的" + caseAffiliate.getName() + ",您的"+logCase.getCaseNum()+"仲裁案件,审核未通过,理由为"+vo.getReason()+",请知晓,如非本人操作,请忽略本短信。"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + return AjaxResult.success(); + } + + @Override + public AjaxResult selectCompareCase(UpdateSubmitVO vo) { + // 查询当前版本号和主表的案件 + CaseApplication afterCase = caseApplicationLogMapper.selectByCaseIdAndVersion(vo.getCaseId(), vo.getVersion()); + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setCaseAppliId(vo.getCaseId()); + caseApplication.setId(vo.getCaseId()); + CaseApplication beforeCase = caseApplicationService.selectCaseApplication(caseApplication); + + // 查询案件关联人员 + afterCase.setCaseAffiliates(caseAffiliateLogMapper.selectCaseAffiliate(afterCase.getCaseLogId())); + // 查询自定义字段表 + afterCase.setColumnValues(columnValueLogMapper.listBycaseAppliLogId(afterCase.getCaseLogId())); + // 查询附件 + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setCaseAppliLogId(beforeCase.getCaseLogId()); + caseAttach.setAnnexType(2); + caseAttachLogMapper.getCaseAttachByCaseIdAndType(caseAttach); + caseAttach.setCaseAppliLogId(afterCase.getCaseLogId()); + List afterAttachList = caseAttachLogMapper.getCaseAttachByCaseIdAndType(caseAttach); + if (CollectionUtil.isNotEmpty(afterAttachList)) { + for (CaseAttach attach : afterAttachList) { + String annexName = attach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + attach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + attach.setAnnexName(annexNamenew); + } + } + afterCase.setCaseAttachList(afterAttachList); + } + afterCase.setCaseAttachList(afterAttachList); + CompareCaseVO compareCaseVO = new CompareCaseVO(); + compareCaseVO.setBeforeCase(beforeCase); + compareCaseVO.setAfterCase(afterCase); + + StringBuilder changeColumn = new StringBuilder(); + // 对比基本字段 + for (String column : columns) { + String beforeValue = ObjectFieldUtils.getValue(beforeCase, column); + String afterValue = ObjectFieldUtils.getValue(afterCase, column); + if (StrUtil.isEmpty(beforeValue) && StrUtil.isNotEmpty(afterValue)) { + changeColumn.append(column).append(","); + continue; + } + if (StrUtil.isNotEmpty(beforeValue) && StrUtil.isEmpty(afterValue)) { + changeColumn.append(column).append(","); + continue; + } + if (StrUtil.isNotEmpty(beforeValue) && StrUtil.isNotEmpty(afterValue) && !Objects.equals(beforeValue, afterValue)) { + changeColumn.append(column).append(","); + continue; + + } + + } + // 对比案件人员字段 + compareAffilate(beforeCase, afterCase); + // 对比申请人证据资料 + compareCaseVO.setChangeColumn(compareApplicantFile(beforeCase, afterCase, changeColumn).toString()); + // 对比自定义字段 + // + List beforeColumnValues = beforeCase.getColumnValues(); + List afterColumnValues = afterCase.getColumnValues(); + StringBuilder columnValueChange = new StringBuilder(); + + if (CollectionUtil.isNotEmpty(beforeColumnValues) && CollectionUtil.isNotEmpty(afterColumnValues)) { + Map beforeColumnValueMap = beforeColumnValues.stream().collect(Collectors.toMap(ColumnValue::getColumn, ColumnValue::getValue, (n1, n2) -> n2)); + for (ColumnValue afterColumnValue : afterColumnValues) { + // 改变前字段不包含改变后字段 + if (!beforeColumnValueMap.containsKey(afterColumnValue.getColumn())) { + columnValueChange.append(afterColumnValue.getColumn()).append(","); + } else { + // 都有这个字段,比较内容是否相同 + // 修改后为空,修改前不为空 + if (StrUtil.isEmpty(afterColumnValue.getValue()) && StrUtil.isNotEmpty(beforeColumnValueMap.get(afterColumnValue.getColumn()))) { + columnValueChange.append(afterColumnValue.getColumn()).append(","); + } else if (StrUtil.isNotEmpty(afterColumnValue.getValue()) && StrUtil.isEmpty(beforeColumnValueMap.get(afterColumnValue.getColumn()))) { + // 修改前为空,修改后不为空 + columnValueChange.append(afterColumnValue.getColumn()).append(","); + } else if (StrUtil.isNotEmpty(afterColumnValue.getValue()) && StrUtil.isNotEmpty(beforeColumnValueMap.get(afterColumnValue.getColumn())) + && !afterColumnValue.getValue().equals(beforeColumnValueMap.get(afterColumnValue.getColumn()))) { + // 修改前不为空,修改后不为空,内容不同 + columnValueChange.append(afterColumnValue.getColumn()).append(","); + } + } + } + + } else if (CollectionUtil.isEmpty(beforeColumnValues) && CollectionUtil.isNotEmpty(afterColumnValues)) { + for (ColumnValue afterColumnValue : afterColumnValues) { + columnValueChange.append(afterColumnValue.getColumn()).append(","); + } + + } else if (CollectionUtil.isNotEmpty(beforeColumnValues) && CollectionUtil.isEmpty(afterColumnValues)) { + for (ColumnValue beforeColumn : beforeColumnValues) { + columnValueChange.append(beforeColumn.getColumn()).append(","); + } + + } + compareCaseVO.setColumnValueChangeColumn(columnValueChange.toString()); + + return AjaxResult.success(compareCaseVO); + } + + /** + * 对比申请人证据资料 + * @param beforeCase + * @param afterCase + * @param changeColumn + * @return + */ + private StringBuilder compareApplicantFile(CaseApplication beforeCase, CaseApplication afterCase, StringBuilder changeColumn) { + List beforeAttachFilter =new ArrayList<>(); + List afterAttachFilter =new ArrayList<>(); + if(CollectionUtil.isNotEmpty(beforeCase.getCaseAttachList())){ + beforeAttachFilter = beforeCase.getCaseAttachList().stream().filter(n -> n.getAnnexType() == 2).collect(Collectors.toList()); + } + if(CollectionUtil.isNotEmpty(afterCase.getCaseAttachList())){ + afterAttachFilter = afterCase.getCaseAttachList().stream().filter(n -> n.getAnnexType() == 2).collect(Collectors.toList()); + } + if(CollectionUtil.isNotEmpty(beforeAttachFilter)&& CollectionUtil.isNotEmpty(afterAttachFilter)){ + if(beforeAttachFilter.size()!=afterAttachFilter.size()){ + changeColumn.append("fileColumn"); + }else { + Map afterAttachMap = afterAttachFilter.stream().collect(Collectors.toMap(CaseAttach::getAnnexPath, Function.identity(), (n1, n2) -> n2)); + for (CaseAttach beforeCaseAttach : beforeAttachFilter) { + if(!afterAttachMap.containsKey(beforeCaseAttach.getAnnexPath())) { + changeColumn.append("fileColumn"); + break; + } + } + } + } + + + return changeColumn; + } + + /** + * 对比案件人员字段 + * @param beforeCase + * @param afterCase + */ + private void compareAffilate(CaseApplication beforeCase, CaseApplication afterCase) { + // 对比人员字段 + List beforeCaseCaseAffiliates = beforeCase.getCaseAffiliates(); + List afterCaseCaseAffiliates = afterCase.getCaseAffiliates(); + Map beforeCaseCaseAffiliateMap = null; + if (CollectionUtil.isNotEmpty(beforeCaseCaseAffiliates)) { + // 转为map + beforeCaseCaseAffiliateMap = beforeCaseCaseAffiliates.stream().collect(Collectors.toMap(CaseAffiliate::getIdentityType, v -> v, (n1, n2) -> n2)); + } + StringBuilder affiliateChangeColumn; + // 如果上一个版本和现版本有一个为空,那么所有字段都修改 + if (beforeCaseCaseAffiliates != null && afterCaseCaseAffiliates == null) { + affiliateChangeColumn = new StringBuilder(); + for (String column : affiliateColumns) { + + affiliateChangeColumn.append(column).append(","); + } + + } else if (beforeCaseCaseAffiliates == null && afterCaseCaseAffiliates != null) { + affiliateChangeColumn = new StringBuilder(); + for (String column : affiliateColumns) { + + affiliateChangeColumn.append(column).append(","); + } + } else if (beforeCaseCaseAffiliates != null && afterCaseCaseAffiliates != null) { + for (CaseAffiliate afterCaseCaseAffiliate : afterCaseCaseAffiliates) { + // 找到相同身份类型的数据,进行对比 + affiliateChangeColumn = new StringBuilder(); + int identityType = afterCaseCaseAffiliate.getIdentityType(); + if (beforeCaseCaseAffiliateMap != null && beforeCaseCaseAffiliateMap.containsKey(identityType)) { + CaseAffiliate beforeCaseCaseAffiliate = beforeCaseCaseAffiliateMap.get(identityType); + for (String column : affiliateColumns) { + String beforeValue = ObjectFieldUtils.getValue(beforeCaseCaseAffiliate, column); + String afterValue = ObjectFieldUtils.getValue(afterCaseCaseAffiliate, column); + if (StrUtil.isEmpty(beforeValue) && StrUtil.isNotEmpty(afterValue)) { + affiliateChangeColumn.append(column).append(","); + continue; + } + if (StrUtil.isNotEmpty(beforeValue) && StrUtil.isEmpty(afterValue)) { + affiliateChangeColumn.append(column).append(","); + continue; + } + if (StrUtil.isNotEmpty(beforeValue) && StrUtil.isNotEmpty(afterValue) && !Objects.equals(beforeValue, afterValue)) { + affiliateChangeColumn.append(column).append(","); + continue; + + } + + } + + + } else { + for (String column : affiliateColumns) { + + affiliateChangeColumn.append(column).append(","); + } + } + afterCaseCaseAffiliate.setChangeColumn(affiliateChangeColumn.toString()); + + } + + + } + } + + /** + * 同意撤销 + * @param vo + */ + private void agreeRevoke(UpdateSubmitVO vo) { + CaseApplication caseApplicationLog; + // 查询日志记录表上个版本未被拒绝数据 + if(vo.getVersion()<=1){ + caseApplicationLog = caseApplicationLogMapper.selectByCaseIdAndVersion(vo.getCaseId(), vo.getVersion() ); + + }else { + caseApplicationLog = caseApplicationLogMapper.selectBeforeCase(vo.getCaseId(), vo.getVersion() ); + } + if (caseApplicationLog == null) { + return; + } + // 将日志表改版本的状态改为拒绝 + vo.setUpdateSubmitStatus(UpdateSubmitStatus.AGREE_REVOKE.getCode()); + caseApplicationLogMapper.updateStatus(vo); + // 根据caseLogId查询相关人员表 + List affiliateLogList = caseAffiliateLogMapper.selectCaseAffiliate(caseApplicationLog.getCaseLogId()); + + + // 更新案件主表 + caseApplicationMapper.updataCaseApplication(caseApplicationLog); + + // 更新相关人员主表 + if(CollectionUtil.isNotEmpty(affiliateLogList)){ + caseAffiliateMapper.deleteByCaseId(vo.getCaseId()); + for (CaseAffiliate caseAffiliate : affiliateLogList) { + caseAffiliate.setCaseAppliId(vo.getCaseId()); + + } + caseAffiliateMapper.batchCaseAffiliate(affiliateLogList); + } + // // 根据caseLogId查询案件记录附件表 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setCaseLogId(caseApplicationLog.getCaseLogId()); + caseApplication.setAnnexType(2); + List attachLogList = caseAttachLogMapper.queryCaseAttachList(caseApplication); + // 更新记录附件表 + if(CollectionUtil.isNotEmpty(attachLogList)){ + for (CaseAttach caseAttach : attachLogList) { + caseAttach.setCaseAppliId(vo.getCaseId()); + caseAttachMapper.updateCaseAttach(caseAttach); + } + } + // 根据caseLogId查询自定义字段表 + List columnValueList = columnValueLogMapper.listBycaseAppliLogId(caseApplicationLog.getCaseLogId()); + + // 更新相关人员主表 + if(CollectionUtil.isNotEmpty(columnValueList)){ + for (ColumnValue columnValue : columnValueList) { + columnValue.setCaseAppliLogId(vo.getCaseId()); + + } + columnValueLogMapper.batchUpdate(columnValueList); + } + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationServiceImpl.java new file mode 100644 index 0000000..7005ca1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationServiceImpl.java @@ -0,0 +1,3703 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.*; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.UpdateSubmitStatus; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.*; +import com.ruoyi.common.utils.file.SaaSAPIFileUtils; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.thread.ThreadPoolUtil; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.*; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.ToDoCount; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +import com.ruoyi.wisdomarbitrate.utils.SignAward; +import com.ruoyi.wisdomarbitrate.utils.UnZipFileUtils; +import com.ruoyi.wisdomarbitrate.utils.ZipFileUtils; +import com.tencentyun.TLSSigAPIv2; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.*; +import java.util.List; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.zip.ZipOutputStream; + +import static com.ruoyi.common.core.domain.AjaxResult.error; +import static com.ruoyi.common.core.domain.AjaxResult.success; +import static com.ruoyi.common.utils.PageUtils.startPage; +import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; +import static com.ruoyi.common.utils.SecurityUtils.getUsername; +import static com.ruoyi.wisdomarbitrate.utils.CaseLogUtils.insertCaseLog; + + +@Service +public class CaseApplicationServiceImpl implements ICaseApplicationService { + // 腾讯云即时通信sdkAppId + @Value("${imConfig.sdkAppId}") + private long sdkAppId; + // 腾讯云即时通信密钥 + @Value("${imConfig.sdkSecretKey}") + private String sdkSecretKey; + @Autowired + private CaseApplicationMapper caseApplicationMapper; + + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + + @Autowired + private ArbitrateRecordMapper arbitrateRecordMapper; + @Autowired + private ICaseApplicationService caseApplicationService; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private SysDeptMapper sysDeptMapper; + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private SysUserRoleMapper userRoleMapper; + @Autowired + private SysRoleMapper roleMapper; + @Autowired + private SealSignRecordMapper sealSignRecordMapper; + @Autowired + private CaseLogRecordMapper caseLogRecordMapper; + @Autowired + private CaseEvidenceDirectoryMapper caseEvidenceDirectoryMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + @Autowired + private DeptIdentifyMapper deptIdentifyMapper; + @Autowired + private ReservedConferenceMapper reservedConferenceMapper; + + @Autowired + private SealManageMapper sealManageMapper; + @Autowired + private CaseApplicationLogMapper caseApplicationLogMapper; + @Autowired + private CaseAffiliateLogMapper caseAffiliateLogMapper; + @Autowired + private CaseAttachLogMapper caseAttachLogMapper; + + @Autowired + private ColumnValueMapper columnValueMapper; + @Autowired + private ColumnValueLogMapper columnValueLogMapper; + + @Autowired + private CaseZipImportImpl caseZipImportImpl; + // 手机号正则 + private static final Pattern TELEPHONE_REGX = Pattern.compile("^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$"); + // 邮箱正则 + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"); + + // 基本字段校验 + private static final String[] baseColumns = {"caseName","caseSubjectAmount","loanStartDate", "loanEndDate","contractNumber","claimInterestOwed","claimLiquidDamag", + "claimPrinciOwed","arbitratClaims"}; + // 申请人字段校验 + private static final String[] applicAffiliateColumns = {"name", "contactTelphone","contactAddress","workTelphone","workAddress", + "residenAffili","compLegalPerson", + "compLegalperPost","email","nameAgent", "identityNumAgent","contactTelphoneAgent","contactAddressAgent"}; + // 申请人/被申请人代理人字段校验 + private static final String[] applicAgentAffiliateColumns = {"nameAgent", "identityNumAgent","contactTelphoneAgent","contactAddressAgent"}; + // 被申请人字段校验 + private static final String[] dectborAffiliateColumns = {"name", "identityNum","contactTelphone","contactAddress","workTelphone","workAddress", + "residenAffili","responSex","responBirth","email","nameAgent", "identityNumAgent","contactTelphoneAgent","contactAddressAgent"}; + + /** + * 数据权限:1.每个人不同的角色,而每个角色可以操作不同的案件状态 + * 2.申请人:金融机构下,可以看到改机构的所有的案件 + * 3.被申请人:可以看到自己相关的案件(案件有被申请人相关的信息) + * 4.仲裁员:案件选定了某个仲裁员后,该仲裁员就可以查看该案件 + * 5.仲裁委(部门长):可以查看所有的案件 + * 6.法律顾问秘书:可以属于多个机构,可以查看相关机构的所有案件 + * 7.超级管理员:可以查看所有的信息和数据 + * + * @param caseApplication + * @return + */ + @Override + public List selectCaseApplicationListByRole(CaseApplication caseApplication) { + // 获取登录用户 + LoginUser loginUser = getLoginUser(); + SysUser user = loginUser.getUser(); + Long userId = user.getUserId(); + // 查询登录人身份证号 + SysUser sysUser = sysUserMapper.selectUserById(userId); + startPage(); + caseApplication.setLoginUserName(sysUser.getUserName()); + List roles = sysUser.getRoles(); + // 没有角色不能查看案件列表 + if (CollectionUtil.isEmpty(roles)) { + throw new ServiceException("该用户没有角色权限"); + } + + for (SysRole role : roles) { + if (StrUtil.isEmpty(role.getRoleName())) { + continue; + } + // 超级管理员和仲裁委(部门长)案件,可查看所有案件 √ + if ("超级管理员".equals(role.getRoleName()) + ) { + List caseApplicationlist = caseApplicationMapper.selectAdminCaseApplicationList(caseApplication); + if(caseApplicationlist!=null&&caseApplicationlist.size()>0){ + for(CaseApplication caseApplicationsel : caseApplicationlist){ + Integer caseStatus = caseApplicationsel.getCaseStatus(); + if(caseStatus.intValue() == CaseApplicationConstants.CHECK_ARBITRATION_METHOD){ + Integer applicantIsWrittenHear = caseApplicationsel.getApplicantIsWrittenHear(); + Integer respondentIsWrittenHear = caseApplicationsel.getRespondentIsWrittenHear(); + if(applicantIsWrittenHear!=null&&respondentIsWrittenHear!=null){ + if(applicantIsWrittenHear.intValue()==respondentIsWrittenHear.intValue()){ + caseApplicationsel.setArbitraMethodIssame(1); + if(applicantIsWrittenHear.intValue()==1&&respondentIsWrittenHear.intValue()==1){ + caseApplicationsel.setArbitratMethod(2); + }else { + caseApplicationsel.setArbitratMethod(1); + } + }else { + caseApplicationsel.setArbitraMethodIssame(2); + String applicantarbitratMethod = ""; + String respondentbitratMethod = ""; + if(applicantIsWrittenHear.intValue()==1){ + applicantarbitratMethod = "书面审理"; + }else { + applicantarbitratMethod = "开庭审理"; + } + if(respondentIsWrittenHear.intValue()==1){ + respondentbitratMethod = "书面审理"; + }else { + respondentbitratMethod = "开庭审理"; + } + String arbitratMethodIllustrate = "当前案件开庭方式:申请人选择开庭方式为"+applicantarbitratMethod+ + "被申请人选择开庭方式为"+respondentbitratMethod+",请确定开庭方式。"; + caseApplicationsel.setArbitratMethodIllustrate(arbitratMethodIllustrate); + } + } + + } + } + } + return caseApplicationlist; + } + if ("仲裁委".equals(role.getRoleName()) + || "部门长".equals(role.getRoleName())) { + List caseStatusList = new ArrayList<>(); + caseStatusList.add(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + caseStatusList.add(CaseApplicationConstants.CHECK_ARBITRATION); + // caseStatusList.add(CaseApplicationConstants.ARBITRATED_SEAL); + caseApplication.setDeptHeadStatus(caseStatusList); + caseApplication.setIsOtherRole(1); + } + if ("仲裁员".equals(role.getRoleName())) { + caseApplication.setUserId(String.valueOf(userId)); + caseApplication.setIsOtherRole(1); + } + if ("财务".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + caseApplication.setFinanceStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM); + } + if ("法律顾问".equals(role.getRoleName())) { + // 秘书查看所有案件 + // 查询角色有关的用户部门 + List deptIds = new ArrayList<>(); + deptIds.add(sysUser.getDeptId()); + caseApplication.setDeptIds(deptIds); + } + if ("申请人".equals(role.getRoleName())) { + // caseApplication.setIsOtherRole(1); + // 查询有关的用户部门 + caseApplication.setApplicationOrganId(String.valueOf(sysUser.getDeptId())); + } + if ("被申请人".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + // + caseApplication.setIdCard(String.valueOf(sysUser.getIdCard())); + } + if ("代理人".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + // 查询角色有关的用户部门 + // List agentDeptIds = sysDeptMapper.selectUserDeptListByRoleId(role.getRoleId()); + List agentDeptIds = new ArrayList<>(); + agentDeptIds.add(sysUser.getDeptId()); + caseApplication.setAgentDeptIds(agentDeptIds); + } + } + + + // 根据条件查询申请人,被申请人,仲裁员,法律顾问案件 +// return caseApplicationMapper.selectCaseApplicationList(caseApplication); + List caseApplications = caseApplicationMapper.selectCaseApplicationList1(caseApplication); + if(caseApplications!=null&&caseApplications.size()>0){ + for(CaseApplication caseApplicationsel : caseApplications){ + Integer caseStatus = caseApplicationsel.getCaseStatus(); + if(caseStatus.intValue() == CaseApplicationConstants.CHECK_ARBITRATION_METHOD){ + Integer applicantIsWrittenHear = caseApplicationsel.getApplicantIsWrittenHear(); + Integer respondentIsWrittenHear = caseApplicationsel.getRespondentIsWrittenHear(); + if(applicantIsWrittenHear!=null&&respondentIsWrittenHear!=null){ + if(applicantIsWrittenHear.intValue()==respondentIsWrittenHear.intValue()){ + caseApplicationsel.setArbitraMethodIssame(1); + if(applicantIsWrittenHear.intValue()==1&&respondentIsWrittenHear.intValue()==1){ + caseApplicationsel.setArbitratMethod(2); + }else { + caseApplicationsel.setArbitratMethod(1); + } + }else { + caseApplicationsel.setArbitraMethodIssame(2); + String applicantarbitratMethod = ""; + String respondentbitratMethod = ""; + if(applicantIsWrittenHear.intValue()==1){ + applicantarbitratMethod = "书面审理"; + }else { + applicantarbitratMethod = "开庭审理"; + } + if(respondentIsWrittenHear.intValue()==1){ + respondentbitratMethod = "书面审理"; + }else { + respondentbitratMethod = "开庭审理"; + } + String arbitratMethodIllustrate = "当前案件开庭方式:申请人选择开庭方式为"+applicantarbitratMethod+ + "被申请人选择开庭方式为"+respondentbitratMethod+",请确定开庭方式。"; + caseApplicationsel.setArbitratMethodIllustrate(arbitratMethodIllustrate); + } + } + + } + } + } + return caseApplications; + + } + + + @Override + public ToDoCount selectToDoCount() { + + // 获取登录用户 + LoginUser loginUser = getLoginUser(); + SysUser user = loginUser.getUser(); + Long userId = user.getUserId(); + + // 查询登录人信息 + SysUser sysUser = sysUserMapper.selectUserById(userId); + List roles = sysUser.getRoles(); + // 没有角色不能查看案件列表 + if (CollectionUtil.isEmpty(roles)) { + throw new ServiceException("该用户没有角色权限"); + } + CaseApplication caseApplication = new CaseApplication(); + List caseStatusList = new ArrayList<>(); + for (SysRole role : roles) { + if (StrUtil.isEmpty(role.getRoleName())) { + continue; + } + // 超级管理员和仲裁委(部门长)案件,可查看所有案件 √ + if (role.getRoleName().equals("超级管理员") + ) { + return caseApplicationMapper.selectAdminCaseToDoCount(); + } + if ("仲裁委".equals(role.getRoleName()) + || "部门长".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + caseStatusList.add(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + caseStatusList.add(CaseApplicationConstants.CHECK_ARBITRATION); + // caseStatusList.add(CaseApplicationConstants.ARBITRATED_SEAL); + caseApplication.setDeptHeadStatus(caseStatusList); + } + if ("仲裁员".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + caseApplication.setUserId(String.valueOf(userId)); + } + if ("财务".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + caseApplication.setFinanceStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM); + } + if ("法律顾问".equals(role.getRoleName())) { + // 查询角色有关的用户部门 + // List deptIds = sysDeptMapper.selectUserDeptListByRoleId(role.getRoleId()); + List deptIds = new ArrayList<>(); + deptIds.add(sysUser.getDeptId()); + caseApplication.setDeptIds(deptIds); + } + if ("申请人".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + // 查询角色有关的用户部门 + caseApplication.setApplicationOrganId(String.valueOf(sysUser.getDeptId())); + } + if ("被申请人".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + // + caseApplication.setIdCard(String.valueOf(sysUser.getIdCard())); + } + if ("代理人".equals(role.getRoleName())) { + caseApplication.setIsOtherRole(1); + // 查询角色有关的用户部门 + // List agentDeptIds = sysDeptMapper.selectUserDeptListByRoleId(role.getRoleId()); + List agentDeptIds = new ArrayList<>(); + agentDeptIds.add(sysUser.getDeptId()); + caseApplication.setAgentDeptIds(agentDeptIds); + } + } + + + // 根据条件查询申请人,被申请人,仲裁员,法律顾问案件 + ToDoCount toDoCount = caseApplicationMapper.selectTodoCountByRole(caseApplication); + if (toDoCount == null) { + return new ToDoCount(); + } + return toDoCount; + } + + @Override + public AjaxResult selectCaseProgress(CaseApplication caseApplication) { + Map datas = new HashMap<>(); + Long id = caseApplication.getId(); + CaseLogRecord caseLogRecord = new CaseLogRecord(); + caseLogRecord.setCaseAppliId(id); + List records = caseLogRecordMapper.selectCaseLogRecordList(caseLogRecord); + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + Integer caseStatus = caseApplicationselect.getCaseStatus(); + if (caseStatus.intValue() != 0) { + CaseLogRecord caseLogRecordin = getInCasenode(caseStatus); + records.add(caseLogRecordin); + } + + List recordsnofinish = getNofinishCasenode(caseStatus); + records.addAll(recordsnofinish); + datas.put("allCasenode", records); + datas.put("caseStatus", caseStatus); + return success(datas); + + } + + @Override + @Transactional + public int updateHeardate(CaseApplication caseApplication) { +// caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_OPENCOURT_HEAR); + caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_OPENCOURT_HEAR); + int rows = caseApplicationMapper.submitCaseApplication(caseApplication); + //1975139 修改开庭时间通知 尊敬的{1}用户,您的{2}仲裁案件,开庭日期已改为{3},请知晓,如非本人操作,请忽略本短信 + //发送短信通知 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1975139"); + + // 发送开庭日期通知短信 + sendHearDateMessage(caseApplication, request, "1975139"); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_OPENCOURT_HEAR, ""); + return rows; + } + + @Override + public int updateCaseLockStatus(CaseApplication caseApplication) { + return caseApplicationMapper.updateCaseLockStatus(caseApplication.getId(), caseApplication.getLockStatus()); + } + + + + @Override + @Transactional + public AjaxResult uploadZipFile(MultipartFile file, Long id, String username, Long userId) { + if (file.isEmpty()) { + return AjaxResult.error("请选择要上传的文件"); + } + + String targetPath = "/home/ruoyi/uploadPath/upload/unzipFile"; + File zipFile = null; + InputStream ins = null; + try { + ins = file.getInputStream(); + zipFile = new File(file.getOriginalFilename()); + caseZipImportImpl.inputChangeToFile(ins, zipFile); + } catch (IOException e) { + e.printStackTrace(); + } + //解压缩上传的压缩包 + UnZipFileUtils.unZipFile(zipFile, targetPath); + + //得到解压缩的所有文件 + String zipName = file.getOriginalFilename(); + String subzipName = zipName.substring(0, zipName.indexOf(".zip")); + // todo + String zipPath = "/home/ruoyi/uploadPath/upload/unzipFile/" + subzipName; +// String zipPath = "D:/home/ruoyi/uploadPath/upload/unzipFile/" + subzipName; + + File dirUnzipPath = new File(zipPath); + List allFiles = new ArrayList<>(); + List allFilestr = new ArrayList<>(); + UnZipFileUtils.getFiles(dirUnzipPath, allFiles); + if (allFiles != null && allFiles.size() > 0) { + for (File fileIter : allFiles) { + System.out.println(fileIter.getAbsolutePath()); + allFilestr.add(fileIter.getAbsolutePath()); + } + } + + //保存目录和文件 + if (allFilestr != null && allFilestr.size() > 0) { + for (String filestr : allFilestr) { + List allindex = new ArrayList<>(); +// int indexKey = filestr.indexOf("\\"); + int indexKey = filestr.indexOf("/"); +// System.out.println("filestr:------------"+filestr); + allindex.add(indexKey); + while (indexKey != -1) { +// indexKey = filestr.indexOf("\\", indexKey + 1); + indexKey = filestr.indexOf("/", indexKey + 1); + allindex.add(indexKey); + } + + if (allindex != null && allindex.size() > 0) { + String substrOne = filestr.substring(allindex.get(6) + 1, allindex.get(7)); + Integer series = null; + for (int i = 0; i < allindex.size() - 7; i++) { + String substr = filestr.substring(allindex.get(i + 5) + 1, allindex.get(i + 6)); + series = i + 1; + if (series == 1) { + //查询这个级数的目录是否存在,若不存在,则新建这个目录 + CaseEvidenceDirectory caseEvidenceDirectoryselect = new CaseEvidenceDirectory(); + caseEvidenceDirectoryselect.setCaseId(id); + caseEvidenceDirectoryselect.setEvidenceName(filestr.substring(allindex.get(i + 5) + 1, allindex.get(i + 6))); + caseEvidenceDirectoryselect.setSeries(series); + List caseEvidenceDirectorys = caseEvidenceDirectoryMapper.selectList(caseEvidenceDirectoryselect); + if (caseEvidenceDirectorys != null && caseEvidenceDirectorys.size() > 0) { + continue; + } else { + CaseEvidenceDirectory caseEvidenceDirectory = new CaseEvidenceDirectory(); + caseEvidenceDirectory.setEvidenceName(substr); + caseEvidenceDirectory.setSeries(series); + caseEvidenceDirectory.setCaseId(id); + caseEvidenceDirectory.setCreateBy(username); + caseEvidenceDirectory.setCreateTime(new Date()); + caseEvidenceDirectoryMapper.save(caseEvidenceDirectory); + } + } else { + //查询这个级数的目录是否存在,若不存在,则新建这个目录 + CaseEvidenceDirectory directoryselect = new CaseEvidenceDirectory(); + directoryselect.setCaseId(id); + directoryselect.setEvidenceName(filestr.substring(allindex.get(i + 5) + 1, allindex.get(i + 6))); + directoryselect.setSeries(series); + List evidenceDirectorys = caseEvidenceDirectoryMapper.selectList(directoryselect); + if (evidenceDirectorys != null && evidenceDirectorys.size() > 0) { + continue; + } else { + Long parentId = null; + CaseEvidenceDirectory caseEvidenceDirectoryselect = new CaseEvidenceDirectory(); + caseEvidenceDirectoryselect.setCaseId(id); + caseEvidenceDirectoryselect.setEvidenceName(filestr.substring(allindex.get(i + 4) + 1, allindex.get(i + 5))); + caseEvidenceDirectoryselect.setSeries(series - 1); + List caseEvidenceDirectorys = caseEvidenceDirectoryMapper.selectList(caseEvidenceDirectoryselect); + if (caseEvidenceDirectorys != null && caseEvidenceDirectorys.size() > 0) { + parentId = caseEvidenceDirectorys.get(0).getId(); + } + + CaseEvidenceDirectory caseEvidenceDirectory = new CaseEvidenceDirectory(); + caseEvidenceDirectory.setEvidenceName(substr); + caseEvidenceDirectory.setSeries(series); + caseEvidenceDirectory.setCreateBy(username); + caseEvidenceDirectory.setCreateTime(new Date()); + caseEvidenceDirectory.setCaseId(id); + caseEvidenceDirectory.setParentId(parentId); + caseEvidenceDirectoryMapper.save(caseEvidenceDirectory); + } + + } + } + + //得到最后1级的目录,即文件 + int lastIndex = allindex.get(7); + String substrfile = filestr.substring(lastIndex + 1); + //保存到附件表 + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + // todo + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; +// String saveFolderPath = "D:/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + "_" + substrfile; + String resultFilePath = saveFolderPath + "/" + fileName; + try { + File resultFilePathFile = new File(resultFilePath); + File parentFilePathFile = resultFilePathFile.getParentFile(); + if (!parentFilePathFile.exists()) { + parentFilePathFile.mkdirs(); + } + if (!resultFilePathFile.exists()) { + resultFilePathFile.createNewFile(); + } + + FileInputStream fis = new FileInputStream(new File(filestr)); + FileOutputStream fos = new FileOutputStream(resultFilePathFile); + byte[] btyeBuf = new byte[1024]; + int len = 0; + while ((len = fis.read(btyeBuf)) != -1) { + fos.write(btyeBuf, 0, len); + } + fis.close(); + fos.close(); + + } catch (IOException e) { + AjaxResult.error("文件解压异常", e); + } + + String substrTwo = filestr.substring(allindex.get(6) + 1, allindex.get(7)); + Integer annexType = null; + if ("申请书".equals(substrTwo)) { + annexType = 1; + } else if ("证据材料".equals(substrTwo)) { + annexType = 2; + } + String savePath = "/home/ruoyi/uploadPath/upload"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + //将附件保存到附件表里 + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(annexType) + .build(); + int i = caseAttachMapper.save(caseAttach); + Integer annexId = caseAttach.getAnnexId(); + + //保存到目录表 + Long parentId = null; + CaseEvidenceDirectory caseEvidenceDirectoryselect = new CaseEvidenceDirectory(); + caseEvidenceDirectoryselect.setCaseId(id); + caseEvidenceDirectoryselect.setEvidenceName(filestr.substring(allindex.get(6) + 1, allindex.get(7))); + caseEvidenceDirectoryselect.setSeries(series); + List caseEvidenceDirectorys = caseEvidenceDirectoryMapper.selectList(caseEvidenceDirectoryselect); + if (caseEvidenceDirectorys != null && caseEvidenceDirectorys.size() > 0) { + parentId = caseEvidenceDirectorys.get(0).getId(); + } + + CaseEvidenceDirectory caseEvidenceDirectory = new CaseEvidenceDirectory(); + caseEvidenceDirectory.setEvidenceName(substrfile); + caseEvidenceDirectory.setSeries(series + 1); + caseEvidenceDirectory.setCreateBy(username); + caseEvidenceDirectory.setCreateTime(new Date()); + caseEvidenceDirectory.setAnnexId(annexId); + caseEvidenceDirectory.setCaseId(id); + caseEvidenceDirectory.setParentId(parentId); + + caseEvidenceDirectoryMapper.save(caseEvidenceDirectory); + } + } + } + return success(); + + } + + @Override + public List getSmsSendRecord(SmsSendRecord smsSendRecord) { + return smsRecordMapper.getSmsSendRecord(smsSendRecord); + } + + private List getNofinishCasenode(Integer caseStatus) { + CaseLogRecord caseLogRecord1 = new CaseLogRecord(); + caseLogRecord1.setCaseNodeName("立案审查"); + caseLogRecord1.setCaseNode(1); + caseLogRecord1.setContent("法律顾问将进行立案审查"); + CaseLogRecord caseLogRecord2 = new CaseLogRecord(); + caseLogRecord2.setCaseNode(2); + caseLogRecord2.setCaseNodeName("缴费"); + caseLogRecord2.setContent("申请人将进行缴费"); + CaseLogRecord caseLogRecord3 = new CaseLogRecord(); + caseLogRecord3.setCaseNode(3); + caseLogRecord3.setCaseNodeName("缴费确认"); + caseLogRecord3.setContent("财务将进行缴费确认"); + CaseLogRecord caseLogRecord4 = new CaseLogRecord(); + caseLogRecord4.setCaseNode(4); + caseLogRecord4.setCaseNodeName("案件质证"); + caseLogRecord4.setContent("被申请人将进行案件质证"); + CaseLogRecord caseLogRecord5 = new CaseLogRecord(); + caseLogRecord5.setCaseNode(5); + caseLogRecord5.setCaseNodeName("组庭审核"); + caseLogRecord5.setContent("法律顾问将进行组庭审核"); + + CaseLogRecord caseLogRecord6 = new CaseLogRecord(); + caseLogRecord6.setCaseNode(6); + caseLogRecord6.setCaseNodeName("修改开庭时间"); + caseLogRecord6.setContent("部门长将修改开庭时间"); + + CaseLogRecord caseLogRecord7 = new CaseLogRecord(); + caseLogRecord6.setCaseNode(7); + caseLogRecord6.setCaseNodeName("组庭确定"); + caseLogRecord6.setContent("部门长将进行组庭确定"); + + CaseLogRecord caseLogRecord8 = new CaseLogRecord(); + caseLogRecord7.setCaseNode(8); + caseLogRecord7.setCaseNodeName("审核仲裁方式"); + caseLogRecord7.setContent("仲裁员将进行审核仲裁方式"); + CaseLogRecord caseLogRecord9 = new CaseLogRecord(); + caseLogRecord8.setCaseNode(9); + caseLogRecord8.setCaseNodeName("开庭审理"); + caseLogRecord8.setContent("仲裁员将进行开庭审理"); + CaseLogRecord caseLogRecord11 = new CaseLogRecord(); + caseLogRecord9.setCaseNode(11); + caseLogRecord9.setCaseNodeName("书面审理"); + caseLogRecord9.setContent("仲裁员将进行书面审理"); + CaseLogRecord caseLogRecord12 = new CaseLogRecord(); + caseLogRecord11.setCaseNode(12); + caseLogRecord11.setCaseNodeName("核验仲裁文书"); + caseLogRecord11.setContent("法律顾问将进行核验仲裁文书"); + CaseLogRecord caseLogRecord13 = new CaseLogRecord(); + caseLogRecord12.setCaseNode(13); + caseLogRecord12.setCaseNodeName("确认仲裁文书"); + caseLogRecord12.setContent("仲裁员将进行确认仲裁文书"); + CaseLogRecord caseLogRecord14 = new CaseLogRecord(); + caseLogRecord13.setCaseNode(14); + caseLogRecord13.setCaseNodeName("仲裁文书签名"); + caseLogRecord13.setContent("仲裁员将进行仲裁文书签名"); + CaseLogRecord caseLogRecord15 = new CaseLogRecord(); + caseLogRecord14.setCaseNode(15); + caseLogRecord14.setCaseNodeName("仲裁文书用印"); + caseLogRecord14.setContent("部门长将进行仲裁文书用印"); + CaseLogRecord caseLogRecord16 = new CaseLogRecord(); + caseLogRecord15.setCaseNode(16); + caseLogRecord15.setCaseNodeName("仲裁文书送达"); + caseLogRecord15.setContent("法律顾问将进行仲裁文书送达"); + CaseLogRecord caseLogRecord17 = new CaseLogRecord(); + caseLogRecord16.setCaseNode(17); + caseLogRecord16.setCaseNodeName("案件归档"); + caseLogRecord16.setContent("法律顾问将进行案件归档"); + + + List caseLogRecords = new ArrayList<>(); + switch (caseStatus.toString()) { + case "0": + caseLogRecords.add(caseLogRecord1); + caseLogRecords.add(caseLogRecord2); + caseLogRecords.add(caseLogRecord3); + caseLogRecords.add(caseLogRecord4); + caseLogRecords.add(caseLogRecord5); + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + break; + case "1": + caseLogRecords.add(caseLogRecord2); + caseLogRecords.add(caseLogRecord3); + caseLogRecords.add(caseLogRecord4); + caseLogRecords.add(caseLogRecord5); + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + break; + case "2": + caseLogRecords.add(caseLogRecord3); + caseLogRecords.add(caseLogRecord4); + caseLogRecords.add(caseLogRecord5); + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + break; + case "3": + caseLogRecords.add(caseLogRecord4); + caseLogRecords.add(caseLogRecord5); + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "4": + caseLogRecords.add(caseLogRecord5); + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "5": + caseLogRecords.add(caseLogRecord6); + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "6": + caseLogRecords.add(caseLogRecord7); + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "7": + caseLogRecords.add(caseLogRecord8); + caseLogRecords.add(caseLogRecord9); + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "8": + case "9": + caseLogRecords.add(caseLogRecord11); + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + break; + + case "11": + caseLogRecords.add(caseLogRecord12); + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "12": + caseLogRecords.add(caseLogRecord13); + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "13": + caseLogRecords.add(caseLogRecord14); + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "14": + caseLogRecords.add(caseLogRecord15); + caseLogRecords.add(caseLogRecord16); + + break; + case "15": + caseLogRecords.add(caseLogRecord16); + + break; + default: + List caseLogRecords1 = new ArrayList<>(); + } + + return caseLogRecords; + + + } + + private CaseLogRecord getInCasenode(Integer caseStatus) { + CaseLogRecord caseLogRecord = new CaseLogRecord(); + switch (caseStatus.toString()) { + case "1": + caseLogRecord.setCaseNodeName("立案审查"); + caseLogRecord.setCaseNode(1); + caseLogRecord.setContent("法律顾问正在进行立案审查"); + caseLogRecord.setNextRoleName("下一节点角色:申请人"); + break; + case "2": + caseLogRecord.setCaseNodeName("缴费"); + caseLogRecord.setCaseNode(2); + caseLogRecord.setContent("申请人正在进行缴费"); + caseLogRecord.setNextRoleName("下一节点角色:仲裁财务"); + break; + case "3": + caseLogRecord.setCaseNodeName("缴费确认"); + caseLogRecord.setCaseNode(3); + caseLogRecord.setContent("财务正在进行缴费确认"); + caseLogRecord.setNextRoleName("下一节点角色:被申请人"); + break; + case "4": + caseLogRecord.setCaseNodeName("案件质证"); + caseLogRecord.setCaseNode(4); + caseLogRecord.setContent("被申请人将进行案件质证"); + caseLogRecord.setNextRoleName("下一节点角色:法律顾问"); + break; + case "5": + caseLogRecord.setCaseNodeName("组庭审核"); + caseLogRecord.setCaseNode(5); + caseLogRecord.setContent("法律顾问正在进行组庭审核"); + caseLogRecord.setNextRoleName("下一节点角色:部门长"); + break; + case "6": + caseLogRecord.setCaseNodeName("组庭确定"); + caseLogRecord.setCaseNode(6); + caseLogRecord.setContent("部门长正在进行组庭确定"); + caseLogRecord.setNextRoleName("下一节点角色:法律顾问"); + break; + case "7": + caseLogRecord.setCaseNodeName("审核仲裁方式"); + caseLogRecord.setCaseNode(7); + caseLogRecord.setContent("仲裁员正在进行审核仲裁方式"); + caseLogRecord.setNextRoleName("下一节点角色:秘书顾问"); + break; + case "8": + caseLogRecord.setCaseNodeName("开庭审理"); + caseLogRecord.setCaseNode(8); + caseLogRecord.setContent("仲裁员正在进行开庭审理"); + caseLogRecord.setNextRoleName("下一节点角色:仲裁员"); + break; + case "9": + caseLogRecord.setCaseNodeName("书面审理"); + caseLogRecord.setCaseNode(9); + caseLogRecord.setContent("仲裁员正在进行书面审理"); + caseLogRecord.setNextRoleName("下一节点角色:仲裁员"); + break; + case "11": + caseLogRecord.setCaseNodeName("核验仲裁文书"); + caseLogRecord.setCaseNode(11); + caseLogRecord.setContent("法律顾问正在进行核验仲裁文书"); + caseLogRecord.setNextRoleName("下一节点角色:部门长"); + break; + case "12": + caseLogRecord.setCaseNodeName("确认仲裁文书"); + caseLogRecord.setCaseNode(12); + caseLogRecord.setContent("仲裁员正在进行确认仲裁文书"); + caseLogRecord.setNextRoleName("下一节点角色:仲裁员"); + break; + case "13": + caseLogRecord.setCaseNodeName("仲裁文书签名"); + caseLogRecord.setCaseNode(13); + caseLogRecord.setContent("仲裁员正在进行仲裁文书签名"); + caseLogRecord.setNextRoleName("下一节点角色:法律顾问"); + break; + case "14": + caseLogRecord.setCaseNodeName("仲裁文书用印"); + caseLogRecord.setCaseNode(14); + caseLogRecord.setContent("部门长正在进行仲裁文书用印"); + caseLogRecord.setNextRoleName("下一节点角色:法律顾问"); + break; + case "15": + caseLogRecord.setCaseNodeName("仲裁文书送达"); + caseLogRecord.setCaseNode(15); + caseLogRecord.setContent("法律顾问正在进行仲裁文书送达"); + caseLogRecord.setNextRoleName("下一节点角色:法律顾问"); + break; + case "16": + caseLogRecord.setCaseNodeName("案件归档"); + caseLogRecord.setCaseNode(16); + caseLogRecord.setContent("法律顾问正在进行案件归档"); + break; + default: + caseLogRecord.setCaseNodeName("无案件状态"); + caseLogRecord.setContent("无操作内容"); + + } + return caseLogRecord; + } + + @Override + public List selectCaseApplicationList(CaseApplication caseApplication) { + return caseApplicationMapper.selectAdminCaseApplicationList(caseApplication); + + } + + /** + * 新增案件 + * + * @param caseApplication + * @return + */ + @Override + @Transactional + public int insertcaseApplication(CaseApplication caseApplication) { + List columnValueList=caseApplication.getColumnValues(); + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + //根据仲裁费用计费规则计算应缴费用 + //暂时设置计费比率为0.01 + BigDecimal feeRate = new BigDecimal(0.01); + BigDecimal feePayable = caseApplication.getCaseSubjectAmount().multiply(feeRate).setScale(2, BigDecimal.ROUND_HALF_UP); + caseApplication.setFeePayable(feePayable); + // 获取自动编码 + String caseNum = generateCaseNum(); + caseApplication.setCaseNum(caseNum); + // 设置批号 + + caseApplication.setBatchNumber(0); + + caseApplication.setCreateBy(getUsername()); + caseApplication.setVersion(1); + caseApplication.setId(IdWorkerUtil.getId()); + // 新增立案信息 + int rows = caseApplicationMapper.insertCaseApplication(caseApplication); + if (rows == 0) { + return rows; + } + List caseAffiliates = caseApplication.getCaseAffiliates(); + Map deptMap = new HashMap<>(); + // 判断申请机构 + if (caseAffiliates != null && caseAffiliates.size() > 0) { + // 查询所有的组织机构,组装成map + List deptList = sysDeptMapper.selectDeptList(new SysDept()); + if (CollectionUtil.isEmpty(deptList)) { + deptList = new ArrayList<>(); + } + deptMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptName, SysDept::getDeptId, (oldV, newV) -> newV)); + // 查询申请人角色id + Long roleId = roleMapper.selectRoleIdByName("申请人"); + for (CaseAffiliate caseAffiliate : caseAffiliates) { + caseAffiliate.setCaseAppliId(caseApplication.getId()); + // caseAffiliate.setCaseAppliLogId(caseApplication.getId()); + if (caseAffiliate.getIdentityType() == 1 && StrUtil.isNotEmpty(caseAffiliate.getName())) { + // 将组织机构id设为申请人名称 + if (deptMap.containsKey(caseAffiliate.getName())) { + caseAffiliate.setApplicationOrganId(String.valueOf(deptMap.get(caseAffiliate.getName()))); + caseAffiliate.setApplicationOrganName(caseAffiliate.getName()); + } else { + // 如果不存在则新增 + SysDept dept = new SysDept(); + dept.setParentId(0L); + dept.setDeptName(caseAffiliate.getName()); + dept.setAncestors("0"); + dept.setOrderNum(1); + dept.setStatus("0"); + dept.setDelFlag("0"); + dept.setCreateBy(getUsername()); + dept.setUpdateBy(getUsername()); + sysDeptMapper.insertDept(dept); + deptMap.put(dept.getDeptName(), dept.getDeptId()); + caseAffiliate.setApplicationOrganId(String.valueOf(dept.getDeptId())); + caseAffiliate.setApplicationOrganName(caseAffiliate.getName()); + + } + // 组装申请代理人信息 + String agentInfoFlag = buildAgentInfo(caseAffiliate, roleId); + if (StrUtil.isNotEmpty(agentInfoFlag)) { + throw new ServiceException(agentInfoFlag); + } + } + } + // 新增案件关联人 + caseAffiliateMapper.batchCaseAffiliate(caseAffiliates); + } + + List caseAttachList = caseApplication.getCaseAttachList(); + // 是否是压缩包导入,压缩包导入则不更新附件 + boolean isZipImport = caseApplication.getImportFlag() == null || caseApplication.getImportFlag() != 2; + if (caseAttachList != null && caseAttachList.size() > 0 ) { + if(isZipImport) { + for (CaseAttach caseAttach : caseAttachList) { + caseAttach.setCaseAppliId(caseApplication.getId()); + // 修改案件附件 + caseAttachMapper.updateCaseAttach(caseAttach); + } + }else { + // 压缩包导入 + for (CaseAttach caseAttach : caseAttachList) { + caseAttach.setCaseAppliId(caseApplication.getId()); + } + caseAttachMapper.batchSave(caseAttachList); + } + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_APPLICATION, ""); + // 异步新增案件日志 + + ThreadPoolUtil.execute(() -> { + // 批量新增columnValue自定义字段 + if(CollectionUtil.isNotEmpty(columnValueList)) { + columnValueList.forEach(columnValue -> columnValue.setCaseId(caseApplication.getId())); + columnValueMapper.batchSave(columnValueList); + } + // 新增案件日志表 + caseApplication.setCaseAppliId(caseApplication.getId()); + caseApplication.setUpdateSubmitStatus(UpdateSubmitStatus.UNCOMMITTED.getCode()); + caseApplication.setCaseLogId(IdWorkerUtil.getId()); + int insertRow = caseApplicationLogMapper.insert(caseApplication); + // 插入案件相关人员表日志 + if (insertRow != 0 && CollectionUtil.isNotEmpty(caseAffiliates)) { + caseAffiliates.forEach(caseAffiliate -> caseAffiliate.setCaseAppliLogId(caseApplication.getCaseLogId())); + + caseAffiliateLogMapper.batchCaseAffiliate(caseAffiliates); + } + // 插入附件表日志 + if (CollectionUtil.isNotEmpty(caseAttachList)) { + List filterList = caseAttachList.stream().filter(c -> c.getAnnexType().equals(2)).collect(Collectors.toList()); + // 插入日志附件表 + if (CollectionUtil.isNotEmpty(filterList)) { + for (CaseAttach caseAttach : filterList) { + // 查询附件表 + CaseAttach attach = caseAttachMapper.queryAnnexById(caseAttach.getAnnexId()); + attach.setCaseAppliLogId(caseApplication.getCaseLogId()); + caseAttachLogMapper.save(attach); + } + } + + } + // 插入columnValueLog自定义字段日志表 + if (CollectionUtil.isNotEmpty(columnValueList)) { + columnValueList.forEach(caseAffiliate -> caseAffiliate.setCaseAppliLogId(caseApplication.getCaseLogId())); + columnValueLogMapper.batchSave(columnValueList); + + } + + + }); + + return rows; + } + + /** + * 获取自动编码 + * + * @return + */ + + public String generateCaseNum() { + // 自动编码格式 zc+yyyyMMdd+001 + String currentDay = DateUtils.dateTime(); + String caseNum = "zc" + currentDay; + //查询出当天的案件编号的最大值 + Integer maxCaseNum = caseApplicationMapper.selectCaseNumLike(caseNum, caseNum.length()); + if (null == maxCaseNum) { + caseNum = caseNum + "001"; + } else { + maxCaseNum=maxCaseNum+1; + caseNum = caseNum + String.format("%03d", maxCaseNum); + } + return caseNum; + + } + + @Override + public int selectCaseApplicationCount(CaseApplication caseApplication) { + return caseApplicationMapper.selectCaseApplicationCount(caseApplication); + } + + @Override + @Transactional + public AjaxResult editCaseApplication(CaseApplication caseApplication) { + //根据仲裁费用计费规则计算应缴费用 + //暂时设置计费比率为0.01 + BigDecimal feeRate = new BigDecimal("0.01"); + BigDecimal feePayable = caseApplication.getCaseSubjectAmount().multiply(feeRate).setScale(2, RoundingMode.HALF_UP); + caseApplication.setFeePayable(feePayable); + caseApplication.setUpdateBy(getUsername()); + // 立案申请状态直接修改主表信息 + if (caseApplication.getCaseStatus() != null && caseApplication.getCaseStatus().equals(CaseApplicationConstants.CASE_APPLICATION)) { + // 修改内置字段 + caseApplicationMapper.updataCaseApplication(caseApplication); + if(CollectionUtil.isNotEmpty(caseApplication.getColumnValues())) { + // 修改自定义字段 + for (ColumnValue columnValue : caseApplication.getColumnValues()) { + if(StrUtil.isNotEmpty(columnValue.getValue())) { + columnValueMapper.updateColumnValue(columnValue); + } + } + } + // 修改记录表状态为同意提交修改的内容 + caseApplication.setUpdateSubmitStatus(0); + } else { + // 修改记录表状态为已提交修改的内容 + caseApplication.setUpdateSubmitStatus(UpdateSubmitStatus.COMMITTED.getCode()); + } + List caseAffiliates = caseApplication.getCaseAffiliates(); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + // 查询所有的组织机构,组装成map + List deptList = sysDeptMapper.selectDeptList(new SysDept()); + if (CollectionUtil.isEmpty(deptList)) { + deptList = new ArrayList<>(); + } + Map deptMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptName, SysDept::getDeptId, (oldV, newV) -> newV)); + // 查询申请人角色id + Long roleId = roleMapper.selectRoleIdByName("申请人"); + for (CaseAffiliate caseAffiliate : caseAffiliates) { + caseAffiliate.setCaseAppliId(caseApplication.getId()); + if (caseAffiliate.getIdentityType() == 1 && StrUtil.isNotEmpty(caseAffiliate.getName())) { + // 将组织机构id设为申请人名称 + if (deptMap.containsKey(caseAffiliate.getName())) { + caseAffiliate.setApplicationOrganName(caseAffiliate.getName()); + caseAffiliate.setApplicationOrganId(String.valueOf(deptMap.get(caseAffiliate.getName()))); + } else { + // 如果不存在则新增 + SysDept dept = new SysDept(); + dept.setParentId(0L); + dept.setDeptName(caseAffiliate.getName()); + dept.setAncestors("0"); + dept.setOrderNum(1); + dept.setStatus("0"); + dept.setDelFlag("0"); + dept.setCreateBy(getUsername()); + dept.setUpdateBy(getUsername()); + sysDeptMapper.insertDept(dept); + deptMap.put(dept.getDeptName(), dept.getDeptId()); + + caseAffiliate.setApplicationOrganName(caseAffiliate.getName()); + caseAffiliate.setApplicationOrganId(String.valueOf(dept.getDeptId())); + + } + String agentInfoFlag = buildAgentInfo(caseAffiliate, roleId); + if (StrUtil.isNotEmpty(agentInfoFlag)) { + throw new ServiceException(agentInfoFlag); + } + + } + // 立案申请状态直接修改主表信息 + if (caseApplication.getCaseStatus() != null && caseApplication.getCaseStatus().equals(CaseApplicationConstants.CASE_APPLICATION)) { + + caseAffiliateMapper.updataCaseAffiliate(caseAffiliate); + } + } + + } + List caseAttachList = caseApplication.getCaseAttachList(); + // 立案申请状态直接修改主表信息 + if (caseAttachList != null && caseAttachList.size() > 0 + && caseApplication.getCaseStatus() != null && caseApplication.getCaseStatus().equals(CaseApplicationConstants.CASE_APPLICATION)) { + List filterList = caseAttachList.stream().filter(c -> c.getAnnexType().equals(2)).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(filterList)) { + for (CaseAttach caseAttach : caseAttachList) { + caseAttach.setCaseAppliId(caseApplication.getId()); + caseAttachMapper.updateCaseAttach(caseAttach); + } + } + + } + // 根据案件id查询最新版本号 + Integer maxVersion = caseApplicationLogMapper.selectMaxVersionByCaseId(caseApplication.getId()); + if (maxVersion == null) { + maxVersion = 1; + } + caseApplication.setVersion(maxVersion + 1); + // 异步新增案件日志 + ThreadPoolUtil.execute(() -> { + try { + caseApplication.setCaseAppliId(caseApplication.getId()); + caseApplication.setCaseLogId(IdWorkerUtil.getId()); + int insertRow = caseApplicationLogMapper.insert(caseApplication); + if (insertRow != 0) { + if (CollectionUtil.isNotEmpty(caseAffiliates)) { + caseAffiliates.forEach(caseAffiliate -> caseAffiliate.setCaseAppliLogId(caseApplication.getCaseLogId())); + // 插入案件日志人员相关表 + caseAffiliateLogMapper.batchCaseAffiliate(caseAffiliates); + } + if (CollectionUtil.isNotEmpty(caseAttachList)) { + List filterList = caseAttachList.stream().filter(c -> c.getAnnexType().equals(2)).collect(Collectors.toList()); + // 插入日志附件表 + if (CollectionUtil.isNotEmpty(filterList)) { + for (CaseAttach caseAttach : filterList) { + // 查询附件表 + CaseAttach attach = caseAttachMapper.queryAnnexById(caseAttach.getAnnexId()); + attach.setCaseAppliLogId(caseApplication.getCaseLogId()); + caseAttachLogMapper.save(attach); + } + } + + } + // 插入案件columnValueLog自定义字段表 + if (CollectionUtil.isNotEmpty(caseApplication.getColumnValues())) { + caseApplication.getColumnValues().forEach(columnValue -> columnValue.setCaseAppliLogId(caseApplication.getCaseLogId())); + + columnValueLogMapper.batchSave(caseApplication.getColumnValues()); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + return success(); + } + + + /** + * 组装申请代理人信息 + * + * @param caseAffiliate + */ + private String buildAgentInfo(CaseAffiliate caseAffiliate, Long roleId) { + if (caseAffiliate.getIdentityType() == 1 && StrUtil.isNotEmpty(caseAffiliate.getNameAgent())) { + + // 组装申请机构代理人信息,用户表新增并且和部门关联 + // 根据代理人手机号去用户表查询,有修改,么有新增 + SysUser agentUser = sysUserMapper.selectUserByPhone(caseAffiliate.getContactTelphoneAgent()); + if (agentUser == null) { + agentUser = new SysUser(); + agentUser.setIdCard(caseAffiliate.getIdentityNumAgent()); + agentUser.setNickName(caseAffiliate.getNameAgent()); + agentUser.setUserName(caseAffiliate.getContactTelphoneAgent()); + agentUser.setPhonenumber(caseAffiliate.getContactTelphoneAgent()); + agentUser.setPassword(SecurityUtils.encryptPassword("abc123456")); + agentUser.setDeptId(Long.valueOf(caseAffiliate.getApplicationOrganId())); + int insertUserRow = sysUserMapper.insertUser(agentUser); + // 新增角色为申请人 + ArrayList sysUserRoles = new ArrayList<>(); + SysUserRole sysUserRole = new SysUserRole(); + sysUserRole.setUserId(agentUser.getUserId()); + sysUserRole.setRoleId(roleId); + sysUserRoles.add(sysUserRole); + if (CollectionUtil.isNotEmpty(sysUserRoles)) { + userRoleMapper.batchUserRole(sysUserRoles); + } + if (insertUserRow > 0) { + caseAffiliate.setApplicantAgentUserId(String.valueOf(agentUser.getUserId())); + // 尊敬的{1},您的代理的案件已接入仲裁系统,复制访问https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 进入小程序进行认证注册。如非本人操作,请忽略本短信 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setCaseId(caseAffiliate.getCaseAppliId()); + request.setTemplateId("1956159"); + request.setPhone(agentUser.getPhonenumber()); + request.setTemplateParamSet(new String[]{agentUser.getNickName()}); + Boolean aBoolean = SmsUtils.sendSms(request); + + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseAffiliate.getCaseAppliId()); + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseAffiliate.getCaseAppliId()); + caseApplication = caseApplicationMapper.selectCaseApplication(caseApplication); + smsSendRecord.setCaseNum(caseApplication.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + agentUser.getNickName() + ",您的代理的案件已接入仲裁系统,复制访问https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 进入小程序进行认证注册。如非本人操作,请忽略本短信"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } else if (null != agentUser.getDeptId() && !String.valueOf(agentUser.getDeptId()).equals(caseAffiliate.getApplicationOrganId())) { +// return "该申请代理人已在"+agentUser.getDeptName()+"申请机构下存在,请检查填写信息是否正确"; + if (null != agentUser.getDept() && StrUtil.isNotEmpty(agentUser.getDept().getDeptName())) { + return "该申请代理人已在【" + agentUser.getDept().getDeptName() + "】申请机构下存在,请检查填写信息是否正确"; + } else { + return "该申请代理人已存在,与申请机构不匹配,请检查填写信息是否正确"; + } + } else if (null != agentUser.getDeptId() && String.valueOf(agentUser.getDeptId()).equals(caseAffiliate.getApplicationOrganId())) { + // 同步用户表和案件关联人表的手机号和名称 + caseAffiliate.setContactTelphoneAgent(agentUser.getPhonenumber()); + caseAffiliate.setNameAgent(agentUser.getNickName()); + caseAffiliate.setApplicantAgentUserId(String.valueOf(agentUser.getUserId())); + if(StrUtil.isNotEmpty(agentUser.getIdCard())){ + caseAffiliate.setIdentityNumAgent(agentUser.getIdCard()); + }else { + caseAffiliate.setIdentityNumAgent(caseAffiliate.getIdentityNumAgent()); + } + List longList = new ArrayList<>(); + // 新增角色为申请人 + if (CollectionUtil.isNotEmpty(agentUser.getRoles())) { + longList = agentUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()); + if (!longList.contains(roleId)) { + insertAgentUserRole(agentUser, roleId); + } + } else { + + insertAgentUserRole(agentUser, roleId); + } + + } + + } + return null; + } + + /** + * 新增角色为申请人 + * + * @param agentUser + * @param roleId + */ + private void insertAgentUserRole(SysUser agentUser, Long roleId) { + ArrayList sysUserRoles = new ArrayList<>(); + SysUserRole sysUserRole = new SysUserRole(); + sysUserRole.setUserId(agentUser.getUserId()); + sysUserRole.setRoleId(roleId); + sysUserRoles.add(sysUserRole); + if (CollectionUtil.isNotEmpty(sysUserRoles)) { + userRoleMapper.batchUserRole(sysUserRoles); + } + } + + @Override + @Transactional + public int submitCaseApplication(List ids) { + int rows = 0; + // 查询案件信息,做必填校验,校验不通过,提示,不能提交 + StringBuilder errorMsg = new StringBuilder(); + List caseApplications = caseApplicationMapper.listCaseApplicationByIds(ids); + if(CollectionUtil.isNotEmpty(caseApplications)) { + + Map applicationMap = caseApplications.stream().collect(Collectors.toMap(CaseApplication::getId, Function.identity(), (n1, n2) -> n2)); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliateByCaseIds(ids); + // 转换为Map>形式 + Map> caseAffiliateMap = caseAffiliates.stream().collect(Collectors.groupingBy(CaseAffiliate::getCaseAppliId)); + for (Long id : ids) { + // 必填校验 + CaseApplication caseApplication = applicationMap.get(id); + // 基本字段校验 + if(caseApplication!=null) { + for (String baseColumn : baseColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseApplication, baseColumn))){ + errorMsg.append(baseColumn).append("不能为空,"); + // todo 暂抛出异常,后边改为提示具体的字段 + throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + // 校验人员 + if(CollectionUtil.isNotEmpty(caseAffiliates)){ + List affiliateList = caseAffiliateMap.get(id); + if(CollectionUtil.isNotEmpty(affiliateList)){ + for (CaseAffiliate caseAffiliate : affiliateList) { + if(caseAffiliate.getIdentityType()==1){ + // 校验申请人 + for (String applicAffiliateColumn : applicAffiliateColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseAffiliate, applicAffiliateColumn))){ + errorMsg.append(applicAffiliateColumn).append("不能为空,"); + // todo 暂抛出异常,后边改为提示具体的字段 + throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + }else { + // 校验被申请人 + // 校验申请人 + for (String applicAffiliateColumn : dectborAffiliateColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseAffiliate, applicAffiliateColumn))){ + errorMsg.append(applicAffiliateColumn).append("不能为空,"); + // todo 暂抛出异常,后边改为提示具体的字段 + throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + } + } + } + } + } + + CaseApplication application = new CaseApplication(); + application.setId(id); + //提交立案申请 + application.setCaseStatus(CaseApplicationConstants.CASE_CHECK); + rows += caseApplicationMapper.submitCaseApplication(application); + // 新增日志 + insertCaseLog(application.getId(), CaseApplicationConstants.CASE_CHECK, ""); + } + } + return rows; + } + + @Override + @Transactional + public int deletecaseApplicationByIds(List ids) { + // 查出所有的日志id + List logIds= caseApplicationLogMapper.selectLogsByCaseIds(ids); + int rows = caseApplicationMapper.batchDeletecaseApplication(ids); + // 删除日志 + if(CollectionUtil.isNotEmpty(logIds)) { + caseApplicationLogMapper.batchDeleteLog(logIds); + } + return rows; + } + + @Override + public CaseApplication selectCaseApplication(CaseApplication caseApplication) { + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + if(caseApplicationselect==null){ + throw new ServiceException("案件不存在"); + } + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + + ArbitrateRecord arbitrateRecord = new ArbitrateRecord(); + arbitrateRecord.setCaseAppliId(caseApplication.getId()); + ArbitrateRecord arbitrateRecordselect = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecord); + ColumnValue columnValue = new ColumnValue(); + columnValue.setIsDefault(1); + columnValue.setCaseId(caseApplication.getId()); + List columnValueList = columnValueMapper.queryColumnValueList(columnValue); + caseApplicationselect.setColumnValues(columnValueList); + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + if(startIndex!=-1) { + startIndex += prefix.length(); + + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + } + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + + } + } + caseApplicationselect.setCaseAttachList(caseAttachList); + + List caseAffiliatListeselect = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliatListeselect != null) { + // 查询组织机构 + List sysDepts = sysDeptMapper.selectDeptList(new SysDept()); + Map deptMap = new HashMap<>(); + if (CollectionUtil.isNotEmpty(sysDepts)) { + for (SysDept sysDept : sysDepts) { + deptMap.put(String.valueOf(sysDept.getDeptId()), sysDept.getDeptName()); + } + } + StringBuffer applicantName = new StringBuffer(); + StringBuffer respondentName = new StringBuffer(); + for (int i = 0; i < caseAffiliatListeselect.size(); i++) { + CaseAffiliate caseAffiliateselect = caseAffiliatListeselect.get(i); + int identityType = caseAffiliateselect.getIdentityType(); + if (identityType == 1) { + if (StrUtil.isNotEmpty(caseAffiliateselect.getName()) && deptMap.containsKey(caseAffiliateselect.getName())) { + caseAffiliateselect.setName(deptMap.get(caseAffiliateselect.getName())); + } + applicantName.append(caseAffiliateselect.getName()).append(","); + ; + } else if (identityType == 2) { + respondentName.append(caseAffiliateselect.getName()).append(","); + } + } + caseApplicationselect.setApplicantName(applicantName.toString()); + caseApplicationselect.setRespondentName(respondentName.toString()); + caseApplicationselect.setCaseAffiliates(caseAffiliatListeselect); + caseApplicationselect.setArbitrateRecord(arbitrateRecordselect); + + } + return caseApplicationselect; + } + + @Override + @Transactional + public String importCaseApplication(List caseApplicationList, String operName) { + StringBuilder failureMsg = new StringBuilder(); + StringBuilder successMsg = new StringBuilder(); + int successNum = 0; + List caseAffiliateLogList = new ArrayList<>(); + if (caseApplicationList != null && caseApplicationList.size() > 0) { + // 1,查询所有的组织机构,组装成map + List deptList = sysDeptMapper.selectDeptList(new SysDept()); + Map deptMap = new HashMap<>(); + if (CollectionUtil.isNotEmpty(deptList)) { + deptMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptName, SysDept::getDeptId, (oldV, newV) -> newV)); + } + // 查询申请人角色id + Long roleId = roleMapper.selectRoleIdByName("申请人"); + List caseApplicationListinsert = new ArrayList<>(); + for (int i = 0; i < caseApplicationList.size(); i++) { + CaseApplication caseApplication = caseApplicationList.get(i); + CaseImportValid caseImportValid = new CaseImportValid(caseApplication, deptMap); + // 导入校验 + caseImportValid.importValid(caseApplication, deptMap); + // 校验成功的数据 + if (StrUtil.isEmpty(caseApplication.getErrorMsg())) { + //根据仲裁费用计费规则计算应缴费用 + //暂时设置计费比率为0.01 + BigDecimal feeRate = new BigDecimal("0.01"); + BigDecimal feePayable = caseApplication.getCaseSubjectAmount().multiply(feeRate).setScale(2, RoundingMode.HALF_UP); + caseApplication.setFeePayable(feePayable); + + //赋值CaseApplication的案件关联人信息 + List caseAffiliatesnew = new ArrayList<>(); + // 组装案件关联人信息 + assignmentCaseAffiliates(caseApplication, caseAffiliatesnew, deptMap, roleId); + caseApplication.setImportFlag(1); + caseApplicationListinsert.add(caseApplication); + } else { + // 拼接错误信息 + failureMsg.append("
").append("第").append(i + 2).append("行:").append(caseApplication.getErrorMsg().toString()); + } + } + if (caseApplicationListinsert.size() > 0) { + //对不重复的立案对象集合的立案对象重新组装对应的案件关联人信息 + List caseApplicationNewList = null; + for (int i = 0; i < caseApplicationListinsert.size(); i++) { + caseApplicationNewList = new ArrayList<>(); + CaseApplication caseApplicationinsertDiffer = caseApplicationListinsert.get(i); + // 设置自动编码 + caseApplicationinsertDiffer.setCaseNum(generateCaseNum()); + List caseAffiliatesnew = new ArrayList<>(); + CaseApplication caseApplicationNew = new CaseApplication(); + copyCaseApplication(caseApplicationinsertDiffer, caseApplicationNew); + if (caseApplicationListinsert.size() > 0) { + for (int j = 0; j < caseApplicationListinsert.size(); j++) { + CaseApplication caseApplicationinsert = caseApplicationListinsert.get(j); + + if (StringUtils.isNotEmpty(caseApplicationinsert.getCaseNum()) && + caseApplicationinsert.getCaseNum().equals(caseApplicationinsertDiffer.getCaseNum())) { + + caseAffiliatesnew.addAll(caseApplicationinsert.getCaseAffiliates()); + } + } + caseApplicationNew.setCaseAffiliates(caseAffiliatesnew); + caseApplicationNewList.add(caseApplicationNew); + } + + for (int k = 0; k < caseApplicationNewList.size(); k++) { + CaseApplication caseApplicationItera = caseApplicationNewList.get(k); + // 新增立案信息 + caseApplicationItera.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + caseApplicationItera.setCreateBy(getUsername()); + caseApplicationItera.setImportFlag(1); + caseApplicationItera.setId(IdWorkerUtil.getId()); + int rows = caseApplicationMapper.insertCaseApplication(caseApplicationItera); + if (rows == 0) { + continue; + } + // 新增日志 + insertCaseLog(caseApplicationItera.getId(), CaseApplicationConstants.CASE_APPLICATION, ""); + + List caseAffiliates = caseApplicationItera.getCaseAffiliates(); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate caseAffiliate : caseAffiliates) { + caseAffiliate.setCaseAppliId(caseApplicationItera.getId()); + + } + caseAffiliateMapper.batchCaseAffiliate(caseAffiliates); + } + // 新增案件记录 + caseApplicationItera.setCaseAppliId(caseApplicationItera.getId()); + caseApplicationItera.setUpdateSubmitStatus(UpdateSubmitStatus.UNCOMMITTED.getCode()); + caseApplicationItera.setVersion(1); + caseApplicationItera.setCaseLogId(IdWorkerUtil.getId()); + int insertRow = caseApplicationLogMapper.insert(caseApplicationItera); + if (insertRow > 0) { + caseAffiliates.forEach(caseAffiliate -> caseAffiliate.setCaseAppliLogId(caseApplicationItera.getId())); + caseAffiliateLogList.addAll(caseAffiliates); + } + successNum++; + successMsg.append("
").append(successNum).append("、立案编号 ").append(caseApplicationItera.getCaseNum()).append(" 导入成功"); + } + + + } + + } + // 异步新增案件日志 + ThreadPoolUtil.execute(() -> { + if (CollectionUtil.isNotEmpty(caseAffiliateLogList)) { + // 插入案件日志人员相关表 + caseAffiliateLogMapper.batchCaseAffiliate(caseAffiliateLogList); + } + }); + + + } else { + throw new ServiceException("导入立案申请数据不能为空!"); + } + return successMsg.append(failureMsg).toString(); + + } + + + + + @Override + @Transactional + public int pendTral(CaseApplication caseApplication) { + List arbitrators = caseApplication.getArbitrators(); + int rows = 0; + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication.setArbitratorId(idstr); + caseApplication.setArbitratorName(arbitratorNamestr); + caseApplication.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + + + return rows; + } + + @Override + @Transactional + public int pendTralCheck(CaseApplication caseApplication) { + Integer isAgreePendTral = caseApplication.getIsAgreePendTral(); + caseApplication.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + int rows = 0; + //同意组庭 + if (isAgreePendTral != null && isAgreePendTral == 1) { + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + if(caseApplicationselect==null){ + throw new ServiceException("案件不存在"); + } + String arbitratorId = caseApplicationselect.getArbitratorId(); + String arbitratorName = caseApplicationselect.getArbitratorName(); + List arbitrators = caseApplication.getArbitrators(); + if(arbitrators != null && arbitrators.size() > 0 && StringUtils.isEmpty(arbitratorId) && StringUtils.isEmpty(arbitratorName)){ + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication.setArbitratorId(idstr); + caseApplication.setArbitratorName(arbitratorNamestr); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + } else { + List arbitrators = caseApplication.getArbitrators(); + // 仲裁员信息 + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication.setArbitratorId(idstr); + caseApplication.setArbitratorName(arbitratorNamestr); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL, ""); + return rows; + } + + @Override + @Transactional + public int verificationArbitrateRecord(CaseApplication caseApplication) { + // 秘书核验裁决书,流转到待仲裁员审核仲裁文书 + caseApplication.setCaseStatus(CaseApplicationConstants.HEAD_CHECK_ARBITRATION); + int rows = caseApplicationMapper.submitCaseApplication(caseApplication); + ArbitrateRecord arbitrateRecord = caseApplication.getArbitrateRecord(); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.HEAD_CHECK_ARBITRATION, ""); + return rows; + + } + + /** + * 部门长审核裁决书 + * @param caseApplication + * @return + */ + @Override + @Transactional + public AjaxResult checkArbitrateRecord(CaseApplication caseApplication) { + int rows = 0; + ArbitrateRecord arbitrateRecord = caseApplication.getArbitrateRecord(); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord); + Integer agreeOrNotCheck = caseApplication.getAgreeOrNotCheck(); + if (agreeOrNotCheck!=null&&agreeOrNotCheck.intValue() == 1) {//同意审核 + try { + //获取当前案件的裁决书 + CaseApplication caseApplication2 = caseApplicationService.selectCaseApplication(caseApplication); + List caseAttachList = caseApplication2.getCaseAttachList(); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + if (caseAttach.getAnnexType() == 3) { + String annexPath = caseAttach.getAnnexPath(); + String path = "/home/ruoyi" + annexPath; + // System.out.println("这是查询到的裁决书路径" + path); + // String path = "D:\\home\\新裁决书模板.docx"; + //获取文件上传地址 + EsignHttpResponse response = SaaSAPIFileUtils.getUploadUrl(path); + String body = response.getBody(); + if (body != null) { + JSONObject jsonObject = JSONObject.parseObject(body); + String fileId = jsonObject.getJSONObject("data").getString("fileId"); + String fileUploadUrl = jsonObject.getJSONObject("data").getString("fileUploadUrl"); + //上传文件流 + EsignHttpResponse response1 = SaaSAPIFileUtils.uploadFile(fileUploadUrl, path); + JSONObject jsonObject1 = JSONObject.parseObject(response1.getBody()); + if (jsonObject1.getIntValue("errCode") == 0) { + //查看文件上传状态 + Thread.sleep(3000); + EsignHttpResponse response2 = SaaSAPIFileUtils.getFileStatus(fileId); + JSONObject jsonObject2 = JSONObject.parseObject(response2.getBody()); + JSONObject data = jsonObject2.getJSONObject("data"); + int fileStatus = data.getIntValue("fileStatus"); + if (fileStatus == 2 || fileStatus == 5) { + String fileName = data.getString("fileName"); + //上传成功,获取文件签名印章位置 + SealSignRecord sealSignRecord = new SealSignRecord(); + sealSignRecord.setFileid(fileId); + EsignHttpResponse positions = SignAward.getPositions(sealSignRecord); + Gson gson = new Gson(); + JsonObject positionsJsonObject = gson.fromJson(positions.getBody(), JsonObject.class); + JsonObject positionsData = positionsJsonObject.getAsJsonObject("data"); + String keywordPositions = positionsData.get("keywordPositions").toString(); + //发起签署 + sealSignRecord.setFilename(fileName); + String arbitratorId = caseApplication2.getArbitratorId(); + if (arbitratorId != null) { + SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(arbitratorId)); + if (sysUser == null) { + return AjaxResult.error(); + } + sealSignRecord.setPensonAccount(sysUser.getPhonenumber()); + sealSignRecord.setPensonName(sysUser.getNickName()); + } + + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setIsUse(1); + DeptIdentify deptIdentifyselect = new DeptIdentify(); + List deptIdentifysnew = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifysnew != null && deptIdentifysnew.size() > 0) { + deptIdentifyselect = deptIdentifysnew.get(0); + sealSignRecord.setOrgnizeName(deptIdentifyselect.getIdentifyName()); + sealSignRecord.setOrgnizeNamePsnAccount(deptIdentifyselect.getOperPhone()); + sealSignRecord.setOrgnizeNamepsnName(deptIdentifyselect.getOperName()); + } else { + return AjaxResult.error("没有用印时的机构名称及经办人信息"); + } + + //解析文件签名印章位置 + JSONArray jsonArray = JSONArray.parseArray(keywordPositions); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject3 = jsonArray.getJSONObject(i); + String keyword = jsonObject3.getString("keyword"); + if (keyword.equals("仲裁员:")) { + //签名 + JSONArray positionsArray = jsonObject3.getJSONArray("positions"); + // 遍历 positionsArray 中的每个元素 + for (int j = 0; j < positionsArray.size(); j++) { + JSONObject positionObj = positionsArray.getJSONObject(j); + int pageNum = positionObj.getIntValue("pageNum"); + sealSignRecord.setPositionPagepsn(String.valueOf(pageNum)); + JSONArray coordinatesArray = positionObj.getJSONArray("coordinates"); + JSONObject coordinateObj = coordinatesArray.getJSONObject(0); + double positionX = coordinateObj.getDoubleValue("positionX"); + double positionY = coordinateObj.getDoubleValue("positionY"); + sealSignRecord.setPositionXpsn(positionX + 90); + sealSignRecord.setPositionYpsn(positionY); + } + } else { + //用印 + JSONArray positionsArray = jsonObject3.getJSONArray("positions"); + // 遍历 positionsArray 中的每个元素 + for (int j = 0; j < positionsArray.size(); j++) { + JSONObject positionObj = positionsArray.getJSONObject(j); + int pageNum = positionObj.getIntValue("pageNum"); + sealSignRecord.setPositionPageorg(String.valueOf(pageNum)); + JSONArray coordinatesArray = positionObj.getJSONArray("coordinates"); + JSONObject coordinateObj = coordinatesArray.getJSONObject(0); + double positionX = coordinateObj.getDoubleValue("positionX"); + double positionY = coordinateObj.getDoubleValue("positionY"); + sealSignRecord.setPositionXorg(positionX + 90); + sealSignRecord.setPositionYorg(positionY); + } + } + } + /*DeptIdentify deptIdentify1 = new DeptIdentify(); + deptIdentify1.setSealStatus(1); // 印章状态为启用 + //根据机构名称查询部门id + SysDept sysDept = new SysDept(); + sysDept.setDeptName(sealSignRecord.getOrgnizeName()); + List sysDepts = deptMapper.selectDeptList(sysDept); + if (sysDepts != null && sysDepts.size() > 0) { + Long deptId = sysDepts.get(0).getDeptId(); + deptIdentify1.setDeptId(deptId); + } + List deptIdentifies = deptIdentifyMapper.selectDeptIdentifylistother(deptIdentify1); + List sealIds = new ArrayList<>(); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + for (DeptIdentify identify : deptIdentifies) { + String sealId = identify.getSealId(); + sealIds.add(sealId); + } + }*/ + String orgnizeName = sealSignRecord.getOrgnizeName(); //机构名称 + String orgnizeNamepsnName = sealSignRecord.getOrgnizeNamepsnName(); //机构经办人姓名 + String orgnizeNamePsnAccount = sealSignRecord.getOrgnizeNamePsnAccount(); //机构经办人联系方式 + //查询机构信息 + DeptIdentify deptIdentify1 = new DeptIdentify(); + deptIdentify1.setIdentifyName(orgnizeName); + deptIdentify1.setOperName(orgnizeNamepsnName); + deptIdentify1.setOperPhone(orgnizeNamePsnAccount); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify1); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + Long id = deptIdentifies.get(0).getId(); + SealManage sealManage = new SealManage(); + sealManage.setIdentifyId(id); + List sealIdList = new ArrayList<>(); + List selectSealList = sealManageMapper.selectSealList(sealManage); + if (selectSealList != null && selectSealList.size() > 0) { + for (SealManage manage : selectSealList) { + Integer sealStatus = manage.getSealStatus(); + Integer isUse = manage.getIsUse(); + if (sealStatus == 1 && isUse ==1) { + sealIdList.add(manage.getSealId()); + } + } + EsignHttpResponse response3 = SignAward.createByFile(sealSignRecord, sealIdList); + + JSONObject jsonObject3 = JSONObject.parseObject(response3.getBody()); + if (jsonObject3 != null) { + if (jsonObject3.getIntValue("code") == 0) { + //获取签署流程ID + JSONObject data1 = jsonObject3.getJSONObject("data"); + String signFlowId = data1.getString("signFlowId"); + //保存案件id,文件id,文件名称.流程id到签署用印记录表里 + sealSignRecord.setCaseAppliId(caseApplication.getId()); + sealSignRecord.setSignFlowid(signFlowId); + sealSignRecord.setSignFlowStatus(1);//待签名 + sealSignRecordMapper.insertSealSignRecord(sealSignRecord); + } else { + throw new ServiceException(jsonObject3.getString("message")); + } + } else { + return AjaxResult.error(); + } + + } + + + } else { + return AjaxResult.error(); + } + } + } + } + break; + } + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + caseApplication.setCaseStatus(CaseApplicationConstants.SIGN_ARBITRATION); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.SIGN_ARBITRATION, ""); + + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } else if (agreeOrNotCheck.intValue() == 2) {//拒绝审核 + caseApplication.setCaseStatus(CaseApplicationConstants.HEAD_CHECK_ARBITRATION); + String notes=""; + if(caseApplication.getArbitrateRecord()!=null&&StrUtil.isNotEmpty(caseApplication.getArbitrateRecord().getDeptorReject())){ + notes="部门长驳回仲裁文书,驳回原因:"+caseApplication.getArbitrateRecord().getDeptorReject(); + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.HEAD_CHECK_ARBITRATION, notes); + + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + + return success(); + } + + /** + * 仲裁员审核裁决书 + * @param caseApplication + * @return + */ + @Override + @Transactional + public AjaxResult arbitratorCheckArbitrateRecord(CaseApplication caseApplication) { + // 同意后状态改为待部门长审核仲裁文书(CHECK_ARBITRATION = 12),拒绝改为待秘书核验仲裁文书(VERPRIF_ARBITRATION = 11) + int rows = 0; + Integer agreeOrNotCheck = caseApplication.getAgreeOrNotCheck(); + if (agreeOrNotCheck.intValue() == 1) { + caseApplication.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION); + + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CHECK_ARBITRATION, ""); + } else if (agreeOrNotCheck.intValue() == 2) {//拒绝审核 + ArbitrateRecord arbitrateRecord = caseApplication.getArbitrateRecord(); + if(arbitrateRecord.getId()!=null){ + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord); + }else { + arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecord); + } + caseApplication.setCaseStatus(CaseApplicationConstants.VERPRIF_ARBITRATION); + + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + String notes=""; + if(caseApplication.getArbitrateRecord()!=null&&StrUtil.isNotEmpty(caseApplication.getArbitrateRecord().getArbitrateReject())){ + notes="仲裁员驳回仲裁文书,驳回原因:"+caseApplication.getArbitrateRecord().getArbitrateReject(); + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.VERPRIF_ARBITRATION, notes); + } + return success(); + } + + + + @Override + @Transactional + public int submitCaseApplicationCheck(List ids, Integer agreeOrNotCheck,String caseCheckReject) { + //提交立案审查 + int rows = 0; + for (Long id : ids) { + String notes=""; + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + caseApplication.setAgreeOrNotCheck(agreeOrNotCheck); + if (agreeOrNotCheck == 1) {//同意审核 + caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT); + rows += caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_PAYMENT, notes); + } else if (agreeOrNotCheck == 2) {//拒绝审核 + notes="驳回立案申请,驳回原因:"+caseCheckReject; + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + rows += caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_APPLICATION, notes); + ArbitrateRecord arbitrateRecordsel = new ArbitrateRecord(); + arbitrateRecordsel.setCaseAppliId(id); + ArbitrateRecord arbitrateRecordnew = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecordsel); + if(arbitrateRecordnew!=null){ + arbitrateRecordnew.setCaseCheckReject(caseCheckReject); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordnew); + }else { + arbitrateRecordsel.setCaseCheckReject(caseCheckReject); + arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecordsel); + } + //发短信给申请人 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + //查询案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + String caseName = "仲裁"; + String caseNum = caseApplication1.getCaseNum(); + + if (identityType == 1) { + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("2018697"); + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum,caseCheckReject}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已拒绝,拒接原因:" + caseCheckReject; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + + } + + } + } + } + + } + return rows; + } + + @Override + public CaseApplication selectCaseApplicationConfirm(CaseApplication caseApplication) { + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplicationConfirm(caseApplication); + if (caseApplicationselect == null) { + return caseApplicationselect; + } + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliatListeselect = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliatListeselect != null) { + + for (int i = 0; i < caseAffiliatListeselect.size(); i++) { + CaseAffiliate caseAffiliateselect = caseAffiliatListeselect.get(i); + int identityType = caseAffiliateselect.getIdentityType(); + if (identityType == 1) { + + caseApplicationselect.setApplicantName(caseAffiliateselect.getApplicationOrganName()); + } + } + + } + caseApplication.setAnnexType(8); + // 查询缴费凭证 + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + + } + } + caseApplicationselect.setPayOrderList(caseAttachList); + + return caseApplicationselect; + } + + /** + * 给被申请人发送房间号短信 + * + * @param messageVO + * @return + */ + @Override + public String sendRoomNoMessage(SendRoomNoMessageVO messageVO) { + CaseAffiliate caseAffiliateSelect = new CaseAffiliate(); + caseAffiliateSelect.setCaseAppliId(messageVO.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliateSelect); + if (CollectionUtil.isEmpty(caseAffiliates)) { + return "申请人、被申请人不存在"; + } + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(messageVO.getId()); + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + String returnResult = "短信发送成功"; + // 需要申请模板,申请人,被申请人发送短信通知 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + String startFormat = ""; + String endFormat = ""; + // 创建房间短信通知 + String format = "yyyy/MM/dd HH:mm:ss"; // 目标格式 + Date startDate = messageVO.getScheduleStartTime(); + Date endDate = messageVO.getScheduleEndTime(); + SimpleDateFormat sdf = new SimpleDateFormat(format); + if(startDate!=null) { + startFormat = sdf.format(startDate); + } + if(endDate!=null) { + endFormat = sdf.format(endDate); + } + // 预约会议短信模板 + request.setTemplateId("1983711"); + + + for (CaseAffiliate caseAffiliate : caseAffiliates) { + request.setPhone(caseAffiliate.getContactTelphone()); + request.setTemplateParamSet(new String[]{caseAffiliate.getName(), caseApplicationselect.getCaseNum(), messageVO.getRoomNo() + caseAffiliate.getUserId()}); + String userId = (null == caseAffiliate.getUserId() ? "" : caseAffiliate.getUserId()); + // 1983711 开庭审理预约会议短信通知 尊敬的{1}用户,您的{2}仲裁案件,开庭审理房间号为{3},会议时间为{4},请点击https://txroom.xayunmei.com/#/home, 请知晓,如非本人操作,请忽略本短信。 + request.setTemplateParamSet(new String[]{caseAffiliate.getName(), caseApplicationselect.getCaseNum(), messageVO.getRoomNo() , startFormat + "-" + endFormat}); + + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(messageVO.getId()); + smsSendRecord.setCaseNum(caseApplicationselect.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + caseAffiliate.getName() + "用户,您的" + caseApplicationselect.getCaseNum() + "仲裁案件,开庭审理房间号为" + messageVO.getRoomNo() + "会议时间为" + startFormat + "-" + endFormat + ",请点击https://txroom.xayunmei.com/#/home, 请知晓,如非本人操作,请忽略本短信。"; + smsSendRecord.setSendContent(content); + + String userName; + try { + userName = getUsername(); + } catch (Exception e) { + userName = "admin"; + } + smsSendRecord.setCreateBy(userName); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + return returnResult; + } + + @Override + public SealSignRecord selectSignUrl(CaseApplication caseApplication) throws EsignDemoException { + SealSignRecord sealSignRecord = new SealSignRecord(); + sealSignRecord.setCaseAppliId(caseApplication.getId()); + Gson gson = new Gson(); + List sealSignRecords = sealSignRecordMapper.selectSealSignRecord(sealSignRecord); + SealSignRecord sealSignRecordReslt = new SealSignRecord(); + if (sealSignRecords != null && sealSignRecords.size() > 0) { + SealSignRecord sealSignRecordselect = sealSignRecords.get(0); + EsignHttpResponse signUrl = SignAward.signUrl(sealSignRecordselect); + JsonObject signUrlJsonObject = gson.fromJson(signUrl.getBody(), JsonObject.class); + JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); + String url = signUrlData.get("url").getAsString(); + sealSignRecordReslt.setSignUrl(url); + } + + return sealSignRecordReslt; + } + + @Override + public SealSignRecord selectSealUrl(CaseApplication caseApplication) throws EsignDemoException { + SealSignRecord sealSignRecord = new SealSignRecord(); + sealSignRecord.setCaseAppliId(caseApplication.getId()); + Gson gson = new Gson(); + List sealSignRecords = sealSignRecordMapper.selectSealSignRecord(sealSignRecord); + SealSignRecord sealSignRecordReslt = new SealSignRecord(); + if (sealSignRecords != null && sealSignRecords.size() > 0) { + SealSignRecord sealSignRecordselect = sealSignRecords.get(0); + EsignHttpResponse signUrl = SignAward.usesealUrl(sealSignRecordselect); + JsonObject signUrlJsonObject = gson.fromJson(signUrl.getBody(), JsonObject.class); + JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); + String url = signUrlData.get("url").getAsString(); + sealSignRecordReslt.setSealUrl(url); + } + return sealSignRecordReslt; + } + + @Override + @Transactional + public AjaxResult creatTrialRecord(ArbitrateRecord arbitrateRecordselect) { + //生成仲裁结果 + CaseApplication caseApplicationselect = new CaseApplication(); + caseApplicationselect.setId(arbitrateRecordselect.getCaseAppliId()); + CaseApplication caseApplication = caseApplicationMapper.selectCaseApplication(caseApplicationselect); + String createBy = caseApplication.getCreateBy(); + if (createBy != null) { + arbitrateRecordselect.setCreateBy(createBy); + } + // + CaseApplication caseApplicationupdate = new CaseApplication(); + caseApplicationupdate.setId(arbitrateRecordselect.getCaseAppliId()); + caseApplicationupdate.setIsAbsence(arbitrateRecordselect.getIsAbsence()); + caseApplicationupdate.setAppliIsAbsen(arbitrateRecordselect.getAppliIsAbsen()); + caseApplicationupdate.setRespondentOpinion(arbitrateRecordselect.getRespondentOpinion()); + caseApplicationupdate.setApplicantOpinion(arbitrateRecordselect.getApplicantOpinion()); + caseApplicationupdate.setCaseFacts(arbitrateRecordselect.getCaseFacts()); + caseApplicationupdate.setCaseFocus(arbitrateRecordselect.getCaseFocus()); + caseApplicationMapper.submitCaseApplication(caseApplicationupdate); + + //先判断案件是否已经提交过仲裁结果 + ArbitrateRecord arbitrateRecordsele = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecordselect); + if (arbitrateRecordsele != null) { + int i = arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordselect); + if (i > 0) { + //案件日志表里添加数据 + CaseLogRecord caseLogRecord = new CaseLogRecord(); + caseLogRecord.setCaseAppliId(caseApplication.getId()); + caseLogRecord.setCaseNode(caseApplication.getCaseStatus()); + if (createBy != null) { + caseLogRecord.setCreateBy(createBy); + } + caseLogRecordMapper.insertCaseLogRecord(caseLogRecord); + + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.GENERATED_ARBITRATION, ""); + + + } + } else { + //提交仲裁结果 + int i = arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecordselect); + + if (i > 0) { + //案件日志表里添加数据 + CaseLogRecord caseLogRecord = new CaseLogRecord(); + caseLogRecord.setCaseAppliId(caseApplication.getId()); + caseLogRecord.setCaseNode(caseApplication.getCaseStatus()); + if (createBy != null) { + caseLogRecord.setCreateBy(createBy); + } + caseLogRecordMapper.insertCaseLogRecord(caseLogRecord); + + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.GENERATED_ARBITRATION, ""); + + } + } + + //生成庭审笔录 + try { + Map datas = new HashMap<>(); + Long id = caseApplication.getId(); + if (id == null) { + return null; + } + + //获取仲裁记录表里的相关信息 + ArbitrateRecord arbitrateRecord = new ArbitrateRecord(); + arbitrateRecord.setCaseAppliId(id); + ArbitrateRecord arbitrateRecord1 = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecord); + + //获取案件关联人信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + if (identityType == 1) { //申请人 + datas.put("appName", affiliate.getName()); + datas.put("appIDNo", affiliate.getIdentityNum()); + datas.put("appAddress", affiliate.getContactAddress()); + datas.put("appAgentName", affiliate.getNameAgent()); + datas.put("appAgentIDNo", affiliate.getIdentityNumAgent()); + } else if (identityType == 2) { //被申请人 + datas.put("resName", affiliate.getName()); + datas.put("resIDNo", affiliate.getIdentityNum()); + datas.put("resAddress", affiliate.getContactAddress()); + datas.put("resAgentName", affiliate.getNameAgent()); + datas.put("resAgentIDNo", affiliate.getIdentityNumAgent()); + } + } + } + String arbitratorName = caseApplication.getArbitratorName(); + datas.put("caseName", caseApplication.getCaseName()); + datas.put("caseNum", caseApplication.getCaseNum()); + datas.put("arbitratorName", arbitratorName); + Date hearDate = caseApplication.getHearDate(); + if (hearDate != null) { + LocalDate localDate = hearDate.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + datas.put("hearYear", localDate.getYear()); + datas.put("hearMonths", localDate.getMonthValue()); + datas.put("hearDay", localDate.getDayOfMonth()); + } else { + datas.put("hearYear", null); + datas.put("hearMonths", null); + datas.put("hearDay", null); + } + datas.put("appArbitrationClaims", caseApplication.getArbitratClaims()); + datas.put("evidenDetermi", "认定为申请人证据充足"); + datas.put("factDetermi", "被申请人欠款属实"); + datas.put("caseSketch", "申请人所求通过"); + datas.put("arbitrateThink", "被申请人应按约定还款"); + datas.put("rulingFollows", "被申请人依法偿还申请人欠款"); + datas.put("legalProvisions", "仲裁法"); + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + datas.put("year", year); + datas.put("months", month); + datas.put("day", day); + String modalFilePath = "/data/arbitrate-document/template/仲裁裁决书模板.docx"; +// String modalFilePath = "D:/develop/仲裁裁决书模板 (2).docx"; + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; +// String saveFolderPath = "D:/data/" + now.getYear() + "/" + now.getMonthValue() + "/" + now.getDayOfMonth(); + String fileName = UUID.randomUUID().toString().replace("-", "") + ".docx"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String resultFilePath = saveFolderPath + "/" + fileName; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + Path sourcePath = new File(modalFilePath).toPath(); + Path destinationPath = new File(resultFilePath).toPath(); + Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + String docFilePath = WordUtil.getDocFilePath(datas, modalFilePath, resultFilePath); + String savePath = docFilePath.substring(0, docFilePath.indexOf("/upload/") + 8); + +// String savePath = saveFolderPath; +// saveName = fileName; + + caseApplication.setAnnexType(7); + List caseAttachs = caseAttachMapper.queryCaseAttachList(caseApplication); + if (caseAttachs != null && caseAttachs.size() > 0) { + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(7) + .build(); + int i = caseAttachMapper.updateCaseAttachBycaseid(caseAttach); + + } else { + //将庭审笔录保存到附件表里 + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(7) + .build(); + int i = caseAttachMapper.save(caseAttach); + + } + + //获取案件详细信息 + CaseApplication caseApplicationSelct = selectCaseApplication(caseApplication); + return success(caseApplicationSelct); + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error("生成庭审笔录异常"); + } + + } + + @Override + @Transactional + public AjaxResult creatTrialRecordnew(ArbitrateRecord arbitrateRecordselect) { + //生成仲裁结果 + CaseApplication caseApplicationupdate = new CaseApplication(); + caseApplicationupdate.setId(arbitrateRecordselect.getCaseAppliId()); + caseApplicationupdate.setIsAbsence(arbitrateRecordselect.getIsAbsence()); + caseApplicationupdate.setAppliIsAbsen(arbitrateRecordselect.getAppliIsAbsen()); + caseApplicationMapper.submitCaseApplication(caseApplicationupdate); + + //先判断案件是否已经提交过仲裁结果 + ArbitrateRecord arbitrateRecordsele = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecordselect); + if (arbitrateRecordsele != null) { + arbitrateRecordselect.setId(arbitrateRecordsele.getId()); + int i = arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordselect); + } else { + //提交仲裁结果 + int i = arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecordselect); + } + return success(); + + } + + @Override + @Transactional + public AjaxResult editCaseApplicationDefineval(CaseApplication caseApplication) { + if(CollectionUtil.isNotEmpty(caseApplication.getColumnValues())) { + for (ColumnValue columnValue : caseApplication.getColumnValues()) { + columnValueMapper.updateColumnValue(columnValue); + } + } + return success(); + } + + @Override + @Transactional + public CaseAttach downloadCaseZipFile(CaseApplication caseApplication) { + caseApplication.setAnnexType(12); + CaseAttach caseAttach = new CaseAttach(); + List caseAttachs = caseAttachMapper.queryCaseAttachList( caseApplication); + if(caseAttachs!=null&&caseAttachs.size()>0){ + caseAttach = caseAttachs.get(0); + + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + if(startIndex!=-1) { + startIndex += prefix.length(); + + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + } + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + }else { + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setId(caseApplication.getId()); + List annexTypeList = new ArrayList<>(); + annexTypeList.add(1); + annexTypeList.add(2); + annexTypeList.add(3); + annexTypeList.add(6); + annexTypeList.add(7); + annexTypeList.add(9); + annexTypeList.add(11); + caseApplicationsel.setAnnexTypeList(annexTypeList); + List caseAttachList = caseAttachMapper.queryCaseAttachList( caseApplicationsel); + if(caseAttachList!=null&&caseAttachList.size()>0){ + List pathList = new ArrayList<>(); + for (CaseAttach caseAttach1 : caseAttachList) { + String annexName = caseAttach1.getAnnexName(); + String annexPathsel = caseAttach1.getAnnexPath(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + if(startIndex!=-1) { + startIndex += prefix.length(); + + String annexPath = "/uploadPath" + annexName.substring(startIndex); + String path = "/home/ruoyi" + annexPath; + pathList.add(path); + }else if(annexPathsel.contains(annexName)){ + pathList.add(annexPathsel); + } + } + //将案件相关附件压缩zip文件 + if(pathList!=null&&pathList.size()>0){ + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; +// String saveFolderPath = "D:/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".zip"; + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + String zipFileOutPath = saveFolderPath + "/" + fileName; + try { + + FileOutputStream zfous = new FileOutputStream(zipFileOutPath); + ZipOutputStream zipFileOutstream = new ZipOutputStream(zfous); + + for (String pathstr : pathList) { + FileInputStream fis1 = new FileInputStream(pathstr); + ZipFileUtils.zipFile(pathstr, fis1, zipFileOutstream); + } + zipFileOutstream.close(); + zfous.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + //保存压缩文件附件 + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; +// String saveName = "D:/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String savePath = "/home/ruoyi/uploadPath/upload"; + caseAttach = CaseAttach.builder() + .caseAppliId(caseApplication.getId()) + .annexName(saveName) + .annexPath(savePath) + .annexType(12) + .build(); + int i = caseAttachMapper.save(caseAttach); + + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + if(startIndex!=-1) { + startIndex += prefix.length(); + + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + } + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + return caseAttach; + + } + } + } + return caseAttach; + } + + @Override + public List selectCaseApplicationListBatchByRole(CaseApplication caseApplication) { + List caseApplicationlist = caseApplicationMapper.selectAdminCaseApplicationListBatch(caseApplication); + if(caseApplicationlist!=null&&caseApplicationlist.size()>0){ + for(CaseApplication caseApplicationselect : caseApplicationlist){ + Integer batchNumber = caseApplicationselect.getBatchNumber(); + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(batchNumber); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + if (caseApplications != null && caseApplications.size() > 0) { + List caseStatuss = caseApplications.stream().map(CaseApplication::getCaseStatus).collect(Collectors.toList()); + List caseStatusNames = caseApplications.stream().map(CaseApplication::getCaseStatusName).collect(Collectors.toList()); + List caseStatussnew = caseStatuss.stream().distinct().collect(Collectors.toList()); + List caseStatusNamesnew = caseStatusNames.stream().distinct().collect(Collectors.toList()); + String caseStatusName = caseStatusNamesnew.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplicationselect.setCaseStatusName(caseStatusName); + } + } + } + + return caseApplicationlist; + } + + @Override + @Transactional + public int submitCaseApplicationBatch(String batchNumber) { + int rows = 0; + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + List ids = caseApplications.stream().map(CaseApplication::getId).collect(Collectors.toList()); + if(caseApplications!=null&&caseApplications.size()>0){ + Map applicationMap = caseApplications.stream().collect(Collectors.toMap(CaseApplication::getId, Function.identity(), (n1, n2) -> n2)); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliateByCaseIds(ids); + // 转换为Map>形式 + Map> caseAffiliateMap = caseAffiliates.stream().collect(Collectors.groupingBy(CaseAffiliate::getCaseAppliId)); + for (Long id : ids) { + // 查询案件信息,做必填校验,校验不通过,提示,不能提交 + StringBuilder errorMsg = new StringBuilder(); + // 必填校验 + CaseApplication caseApplication = applicationMap.get(id); + String caseNum = caseApplication.getCaseNum(); + // 基本字段校验 + if(caseApplication!=null) { + for (String baseColumn : baseColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseApplication, baseColumn))){ + errorMsg.append(getColumnstr(baseColumn)).append("不能为空,"); +// throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + // 校验人员 + if(CollectionUtil.isNotEmpty(caseAffiliates)){ + List affiliateList = caseAffiliateMap.get(id); + if(CollectionUtil.isNotEmpty(affiliateList)){ + for (CaseAffiliate caseAffiliate : affiliateList) { + if(caseAffiliate.getIdentityType()==1){ + // 校验申请人 + for (String applicAffiliateColumn : applicAffiliateColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseAffiliate, applicAffiliateColumn))){ + errorMsg.append(getColumnstr(applicAffiliateColumn)).append("不能为空,"); +// throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + }else { + // 校验被申请人 + for (String applicAffiliateColumn : dectborAffiliateColumns) { + if(StrUtil.isEmpty( ObjectFieldUtils.getValue(caseAffiliate, applicAffiliateColumn))){ + errorMsg.append(getColumnstr(applicAffiliateColumn)).append("不能为空,"); +// throw new ServiceException("必填字段未填写,请完善案件信息!"); + } + } + } + } + } + } + } + if(StringUtils.isNotEmpty(errorMsg.toString())){ + throw new ServiceException("案件编号" + caseNum + errorMsg.toString()+"请完善案件信息!"); + } + + CaseApplication application = new CaseApplication(); + application.setId(id); + //提交立案申请 + application.setCaseStatus(CaseApplicationConstants.CASE_CHECK); + rows += caseApplicationMapper.submitCaseApplication(application); + // 新增日志 + insertCaseLog(application.getId(), CaseApplicationConstants.CASE_CHECK, ""); + } + + }else{ + throw new ServiceException("这个批号没有批量提交的案件"); + } + + return rows; + } + + @Override + @Transactional + public int submitCaseApplicationCheckBatch(String batchNumber, Integer agreeOrNotCheck, String caseCheckReject) { + int rows = 0; + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.CASE_CHECK); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + List ids = caseApplications.stream().map(CaseApplication::getId).collect(Collectors.toList()); + if(caseApplications!=null&&caseApplications.size()>0){ + for (Long id : ids) { + String notes=""; + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + caseApplication.setAgreeOrNotCheck(agreeOrNotCheck); + if (agreeOrNotCheck == 1) { + //同意审核 + caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT); + rows += caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_PAYMENT, notes); + } else if (agreeOrNotCheck == 2) { + //拒绝审核 + notes="驳回立案申请,驳回原因:"+caseCheckReject; + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + rows += caseApplicationMapper.submitCaseApplication(caseApplication); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_APPLICATION, notes); + ArbitrateRecord arbitrateRecordsel = new ArbitrateRecord(); + arbitrateRecordsel.setCaseAppliId(id); + ArbitrateRecord arbitrateRecordnew = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecordsel); + if(arbitrateRecordnew!=null){ + arbitrateRecordnew.setCaseCheckReject(caseCheckReject); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordnew); + }else { + arbitrateRecordsel.setCaseCheckReject(caseCheckReject); + arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecordsel); + } + //发短信给申请人 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + //查询案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + String caseName = "仲裁"; + String caseNum = caseApplication1.getCaseNum(); + + if (identityType == 1) { + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("2018697"); + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum,caseCheckReject}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已拒绝,拒接原因:" + caseCheckReject; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + + } + + } + } + } + } + }else{ + throw new ServiceException("这个批号没有批量审查的案件"); + } + return rows; + } + + @Override + @Transactional + public int pendTralCheckBatch(CaseApplication caseApplication) { + Integer isAgreePendTral = caseApplication.getIsAgreePendTral(); + int rows = 0; + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(caseApplication.getBatchNumber()); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.CASE_CROSSEXAMI); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + if (caseApplications != null && caseApplications.size() > 0) { + List caseNums = caseApplications.stream().map(CaseApplication::getCaseNum).collect(Collectors.toList()); + List caseNumsnew = caseNums.stream().distinct().collect(Collectors.toList()); + String caseNumsstr = caseNumsnew.stream().map(Object::toString).collect(Collectors.joining(",")); + throw new ServiceException("案件编号"+caseNumsstr+"在案件质证节点,请先进行案件质证,然后再批量组庭审核"); + } + + + + CaseApplication caseApplication1 = new CaseApplication(); + caseApplication1.setBatchNumber(caseApplication.getBatchNumber()); + caseApplication1.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL_SUBMMIT); + List caseApplications1 = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplication1); + if (caseApplications1 != null && caseApplications1.size() > 0) { + for(CaseApplication caseApplicationse:caseApplications1){ + //同意组庭 + if (isAgreePendTral != null && isAgreePendTral == 1) { + + String arbitratorId = caseApplicationse.getArbitratorId(); + String arbitratorName = caseApplicationse.getArbitratorName(); + List arbitrators = caseApplication.getArbitrators(); + if(arbitrators != null && arbitrators.size() > 0 && StringUtils.isEmpty(arbitratorId) && StringUtils.isEmpty(arbitratorName)){ + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplicationse.setArbitratorId(idstr); + caseApplicationse.setArbitratorName(arbitratorNamestr); + caseApplicationse.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + } + } else { + List arbitrators = caseApplication.getArbitrators(); + // 仲裁员信息 + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplicationse.setArbitratorId(idstr); + caseApplicationse.setArbitratorName(arbitratorNamestr); + caseApplicationse.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + } + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL, ""); + + } + }else{ + throw new ServiceException("这个批号没有批量组庭审核的案件"); + } + return rows; + } + + @Override + @Transactional + public int pendTralSureBatch(CaseApplication caseApplication) { + Integer isAgreePendTral = caseApplication.getIsAgreePendTral(); + int rows = 0; + CaseApplication caseApplication1 = new CaseApplication(); + caseApplication1.setBatchNumber(caseApplication.getBatchNumber()); + caseApplication1.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplication1); + if (caseApplications != null && caseApplications.size() > 0) { + for(CaseApplication caseApplicationse:caseApplications){ + caseApplicationse.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION_METHOD); + caseApplicationse.setIsAgreePendTral(isAgreePendTral); + if (isAgreePendTral != null && isAgreePendTral == 1) { + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + } else { + List arbitrators = caseApplication.getArbitrators(); + // 仲裁员信息 + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplicationse.setArbitratorId(idstr); + caseApplicationse.setArbitratorName(arbitratorNamestr); + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + } + } + + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("2033619"); + sendHearDateMessage(caseApplicationse, request, "2033619"); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CHECK_ARBITRATION_METHOD, ""); + + } + }else{ + throw new ServiceException("这个批号没有批量组庭审核的案件"); + } + return rows; + } + + @Override + @Transactional + public int verificationArbitrateRecordBatch(CaseApplication caseApplication) { + CaseApplication caseApplication1 = new CaseApplication(); + caseApplication1.setBatchNumber(caseApplication.getBatchNumber()); + caseApplication1.setCaseStatus(CaseApplicationConstants.VERPRIF_ARBITRATION); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplication1); + int rows = 0; + if (caseApplications != null && caseApplications.size() > 0) { + for(CaseApplication caseApplicationse:caseApplications){ + // 秘书核验裁决书,流转到待仲裁员审核仲裁文书 + caseApplicationse.setCaseStatus(CaseApplicationConstants.HEAD_CHECK_ARBITRATION); + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); +// ArbitrateRecord arbitrateRecord = caseApplication.getArbitrateRecord(); +// arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord); + // 新增日志 + insertCaseLog(caseApplicationse.getId(), CaseApplicationConstants.HEAD_CHECK_ARBITRATION, ""); + } + }else{ + throw new ServiceException("这个批号没有批量核验裁决书的案件"); + } + + return rows; + } + + @Override + @Transactional + public AjaxResult arbitratorCheckArbitrateRecordBatch(CaseApplication caseApplication) { + int rows = 0; + Integer agreeOrNotCheck = caseApplication.getAgreeOrNotCheck(); + + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(caseApplication.getBatchNumber()); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.HEAD_CHECK_ARBITRATION); + List caseApplications1 = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + if (caseApplications1 != null && caseApplications1.size() > 0) { + for(CaseApplication caseApplicationse:caseApplications1){ + if (agreeOrNotCheck.intValue() == 1) { + caseApplicationse.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION); + + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CHECK_ARBITRATION, ""); + } else if (agreeOrNotCheck.intValue() == 2) {//拒绝审核 + ArbitrateRecord arbitrateRecord = caseApplication.getArbitrateRecord(); + ArbitrateRecord arbitrateRecordnew = caseApplicationse.getArbitrateRecord(); + if(arbitrateRecordnew!=null){ + arbitrateRecordnew.setCheckOpinion(arbitrateRecord.getCheckOpinion()); + arbitrateRecordnew.setArbitrateReject(arbitrateRecord.getArbitrateReject()); + arbitrateRecordnew.setCaseAppliId(caseApplicationse.getId()); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecordnew); + }else { + ArbitrateRecord arbitrateRecordnew1 = new ArbitrateRecord(); + arbitrateRecordnew1.setCheckOpinion(arbitrateRecord.getCheckOpinion()); + arbitrateRecordnew1.setArbitrateReject(arbitrateRecord.getArbitrateReject()); + arbitrateRecordnew1.setCaseAppliId(caseApplicationse.getId()); + arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecordnew1); + } + caseApplicationse.setCaseStatus(CaseApplicationConstants.VERPRIF_ARBITRATION); + + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + String notes=""; + if(caseApplication.getArbitrateRecord()!=null&&StrUtil.isNotEmpty(caseApplication.getArbitrateRecord().getArbitrateReject())){ + notes="仲裁员驳回仲裁文书,驳回原因:"+caseApplication.getArbitrateRecord().getArbitrateReject(); + } + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.VERPRIF_ARBITRATION, notes); + } + } + + }else{ + throw new ServiceException("这个批号没有批量仲裁员审核裁决书的案件"); + } + + return success(rows); + } + + @Override + @Transactional + public AjaxResult checkArbitrateRecordBatch(CaseApplication caseApplication) { + Integer agreeOrNotCheck = caseApplication.getAgreeOrNotCheck(); + int rows = 0; + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(caseApplication.getBatchNumber()); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION); + List caseApplications1 = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + if (caseApplications1 != null && caseApplications1.size() > 0) { + for(CaseApplication caseApplicationse:caseApplications1){ + if (agreeOrNotCheck.intValue() == 1) { + try { + //获取当前案件的裁决书 + CaseApplication caseApplication2 = caseApplicationService.selectCaseApplication(caseApplicationse); + List caseAttachList = caseApplication2.getCaseAttachList(); + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + if (caseAttach.getAnnexType() == 3) { + String annexPath = caseAttach.getAnnexPath(); + String path = "/home/ruoyi" + annexPath; + // System.out.println("这是查询到的裁决书路径" + path); + // String path = "D:\\home\\新裁决书模板.docx"; + //获取文件上传地址 + EsignHttpResponse response = SaaSAPIFileUtils.getUploadUrl(path); + String body = response.getBody(); + if (body != null) { + JSONObject jsonObject = JSONObject.parseObject(body); + String fileId = jsonObject.getJSONObject("data").getString("fileId"); + String fileUploadUrl = jsonObject.getJSONObject("data").getString("fileUploadUrl"); + //上传文件流 + EsignHttpResponse response1 = SaaSAPIFileUtils.uploadFile(fileUploadUrl, path); + JSONObject jsonObject1 = JSONObject.parseObject(response1.getBody()); + if (jsonObject1.getIntValue("errCode") == 0) { + //查看文件上传状态 + Thread.sleep(3000); + EsignHttpResponse response2 = SaaSAPIFileUtils.getFileStatus(fileId); + JSONObject jsonObject2 = JSONObject.parseObject(response2.getBody()); + JSONObject data = jsonObject2.getJSONObject("data"); + int fileStatus = data.getIntValue("fileStatus"); + if (fileStatus == 2 || fileStatus == 5) { + String fileName = data.getString("fileName"); + //上传成功,获取文件签名印章位置 + SealSignRecord sealSignRecord = new SealSignRecord(); + sealSignRecord.setFileid(fileId); + EsignHttpResponse positions = SignAward.getPositions(sealSignRecord); + Gson gson = new Gson(); + JsonObject positionsJsonObject = gson.fromJson(positions.getBody(), JsonObject.class); + JsonObject positionsData = positionsJsonObject.getAsJsonObject("data"); + String keywordPositions = positionsData.get("keywordPositions").toString(); + //发起签署 + sealSignRecord.setFilename(fileName); + String arbitratorId = caseApplication2.getArbitratorId(); + if (arbitratorId != null) { + SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(arbitratorId)); + if (sysUser == null) { + return AjaxResult.error(); + } + sealSignRecord.setPensonAccount(sysUser.getPhonenumber()); + sealSignRecord.setPensonName(sysUser.getNickName()); + } + + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setIsUse(1); + DeptIdentify deptIdentifyselect = new DeptIdentify(); + List deptIdentifysnew = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifysnew != null && deptIdentifysnew.size() > 0) { + deptIdentifyselect = deptIdentifysnew.get(0); + sealSignRecord.setOrgnizeName(deptIdentifyselect.getIdentifyName()); + sealSignRecord.setOrgnizeNamePsnAccount(deptIdentifyselect.getOperPhone()); + sealSignRecord.setOrgnizeNamepsnName(deptIdentifyselect.getOperName()); + } else { + return AjaxResult.error("没有用印时的机构名称及经办人信息"); + } + + //解析文件签名印章位置 + JSONArray jsonArray = JSONArray.parseArray(keywordPositions); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject3 = jsonArray.getJSONObject(i); + String keyword = jsonObject3.getString("keyword"); + if (keyword.equals("仲裁员:")) { + //签名 + JSONArray positionsArray = jsonObject3.getJSONArray("positions"); + // 遍历 positionsArray 中的每个元素 + for (int j = 0; j < positionsArray.size(); j++) { + JSONObject positionObj = positionsArray.getJSONObject(j); + int pageNum = positionObj.getIntValue("pageNum"); + sealSignRecord.setPositionPagepsn(String.valueOf(pageNum)); + JSONArray coordinatesArray = positionObj.getJSONArray("coordinates"); + JSONObject coordinateObj = coordinatesArray.getJSONObject(0); + double positionX = coordinateObj.getDoubleValue("positionX"); + double positionY = coordinateObj.getDoubleValue("positionY"); + sealSignRecord.setPositionXpsn(positionX + 90); + sealSignRecord.setPositionYpsn(positionY); + } + } else { + //用印 + JSONArray positionsArray = jsonObject3.getJSONArray("positions"); + // 遍历 positionsArray 中的每个元素 + for (int j = 0; j < positionsArray.size(); j++) { + JSONObject positionObj = positionsArray.getJSONObject(j); + int pageNum = positionObj.getIntValue("pageNum"); + sealSignRecord.setPositionPageorg(String.valueOf(pageNum)); + JSONArray coordinatesArray = positionObj.getJSONArray("coordinates"); + JSONObject coordinateObj = coordinatesArray.getJSONObject(0); + double positionX = coordinateObj.getDoubleValue("positionX"); + double positionY = coordinateObj.getDoubleValue("positionY"); + sealSignRecord.setPositionXorg(positionX + 90); + sealSignRecord.setPositionYorg(positionY); + } + } + } + /*DeptIdentify deptIdentify1 = new DeptIdentify(); + deptIdentify1.setSealStatus(1); // 印章状态为启用 + //根据机构名称查询部门id + SysDept sysDept = new SysDept(); + sysDept.setDeptName(sealSignRecord.getOrgnizeName()); + List sysDepts = deptMapper.selectDeptList(sysDept); + if (sysDepts != null && sysDepts.size() > 0) { + Long deptId = sysDepts.get(0).getDeptId(); + deptIdentify1.setDeptId(deptId); + } + List deptIdentifies = deptIdentifyMapper.selectDeptIdentifylistother(deptIdentify1); + List sealIds = new ArrayList<>(); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + for (DeptIdentify identify : deptIdentifies) { + String sealId = identify.getSealId(); + sealIds.add(sealId); + } + }*/ + String orgnizeName = sealSignRecord.getOrgnizeName(); //机构名称 + String orgnizeNamepsnName = sealSignRecord.getOrgnizeNamepsnName(); //机构经办人姓名 + String orgnizeNamePsnAccount = sealSignRecord.getOrgnizeNamePsnAccount(); //机构经办人联系方式 + //查询机构信息 + DeptIdentify deptIdentify1 = new DeptIdentify(); + deptIdentify1.setIdentifyName(orgnizeName); + deptIdentify1.setOperName(orgnizeNamepsnName); + deptIdentify1.setOperPhone(orgnizeNamePsnAccount); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify1); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + Long id = deptIdentifies.get(0).getId(); + SealManage sealManage = new SealManage(); + sealManage.setIdentifyId(id); + List sealIdList = new ArrayList<>(); + List selectSealList = sealManageMapper.selectSealList(sealManage); + if (selectSealList != null && selectSealList.size() > 0) { + for (SealManage manage : selectSealList) { + Integer sealStatus = manage.getSealStatus(); + Integer isUse = manage.getIsUse(); + if (sealStatus == 1 && isUse ==1) { + sealIdList.add(manage.getSealId()); + } + } + EsignHttpResponse response3 = SignAward.createByFile(sealSignRecord, sealIdList); + + JSONObject jsonObject3 = JSONObject.parseObject(response3.getBody()); + if (jsonObject3 != null) { + if (jsonObject3.getIntValue("code") == 0) { + //获取签署流程ID + JSONObject data1 = jsonObject3.getJSONObject("data"); + String signFlowId = data1.getString("signFlowId"); + //保存案件id,文件id,文件名称.流程id到签署用印记录表里 + sealSignRecord.setCaseAppliId(caseApplicationse.getId()); + sealSignRecord.setSignFlowid(signFlowId); + sealSignRecord.setSignFlowStatus(1);//待签名 + sealSignRecordMapper.insertSealSignRecord(sealSignRecord); + } else { + throw new ServiceException(jsonObject3.getString("message")); + } + } else { + return AjaxResult.error(); + } + + } + + + } else { + return AjaxResult.error(); + } + } + } + } + break; + } + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + caseApplicationse.setCaseStatus(CaseApplicationConstants.SIGN_ARBITRATION); + // 新增日志 + insertCaseLog(caseApplicationse.getId(), CaseApplicationConstants.SIGN_ARBITRATION, ""); + rows += caseApplicationMapper.submitCaseApplication(caseApplicationse); + } else if (agreeOrNotCheck.intValue() == 2) { + caseApplicationse.setCaseStatus(CaseApplicationConstants.HEAD_CHECK_ARBITRATION); + String notes=""; + if(caseApplication.getArbitrateRecord()!=null&&StrUtil.isNotEmpty(caseApplication.getArbitrateRecord().getDeptorReject())){ + notes="部门长驳回仲裁文书,驳回原因:"+caseApplication.getArbitrateRecord().getDeptorReject(); + } + // 新增日志 + insertCaseLog(caseApplicationse.getId(), CaseApplicationConstants.HEAD_CHECK_ARBITRATION, notes); + + rows = caseApplicationMapper.submitCaseApplication(caseApplicationse); + + } + + } + + } + return success(rows); + + } + + private String getColumnstr(String columnname) { + String columnstr = ""; + switch (columnname) { + case "caseName": + columnstr = "案件名称"; + break; + case "caseSubjectAmount": + columnstr = "案件标的"; + break; + case "loanStartDate": + columnstr = "借款开始日期"; + break; + case "loanEndDate": + columnstr = "借款结束日期"; + break; + case "contractNumber": + columnstr = "合同编号"; + break; + case "claimInterestOwed": + columnstr = "申请人主张欠利息"; + break; + case "claimLiquidDamag": + columnstr = "申请人主张违约金"; + break; + case "claimPrinciOwed": + columnstr = "申请人主张欠本金"; + break; + case "arbitratClaims": + columnstr = "申请人仲裁请求及事实和理由"; + break; + case "name": + columnstr = "姓名"; + break; + case "identityNum": + columnstr = "身份证号"; + break; + case "contactTelphone": + columnstr = "联系电话"; + break; + case "contactAddress": + columnstr = "联系地址"; + break; + case "workTelphone": + columnstr = "单位电话"; + break; + case "workAddress": + columnstr = "单位地址"; + break; + case "residenAffili": + columnstr = "住所"; + break; + case "compLegalPerson": + columnstr = "法定代表人"; + break; + case "compLegalperPost": + columnstr = "法定代表人职位"; + break; + case "email": + columnstr = "邮箱"; + break; + case "nameAgent": + columnstr = "代理人姓名"; + break; + case "identityNumAgent": + columnstr = "代理人身份证号"; + break; + case "contactTelphoneAgent": + columnstr = "代理人联系电话"; + break; + case "contactAddressAgent": + columnstr = "代理人联系地址"; + break; + case "responSex": + columnstr = "被申请人性别"; + break; + case "responBirth": + columnstr = "被申请人出生年月日"; + break; + default: + columnstr = ""; + } + + return columnstr; + } + + + @Override + public CaseApplication selectSignSealUrl(CaseApplication caseApplication) throws EsignDemoException { + Gson gson = new Gson(); + SealSignRecord sealSignRecord = new SealSignRecord(); + sealSignRecord.setCaseAppliId(caseApplication.getId()); + List sealSignRecords = sealSignRecordMapper.selectSealSignRecord(sealSignRecord); + if (sealSignRecords != null && sealSignRecords.size() > 0) { + String signFlowid = sealSignRecords.get(0).getSignFlowid(); + EsignHttpResponse fileDownload = SaaSAPIFileUtils.fileDownloadUrl(signFlowid); + JsonObject fileDownloadJsonObject = gson.fromJson(fileDownload.getBody(), JsonObject.class); + JsonObject fileDownloadData = fileDownloadJsonObject.getAsJsonObject("data"); + JsonArray filesArray = fileDownloadData.get("files").getAsJsonArray(); + if (filesArray != null && filesArray.size() > 0) { + JsonObject fileObject = (JsonObject) filesArray.get(0); + String fileDownloadUrl = fileObject.get("downloadUrl").toString(); + String filearbitraUrl = fileDownloadUrl.substring(1, fileDownloadUrl.length() - 1); + caseApplication.setFilearbitraUrl(filearbitraUrl); + } + } + + return caseApplication; + } + + + @Override + @Transactional + public int pendTralSure(CaseApplication caseApplication) { +// caseApplication.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION_METHOD); + + caseApplication.setCaseStatus(CaseApplicationConstants.CHECK_ARBITRATION_METHOD); + Integer isAgreePendTral = caseApplication.getIsAgreePendTral(); + int rows = 0; + //同意组庭 + if (isAgreePendTral != null && isAgreePendTral == 1) { + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } else { + List arbitrators = caseApplication.getArbitrators(); + // 仲裁员信息 + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication.setArbitratorId(idstr); + caseApplication.setArbitratorName(arbitratorNamestr); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + } + + //发送短信通知 1947342 尊敬的{1}用户,您的{2}仲裁案件,开庭日期已确定为{3},请知晓,如非本人操作,请忽略本短信。 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("2033619"); + // 发送开庭日期通知短信 + sendHearDateMessage(caseApplication, request, "2033619"); + // 新增日志 + insertCaseLog(caseApplication.getId(), CaseApplicationConstants.MODIFY_HEARDATE, ""); + + return rows; + + } + + /** + * 发送开庭日期通知短信 + * + * @param caseApplication + * @param request + */ + private void sendHearDateMessage(CaseApplication caseApplication, SmsUtils.SendSmsRequest request, String templateId) { + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + + String caseNum = caseApplicationselect.getCaseNum(); + Date hearDate = caseApplicationselect.getHearDate(); + String hearDatestr = ""; + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + if(hearDate!=null) { + hearDatestr = dateFormat.format(hearDate); + } + String arbitratorId = caseApplicationselect.getArbitratorId(); +// List arbitratorList = new ArrayList<>(); + if (StringUtils.isNotEmpty(arbitratorId)) { + String[] idStrList = arbitratorId.split(","); + List idList = new ArrayList<>(); + for (int i = 0; i < idStrList.length; i++) { + idList.add(Long.parseLong(idStrList[i])); + } + // 查询仲裁员电话号 + List userList = sysUserMapper.selectUserListByIds(idList); + if (CollectionUtil.isNotEmpty(userList)) { + for (SysUser user : userList) { + //给仲裁员发送短信通知 + request.setPhone(user.getPhonenumber()); + // 1947342 普通短信 开庭日期通知 尊敬的{1}用户,您的{2}仲裁案件,开庭日期已确定为{3},请知晓,如非本人操作,请忽略本短信。 + String name = user.getNickName(); + if (templateId.equals("2033619")) { + request.setTemplateParamSet(new String[]{name, caseNum}); + } + if (templateId.equals("1975139")) { + request.setTemplateParamSet(new String[]{name, caseNum, hearDatestr}); + } + + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplicationselect.getId()); + smsSendRecord.setCaseNum(caseApplicationselect.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = ""; + if (templateId.equals("2033619")) { + content = "尊敬的" + name + "用户,您的" + caseNum + "仲裁案件,已组庭,请知晓,如非本人操作,请忽略本短信。"; + } + if (templateId.equals("1975139")) { + content = "尊敬的" + name + "用户,您的" + caseNum + "仲裁案件,开庭日期已改为" + hearDatestr + ",请知晓,如非本人操作,请忽略本短信。"; + } + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } + + } + + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliatListeselect = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + if (caseAffiliatListeselect != null) { + + for (int j = 0; j < caseAffiliatListeselect.size(); j++) { + CaseAffiliate caseAffiliateselect = caseAffiliatListeselect.get(j); + int identityType = caseAffiliateselect.getIdentityType(); + if (identityType == 1) { + caseAffiliateselect.setName(caseAffiliateselect.getApplicationOrganName()); + + } + //给申请人、被申请人发送短信通知 + request.setPhone(caseAffiliateselect.getContactTelphone()); + // 1947342 普通短信 开庭日期通知 尊敬的{1}用户,您的{2}仲裁案件,开庭日期已确定为{3},请知晓,如非本人操作,请忽略本短信。 + String name = caseAffiliateselect.getName(); + if (templateId.equals("2033619")) { + request.setTemplateParamSet(new String[]{name, caseNum}); + } + if (templateId.equals("1975139")) { + request.setTemplateParamSet(new String[]{name, caseNum, hearDatestr}); + } + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseApplicationselect.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = ""; + if (templateId.equals("2033619")) { + content = "尊敬的" + name + "用户,您的" + caseNum + "仲裁案件,已组庭,请知晓,如非本人操作,请忽略本短信。"; + } + if (templateId.equals("1975139")) { + content = "尊敬的" + name + "用户,您的" + caseNum + "仲裁案件,开庭日期已改为" + hearDatestr + ",请知晓,如非本人操作,请忽略本短信。"; + } + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } + } + + + @Override + @Transactional + public int pendingAppointArbotrar(CaseApplication caseApplication) { + int pendingAppointArbotrar = caseApplication.getPendingAppointArbotrar(); + List arbitrators = caseApplication.getArbitrators(); + int rows = 0; + if (pendingAppointArbotrar == 1) { + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication.setArbitratorId(idstr); + caseApplication.setArbitratorName(arbitratorNamestr); + caseApplication.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL); + caseApplication.setPendingAppointArbotrar(1); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + } + + } else { + caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_TRIAL); + caseApplication.setPendingAppointArbotrar(2); + rows = caseApplicationMapper.submitCaseApplication(caseApplication); + + } + + return rows; + + } + + + private void assignmentCaseAffiliates(CaseApplication caseApplication, List caseAffiliatesnew, + Map deptMap, Long roleId) { + // 申请人信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate = buildApplicaInfo(caseApplication); + // 申请人(机构),需要判断部门中是否存在,不存在则新增,当身份类型为1的时候,查询时需要根据名称查询组织机构 + if (StrUtil.isNotEmpty(caseApplication.getName())) { + setApplicantOrganization(caseAffiliate, caseApplication, deptMap); + } + String s = buildAgentInfo(caseAffiliate, roleId); + if (StrUtil.isNotEmpty(s)) { + StringBuilder errorMsg = caseApplication.getErrorMsg(); + if (StrUtil.isEmpty(errorMsg)) { + errorMsg = new StringBuilder(); + } + errorMsg.append(s); + caseApplication.setErrorMsg(errorMsg); + } + caseAffiliatesnew.add(caseAffiliate); + + // 组装被申请人信息 + caseAffiliatesnew.add(buildDebtorInfo(caseApplication)); + caseApplication.setCaseAffiliates(caseAffiliatesnew); + } + + private CaseAffiliate buildApplicaInfo(CaseApplication caseApplication) { + // 申请人信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + caseAffiliate.setIdentityType(1); + caseAffiliate.setName(caseApplication.getName()); + caseAffiliate.setIdentityNum(caseApplication.getIdentityNum()); + caseAffiliate.setContactTelphone(caseApplication.getContactTelphone()); + caseAffiliate.setContactAddress(caseApplication.getContactAddress()); + caseAffiliate.setWorkTelphone(caseApplication.getWorkTelphone()); + caseAffiliate.setWorkAddress(caseApplication.getWorkAddress()); + caseAffiliate.setNameAgent(caseApplication.getNameAgent()); + caseAffiliate.setIdentityNumAgent(caseApplication.getIdentityNumAgent()); + caseAffiliate.setContactTelphoneAgent(caseApplication.getContactTelphoneAgent()); + caseAffiliate.setContactAddressAgent(caseApplication.getContactAddressAgent()); + caseAffiliate.setCompLegalperPost(caseApplication.getCompLegalperPost()); + caseAffiliate.setCompLegalPerson(caseApplication.getCompLegalPerson()); + + caseAffiliate.setResidenAffili(caseApplication.getResidenAffiliAppli()); + caseAffiliate.setAppliAgentTitle(caseApplication.getAppliAgentTitle()); + caseAffiliate.setEmail(caseApplication.getEmail()); + return caseAffiliate; + + + } + + /** + * 设置申请人的组织机构 + * + * @param caseAffiliate + * @param caseApplication + */ + @DataScope(deptAlias = "d") + private void setApplicantOrganization(CaseAffiliate caseAffiliate, CaseApplication caseApplication, Map deptMap) { + + + // 将组织机构id设为申请人名称 + if (deptMap.containsKey(caseApplication.getName())) { + caseAffiliate.setApplicationOrganId(String.valueOf(deptMap.get(caseApplication.getName()))); + caseAffiliate.setApplicationOrganName(caseApplication.getName()); + } else { + // 如果不存在则新增 + SysDept dept = new SysDept(); + dept.setParentId(0L); + dept.setDeptName(caseApplication.getName()); + dept.setAncestors("0"); + dept.setOrderNum(1); + dept.setStatus("0"); + dept.setDelFlag("0"); + dept.setCreateBy(getUsername()); + dept.setUpdateBy(getUsername()); + sysDeptMapper.insertDept(dept); + deptMap.put(dept.getDeptName(), dept.getDeptId()); + caseAffiliate.setApplicationOrganId(String.valueOf(dept.getDeptId())); + caseAffiliate.setApplicationOrganName(caseApplication.getName()); + + } + + } + + /** + * 组装被申请人信息 + * + * @param caseApplication + * @return + */ + + private CaseAffiliate buildDebtorInfo(CaseApplication caseApplication) { + // 被申请人信息 + CaseAffiliate debtorCaseAffiliate = new CaseAffiliate(); + debtorCaseAffiliate.setCaseAppliId(caseApplication.getId()); + debtorCaseAffiliate.setIdentityType(2); + debtorCaseAffiliate.setName(caseApplication.getDebtorName()); + debtorCaseAffiliate.setIdentityNum(caseApplication.getDebtorIdentityNum()); + debtorCaseAffiliate.setContactTelphone(caseApplication.getDebtorContactTelphone()); + debtorCaseAffiliate.setContactAddress(caseApplication.getDebtorContactAddress()); + debtorCaseAffiliate.setWorkTelphone(caseApplication.getDebtorWorkTelphone()); + debtorCaseAffiliate.setWorkAddress(caseApplication.getDebtorWorkAddress()); + debtorCaseAffiliate.setNameAgent(caseApplication.getDebtorNameAgent()); + debtorCaseAffiliate.setIdentityNumAgent(caseApplication.getDebtorIdentityNumAgent()); + debtorCaseAffiliate.setContactTelphoneAgent(caseApplication.getDebtorContactTelphoneAgent()); + debtorCaseAffiliate.setContactAddressAgent(caseApplication.getDebtorContactAddressAgent()); + debtorCaseAffiliate.setResponSex(caseApplication.getResponSex()); + debtorCaseAffiliate.setResponBirth(caseApplication.getResponBirth()); + debtorCaseAffiliate.setResidenAffili(caseApplication.getResidenAffiliRespon()); + debtorCaseAffiliate.setEmail(caseApplication.getDebtorEmail()); + + return debtorCaseAffiliate; + } + + private void copyCaseApplication(CaseApplication caseApplicationinsertDiffer, CaseApplication caseApplicationNew) { + caseApplicationNew.setArbitratClaims(caseApplicationinsertDiffer.getArbitratClaims()); + caseApplicationNew.setCaseNum(caseApplicationinsertDiffer.getCaseNum()); + caseApplicationNew.setCaseName(caseApplicationinsertDiffer.getCaseName()); + caseApplicationNew.setCaseSubjectAmount(caseApplicationinsertDiffer.getCaseSubjectAmount()); + caseApplicationNew.setLoanStartDate(caseApplicationinsertDiffer.getLoanStartDate()); + caseApplicationNew.setLoanEndDate(caseApplicationinsertDiffer.getLoanEndDate()); + caseApplicationNew.setContractNumber(caseApplicationinsertDiffer.getContractNumber()); + caseApplicationNew.setClaimInterestOwed(caseApplicationinsertDiffer.getClaimInterestOwed()); + caseApplicationNew.setClaimPrinciOwed(caseApplicationinsertDiffer.getClaimPrinciOwed()); + caseApplicationNew.setClaimLiquidDamag(caseApplicationinsertDiffer.getClaimLiquidDamag()); + caseApplicationNew.setFeePayable(caseApplicationinsertDiffer.getFeePayable()); + caseApplicationNew.setRequestRule(caseApplicationinsertDiffer.getRequestRule()); + caseApplicationNew.setProperPreser(caseApplicationinsertDiffer.getProperPreser()); + } + + + /** + * 获取userSign,默认过期时间10小时 + * + * @param userId + * @return + */ + @Override + public String generateUserSign(String userId) { + TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(sdkAppId, sdkSecretKey); + return tlsSigAPIv2.genUserSig(userId, 60 * 60 * 10); + } + + + /** + * 预约会议 + * + * @param reservedConferenceVO + * @return + * @throws Exception + */ + @Transactional + @Override + public AjaxResult reservedConference(ReservedConferenceVO reservedConferenceVO) { + + // 新增预约会议表 + ReservedConference conference = new ReservedConference(reservedConferenceVO.getCaseId(), SecurityUtils.getUserId(), reservedConferenceVO.getRoomId(), + reservedConferenceVO.getScheduleStartTime(), reservedConferenceVO.getScheduleEndTime()); + + reservedConferenceMapper.insert(conference); + return success("预约会议成功"); + } + + + /** + * 生成房间号 + */ + @Transactional + @Override + public long createRoomId(Long caseId) { + long roomId = generateRoomId(); + // 绑定案件与房间号 + caseApplicationMapper.bindCaseId(caseId, String.valueOf(roomId)); + return roomId; + } + + /** + * 获取房间号 + * + * @return + */ + public Long generateRoomId() { + // 查询最大房间号 + Long maxRoomId = caseApplicationMapper.selectMaxRoomId(); + + if (null == maxRoomId || maxRoomId > 4294967294L) { + return 1L; + } else { + return maxRoomId + 1; + } + + } + + /** + * 根据案件id查询已预约的会议 + * + * @param caseId + * @return + */ + @Override + @Transactional + public List reserveConferenceList(Long caseId) { + List reservedConferences = reservedConferenceMapper.selectListByCaseId(caseId); + if (CollectionUtil.isEmpty(reservedConferences)) { + return reservedConferences; + } + Map userIdMap = null; + List userIds = reservedConferences.stream().map(ReservedConference::getUserId).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(userIds)) { + // 根据userids查询用户名 + List userList = sysUserMapper.selectUserListByIds(userIds); + if (CollectionUtil.isNotEmpty(userList)) { + userIdMap = userList.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getUserName)); + } + } + for (ReservedConference reservedConference : reservedConferences) { + if (null != reservedConference.getUserId() && null != userIdMap) { + reservedConference.setUserName(userIdMap.get(reservedConference.getUserId())); + } + Date startTime = reservedConference.getScheduleStartTime(); + if (null == startTime) { + continue; + } + long beforeMinutes = startTime.getTime() - 1000 * 60 * 5; + if (System.currentTimeMillis() < beforeMinutes) { + reservedConference.setIsBeforeFiveMinutes(true); + } else { + reservedConference.setIsBeforeFiveMinutes(false); + } + } + + + return reservedConferences; + } + + /** + * 删除房间号 + * + * @param roomId + * @return + */ + @Override + public AjaxResult deleteRoom(String roomId) { + + return success(reservedConferenceMapper.deleteByRoomId(roomId)); + } + @Transactional + @Override + public AjaxResult uploadCaseZipFile(MultipartFile file, Long templateId) { + return caseZipImportImpl.zipImport( file, templateId); + } + + + + /** + * 根据附件id修改案件id + * @param caseAttach + * @return + */ + @Override + public AjaxResult updateCaseIdByAnnexId(CaseAttach caseAttach) { + caseAttachMapper.updateCaseAttach(caseAttach); + return success(); + } + + +} + + + diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java new file mode 100644 index 0000000..0aa082a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java @@ -0,0 +1,533 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.deepoove.poi.data.PictureRenderData; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.WordUtil; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.IAdjudicationService; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +import com.ruoyi.wisdomarbitrate.utils.CaseLogUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.wisdomarbitrate.service.ICaseArbitrateService; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.*; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +@Service +public class CaseArbitrateServiceImpl implements ICaseArbitrateService { + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private CaseLogRecordMapper caseLogRecordMapper; + @Autowired + private ArbitrateRecordMapper arbitrateRecordMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + @Autowired + private IAdjudicationService adjudicationService; + @Autowired + private RedisCache redisCache; + @Autowired + private ICaseApplicationService caseApplicationService; + + @Override + @Transactional + public AjaxResult examineArbitrateMethod(CaseApplication caseApplication, Integer opinion, Integer arbitratMethodNow) { + //查询案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 == null) { + return AjaxResult.success(); + } + Integer arbitratMethodOriral = caseApplication.getArbitratMethod(); + + String caseNum = caseApplication1.getCaseNum(); + if (opinion == 0) { //拒绝 + if (arbitratMethodOriral == 2) { + caseApplication1.setArbitratMethod(1); // 更改仲裁方式 + //修改案件状态修改开庭时间 + caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + //修改案件状态为待修改开庭时间 +// caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.MODIFY_HEARDATE, ""); + + } else { + caseApplication1.setArbitratMethod(2); + //修改案件状态为待书面审理 + caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_WRIITEN_HEAR); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_WRIITEN_HEAR, ""); + + } + } else if (opinion == 1 ) { + if (arbitratMethodOriral == 2) { + //修改案件状态为待书面审理 + caseApplication1.setArbitratMethod(2); + caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_WRIITEN_HEAR); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_WRIITEN_HEAR, ""); + + } else { + //修改案件状态为待修改开庭时间 + caseApplication1.setArbitratMethod(1); + caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + //修改案件状态为待修改开庭时间 +// caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.MODIFY_HEARDATE, ""); + + } + }else if (opinion == 2) { + if (arbitratMethodNow == 2) { + //修改案件状态为待书面审理 + caseApplication1.setArbitratMethod(2); + caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_WRIITEN_HEAR); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_WRIITEN_HEAR, ""); + + } else { + //修改案件状态为待修改开庭时间 + caseApplication1.setArbitratMethod(1); + caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + //修改案件状态为待修改开庭时间 +// caseApplication1.setCaseStatus(CaseApplicationConstants.MODIFY_HEARDATE); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.MODIFY_HEARDATE, ""); + + } + } + int i = caseApplicationMapper.submitCaseApplication(caseApplication1); + if (i > 0) { + String arbitratMethodStr = caseApplication1.getArbitratMethod() == 1 ? "开庭审理" : "书面审理"; + //发送短信通知 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication1.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); //获取案件关联人信息 + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + request.setTemplateId("1931000"); + request.setPhone(affiliate.getContactTelphone()); + // 这个值,要看你的模板中是否预留了占位符,如果没有则不需要设置 + // 1931000 尊敬的{1}用户,您的{2}仲裁案件,仲裁方式已确定为{3},请知晓,如非本人操作,请忽略本短信。 + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseNum, arbitratMethodStr}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseApplication1.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseNum + "仲裁案件,仲裁方式已确定为" + arbitratMethodStr + ",请知晓,如非本人操作,请忽略本短信。"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean){ + smsSendRecord.setSendStatus(1); + }else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } + + return AjaxResult.success("审核成功"); + } + return AjaxResult.success(); + } + + @Override + @Transactional + public AjaxResult writtenHear(CaseIds caseIds) { + if (caseIds!=null){ + List ids = caseIds.getIds(); + for (Long caseId : ids) { + //查询案件详情 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseId); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + //先判断案件是否已经提交过仲裁结果 + ArbitrateRecord arbitrateRecord = new ArbitrateRecord(); + arbitrateRecord.setCaseAppliId(caseId); + ArbitrateRecord arbitrateRecord1 = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecord); + if (arbitrateRecord1 != null) { + int i = arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord); + if (i > 0) { + //案件日志表里添加数据 + CaseLogRecord caseLogRecord = new CaseLogRecord(); + caseLogRecord.setCaseAppliId(caseApplication1.getId()); + caseLogRecord.setCaseNode(caseApplication1.getCaseStatus()); + caseLogRecord.setCreateBy(getUsername()); + caseLogRecordMapper.insertCaseLogRecord(caseLogRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.GENERATED_ARBITRATION, ""); + + } + } else { + //提交仲裁结果 + int i = arbitrateRecordMapper.insertArbitrateRecord(arbitrateRecord); + if (i > 0) { + //案件日志表里添加数据 + CaseLogRecord caseLogRecord = new CaseLogRecord(); + caseLogRecord.setCaseAppliId(caseApplication1.getId()); + caseLogRecord.setCaseNode(caseApplication1.getCaseStatus()); + caseLogRecord.setCreateBy(getUsername()); + caseLogRecordMapper.insertCaseLogRecord(caseLogRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.GENERATED_ARBITRATION, ""); + } + } + // 生成裁决书 + CaseApplication application = new CaseApplication(); + application.setId(caseId); + adjudicationService.createDocument(application); + //修改案件状态 + caseApplication1.setCaseStatus(CaseApplicationConstants.VERPRIF_ARBITRATION); + int i = caseApplicationMapper.submitCaseApplication(caseApplication1); + + } + return AjaxResult.success("审理成功"); + } + return AjaxResult.error("请检查参数"); + } + + //生成仲裁文书 + private Boolean generateAward(Long id) { + try { + Map datas = new HashMap<>(); + if (id == null) { + return null; + } + //获取案件详细信息 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + //生成编码 + String equipmentNo = getNewEquipmentNo(); + datas.put("num", equipmentNo); + //获取仲裁记录表里的相关信息 + ArbitrateRecord arbitrateRecord = new ArbitrateRecord(); + arbitrateRecord.setCaseAppliId(id); + ArbitrateRecord arbitrateRecord1 = arbitrateRecordMapper.selectArbitrateRecord(arbitrateRecord); + //获取案件关联人信息 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + List nameAgentList = new ArrayList<>(); + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + if (identityType == 1) { //申请人 + datas.put("appName", affiliate.getName()); + datas.put("appAddress", affiliate.getResidenAffili()); + datas.put("appContactAddress", affiliate.getContactAddress()); + datas.put("appLegalPerson", affiliate.getCompLegalPerson()); + datas.put("appLegalPersonTitle", affiliate.getCompLegalperPost()); + datas.put("appAgentName", affiliate.getNameAgent()); + datas.put("appAgentTitle", affiliate.getAppliAgentTitle()); + nameAgentList.add(affiliate.getNameAgent()); + } else if (identityType == 2) { //被申请人 + datas.put("resName", affiliate.getName()); + datas.put("resAddress", affiliate.getResidenAffili()); + String responSex = affiliate.getResponSex(); + if (responSex.equals("0")) { + datas.put("resSex", "男"); + } else if (responSex.equals("1")){ + datas.put("resSex", "女"); + }else { + datas.put("resSex", "未知"); + } + Date responBirth = affiliate.getResponBirth(); + if (responBirth != null) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String responBirthStr = sdf.format(responBirth); + datas.put("resDateOfBirth", responBirthStr); + + } + + datas.put("resContactAddress", affiliate.getContactAddress()); + nameAgentList.add(affiliate.getNameAgent()); + } + } + } + Date createTime = caseApplication1.getCreateTime(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + // 将日期格式化为字符串 + String createTimeStr = sdf.format(createTime); + datas.put("submissionDate", createTimeStr); + Date registerDate = caseApplication1.getRegisterDate(); + String registerDateStr = sdf.format(registerDate); + datas.put("acceptDate", registerDateStr); + //反请求 + Integer adjudicaCounter = caseApplication1.getAdjudicaCounter(); + String counterclaim = "在《2022年版仲裁规则》第十八条第(一)项规定的期限内,被申请人向秘书处提交了" + + "《仲裁反请求申请书》及证据材料。仲裁委依据《2022年版仲裁规则》第十八条的规定受理了该仲裁反请求案申请。" + + "仲裁反请求案件受理后,秘书处向被申请人发送了仲裁反请求通知书及附件,向申请人发送了仲裁反请求通知书及附件、仲裁反请求申请书及附件。"; + if (adjudicaCounter == null) { + datas.put("counterclaim", null); + } else if (adjudicaCounter == 1) { + datas.put("counterclaim", counterclaim); + } else { + datas.put("counterclaim", null); + } + //财产保全 + Integer properPreser = caseApplication1.getProperPreser(); + String preservation = "本案受理后,申请人向仲裁委提交了财产保全申请,仲裁委根据《中华人民共和国仲裁法》" + + "第二十八条之规定,将该申请提交至法院。"; + if (properPreser == null) { + datas.put("preservation", null); + } else if (properPreser == 1) { + datas.put("preservation", preservation); + } else { + datas.put("preservation", null); + } + //管辖权异议 + Integer objectiJuris = caseApplication1.getObjectiJuris(); + String jurisdictionalObjection = "本案受理后,被申请人向仲裁委提交了《XX管辖异议申请书》,认为XXXXXX" + + ",仲裁委经审理,当庭驳回了被申请人的管辖异议申请,并告知被申请人具体的事实和理由将在裁决书中一并列明。"; + if (objectiJuris == null) { + datas.put("jurisdictionalObjection", null); + } else if (objectiJuris == 1) { + datas.put("jurisdictionalObjection", jurisdictionalObjection); + } else { + datas.put("jurisdictionalObjection", null); + } + String arbitratorName = caseApplication1.getArbitratorName(); + datas.put("arbitratorName", arbitratorName); + Integer arbitratMethod = caseApplication1.getArbitratMethod(); + Date hearDate = caseApplication1.getHearDate(); + if (hearDate != null) { + String hearDateStr = sdf.format(hearDate); + //线上开庭时 + if (arbitratMethod == 1) { + String onLine1 = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于"; + String onLine2 = "通过仲裁委智慧仲裁平台开庭审理了本案。"; + datas.put("onLine1", onLine1); + datas.put("hearDate", hearDateStr); + datas.put("onLine2", onLine2); + } else { + //书面仲裁时 + String written1 = "仲裁庭审阅了申请人提交的仲裁申请书、证据材料后,于"; + String written2 = "在仲裁委所在地开庭审理了本案。"; + datas.put("written1", written1); + datas.put("hearDate1", hearDateStr); + datas.put("written2", written2); + } + } + Integer isAbsence = caseApplication1.getIsAbsence(); + if (isAbsence == null) { + datas.put("absent1", null); + datas.put("absent2", null); + datas.put("absent3", null); + datas.put("absent4", null); + datas.put("absent5", null); + datas.put("attend1", null); + datas.put("attend2", null); + datas.put("attend3", null); + datas.put("attend4", null); + datas.put("attend5", null); + datas.put("attend6", null); + datas.put("attend7", null); + datas.put("appAgentName1", null); + datas.put("appAgentName2", null); + datas.put("resAgentName", null); + } else if (isAbsence == 1) { + //缺席审理 + String absent1 = "申请人的特别授权委托代理人"; + String absent2 = "出席了庭审。被申请人经依法送达开庭通知,无正当理由未出席庭审,故仲裁庭依据" + + "《2022年版仲裁规则》第四十条第(二)项的规定,对本案进行了缺席审理。"; + String absent3 = "庭审中,申请人陈述了仲裁请求事项及事实与理由,出示了证据材料并进行了说明," + + "发表了意见,回答了仲裁庭的提问,并作了最后陈述。因被申请人缺席庭审,故仲裁庭无法组织调解。"; + String absent4 = "(二/三)当事人提供的证据材料\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:"; + String absent5 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第四十条第(二)项、第五十一条的规定,缺席裁决如下:"; + datas.put("absent1", absent1); + datas.put("absent2", absent2); + datas.put("absent3", absent3); + datas.put("absent4", absent4); + datas.put("absent5", absent5); + datas.put("appAgentName1", nameAgentList.get(0)); + } else { + //出席审理 + String attend1 = "申请人的特别授权委托代理人"; + String attend2 = "和被申请人本人/的特别授权委托代理人"; + String attend3 = "出席了庭审。"; + String attend4 = "庭审中,申请人陈述了仲裁请求事项及所依据的事实与理由,被申请人进行了答辩;" + + "双方当事人均出示了证据材料并对对方的证据材料进行了质证;申请人出示了证据材料," + + "被申请人对对方的证据材料进行了质证;双方当事人均回答了仲裁庭的提问,进行了辩论," + + "并分别作了最后陈述。双方当事人在仲裁庭的主持下进行了调解,但未能达成调解协议。"; + String attend5 = "(二)被申请人的答辩意见"; + String attend6 = "(二/三)当事人提供的证据材料及对方的质证意见\n" + + "申请人为证明其主张的事实和理由,向仲裁庭提交了如下证据材料:"; + String attend7 = "被申请人对上述材料的质证意见为:"; + datas.put("attend1", attend1); + datas.put("attend2", attend2); + datas.put("attend3", attend3); + datas.put("attend4", attend4); + datas.put("attend5", attend5); + datas.put("attend6", attend6); + datas.put("attend7", attend7); + datas.put("responCrossOpin", caseApplication1.getResponCrossOpin()); + datas.put("appAgentName2", nameAgentList.get(0)); + datas.put("resAgentName", nameAgentList.get(1)); + if (arbitratMethod == 1) { + //被申出席+开庭 + String attend8 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第五十一条的规定,裁决如下:"; + datas.put("attend8", attend8); + } else { + //被申出席+书面 + String attend9 = "综上,仲裁庭依据《上海仲裁委员会仲裁规则》(2022年7月1日起施行的版本)" + + "第五十一条、第五十八条的规定,裁决如下:"; + datas.put("attend9", attend9); + } + } + datas.put("claims", caseApplication1.getArbitratClaims()); + datas.put("request", caseApplication1.getRequestRule()); + CaseApplication caseApplication2 = caseApplicationService.selectCaseApplication(caseApplication); + List caseAttachList1 = caseApplication2.getCaseAttachList(); + if (caseAttachList1 != null && caseAttachList1.size() > 0) { + for (CaseAttach caseAttach : caseAttachList1) { + if (caseAttach.getAnnexType() == 6) { //被申请人证据材料 + String annexName = caseAttach.getAnnexName(); + boolean isImageFile = Pattern.matches(".*\\.(jpg|png|gif|bmp)$", annexName); + if (isImageFile) { + String annexPath = "/home/ruoyi" + caseAttach.getAnnexPath(); + System.out.println("路径是===========" + annexPath); + PictureRenderData pictureRenderData = WordUtil + .rebuildImageContent(100, 100, null, annexPath); + datas.put("resEvidenceMaterial", pictureRenderData); + } + } else if (caseAttach.getAnnexType() == 2) { //申请人证据材料 + String annexName = caseAttach.getAnnexName(); + boolean isImageFile = Pattern.matches(".*\\.(jpg|png|gif|bmp)$", annexName); + if (isImageFile) { + String annexPath = "/home/ruoyi" + caseAttach.getAnnexPath(); + System.out.println("路径是===========" + annexPath); + PictureRenderData pictureRenderData = WordUtil + .rebuildImageContent(100, 100, null, annexPath); + //申请人证据材料 + datas.put("appEvidenceMaterial", pictureRenderData); + } + } + } + } + datas.put("applicaCrossOpin", "被申请人证据不足,无法说明事实"); + datas.put("factDetermi", "被申请人欠款属实"); + datas.put("arbitrateThink", " 被申请人应按约定还款"); + datas.put("rulingFollows", "被申请人依法偿还申请人欠款"); + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + datas.put("year", year); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String modalFilePath = "/data/arbitrate-document/template/新裁决书模板.docx"; + //String modalFilePath = "D:/develop/新裁决书模板.docx"; + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + //String saveFolderPath = "D:/data/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".docx"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String resultFilePath = saveFolderPath + "/" + fileName; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + Path sourcePath = new File(modalFilePath).toPath(); + Path destinationPath = new File(resultFilePath).toPath(); + Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + String docFilePath = WordUtil.getDocFilePath(datas, modalFilePath, resultFilePath); + File file = new File(docFilePath); + if (file.exists()) { + InputStream in = new FileInputStream(file); + XWPFDocument xwpfDocument = new XWPFDocument(in); + WordUtil.changeText(xwpfDocument); + } + String savePath = docFilePath.substring(0, docFilePath.indexOf("/upload/") + 8); + CaseAttach caseAttach = CaseAttach.builder() + .caseAppliId(id) + .annexName(saveName) + .annexPath(savePath) + .annexType(3) + .build(); + //保存到附件表里,先判断之前有没有,有的话更新,没有的话新增 + CaseAttach caseAttach1 = new CaseAttach(); + caseAttach1.setAnnexType(3); + caseAttach1.setCaseAppliId(id); + List caseAttachList = caseAttachMapper.getCaseAttachByCaseIdAndType(caseAttach1); + if (caseAttachList != null && caseAttachList.size() > 0) { + //之前已经生成过了,更新 + caseAttachMapper.updateCaseAttachBycaseid(caseAttach); + } else { + //之前没生成过,新增 + int i = caseAttachMapper.save(caseAttach); + if (i > 0) { + if (arbitrateRecord1 != null) { + Integer annexId = caseAttach.getAnnexId(); + //将附件id保存到仲裁记录表里面 + arbitrateRecord1.setAnnexId(annexId); + arbitrateRecordMapper.updataArbitrateRecord(arbitrateRecord1); + } + } + } + return Boolean.TRUE; + } catch (IOException e) { + return Boolean.FALSE; + } + } + + public String getNewEquipmentNo() { + Object awardNum = redisCache.getCacheObject("awardNum"); + if (awardNum == null) { + redisCache.setCacheObject("awardNum", "00001"); + String s = redisCache.getCacheObject("awardNum").toString(); + // 字符串数字解析为整数 + int no = Integer.parseInt(s); + // 最新设备编号自增1 + int newEquipment = ++no; + // 将整数格式化为5位数字 + s = String.format("%05d", newEquipment); + redisCache.setCacheObject("awardNum", s); + return s; + } else { + String s = awardNum.toString(); + // 字符串数字解析为整数 + int no = Integer.parseInt(s); + // 最新设备编号自增1 + int newEquipment = ++no; + // 将整数格式化为5位数字 + s = String.format("%05d", newEquipment); + redisCache.setCacheObject("awardNum", s); + return s; + } + } +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java new file mode 100644 index 0000000..b1694c6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java @@ -0,0 +1,511 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.core.domain.AjaxResult; +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.utils.SecurityUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceDirectoryVO; +import com.ruoyi.wisdomarbitrate.utils.CaseLogUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseEvidenceDTO; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseDetailVO; +import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.ICaseEvidenceService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +@Service +public class CaseEvidenceServiceImpl implements ICaseEvidenceService { + @Autowired + private CaseEvidenceMapper caseEvidenceMapper; + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private CaseEvidenceDirectoryMapper caseEvidenceDirectoryMapper; + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + + @Override + @Transactional + public AjaxResult getCaseDetailsById(Long id, String userName) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 != null) { + CaseDetailVO caseDetailVO = new CaseDetailVO(); + BeanUtils.copyProperties(caseApplication1, caseDetailVO); + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(id); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + for (CaseAffiliate affiliate : caseAffiliates) { + if (affiliate.getName() != null) { + String name = affiliate.getName(); + //判断当前登录人和案件关联人姓名是否一致 + if (name.equals(userName)) { //一致,将案件关联人的身份类型赋给当前登录人 + caseDetailVO.setIdentityType(affiliate.getIdentityType()); + } + } + if (affiliate.getIdentityType() == 1) { //申请人 + caseDetailVO.setApplicantName(affiliate.getName()); + } else { + caseDetailVO.setRespondentName(affiliate.getName()); + } + //根据案件id查询案件证据材料 + List evidenceMaterialList = caseAttachMapper.queryAnnexPathByCaseId(id); + if (evidenceMaterialList != null && evidenceMaterialList.size() > 0) { +// for (CaseAttach caseAttach : evidenceMaterialList) { +// //根据附件类型决定返回的路径 +// Integer annexType = caseAttach.getAnnexType(); +// if (annexType != 1){ +// String path = caseAttach.getAnnexName(); +// String prefix = "/profile"; +// int startIndex = path.indexOf(prefix); +// startIndex += prefix.length(); +// String extractedPath = "/uploadPath" + path.substring(startIndex); +// caseAttach.setAnnexPath(extractedPath); +// }else { +// String annexPath = caseAttach.getAnnexPath(); +// String result = annexPath.replace("/home/ruoyi", ""); +// caseAttach.setAnnexPath(result); +// } +// } + + for (CaseAttach caseAttach : evidenceMaterialList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + if(startIndex!=-1) { + startIndex += prefix.length(); + + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + } + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + + } + + } + caseDetailVO.setEvidenceMaterialList(evidenceMaterialList); + } + return AjaxResult.success(caseDetailVO); + } + return null; + } + + @Override + @Transactional + public AjaxResult uploadEvidence(MultipartFile file, Integer annexType, Long id, String userName, Long userId) { + + if (file.isEmpty()) { + return AjaxResult.error("请选择要上传的文件"); + } + try { + String filePath = RuoYiConfig.getUploadPath(); + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + CaseAttach caseAttach = CaseAttach.builder().caseAppliId(id) + .annexName(fileName) + .annexPath(filePath) + .annexType(annexType) + .userId(userId) + .userName(userName) + .build(); + int count = caseAttachMapper.save(caseAttach); + if (count > 0 && annexType != null && annexType != 8) { + if (id != null) { + //修改案件状态 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + caseApplication.setCaseStatus(4); + caseApplicationMapper.submitCaseApplication(caseApplication); + } + } + CaseAttach caseAttachselect = new CaseAttach(); + caseAttachselect.setAnnexId(caseAttach.getAnnexId()); + String annexName = caseAttach.getAnnexName(); + if(StrUtil.isNotEmpty(annexName)) { + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + } + caseAttachselect.setAnnexType(caseAttach.getAnnexType()); + return AjaxResult.success("上传成功", caseAttachselect); + } catch (IOException e) { + e.printStackTrace(); + } + + return AjaxResult.error("上传失败"); + } + + + @Autowired + IdentityAuthenticationMapper identityAuthenticationMapper; + + @Override + public List getCaseListAll(Integer caseStatus) { + // 是否为超级管理员 + int adMinFlag=0; + String identityNum = ""; + IdentityAuthentication authentication = new IdentityAuthentication(); + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 查询该用户的角色 + // 查询登录人身份证号 + SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUserId()); + String username = sysUser.getUserName(); + List roles = sysUser.getRoles(); + if(CollectionUtil.isNotEmpty(roles)){ + for (SysRole role : roles) { + if(role.getRoleName().equals("超级管理员") + ){ + // 超级管理员可查看所有待案件质证的案件 + adMinFlag=1; + break; + } + } + } + if(adMinFlag!=1) { + authentication.setUserName(username); + IdentityAuthentication authentication1 = identityAuthenticationMapper.selectIdentityAuthentication(authentication); + if (authentication1 != null) { + identityNum = authentication1.getIdentityNo(); + } + } + + List caseStatusList = Arrays.asList(caseStatus); + return getCaseEvidenceVOList(identityNum, caseStatusList, 2); + } + + @Override + public AjaxResult evidenceConfirmation(CaseApplication caseApplication) { + caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_TRIAL); + int i = caseApplicationMapper.submitCaseApplication(caseApplication); + if (i > 0) { + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_TRIAL, ""); + + return AjaxResult.success("证据确认成功"); + } + return AjaxResult.error("暂无需要确认的证据"); + } + + @Override + @Transactional + public AjaxResult caseCrossexamination(CaseEvidenceDTO caseEvidenceDTO) { + //查询案件详细信息 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseEvidenceDTO.getCaseId()); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 != null) { + caseApplication1.setAdjudicaCounterReason(caseEvidenceDTO.getAdjudicaCounterReason()); + int caseStatus = caseApplication1.getCaseStatus(); + caseApplication1.setObjectionAddEviden(caseEvidenceDTO.getObjectionAddEviden()); + caseApplication1.setPendingAppointArbotrar(caseEvidenceDTO.getPendingAppointArbotrar()); + caseApplication1.setAdjudicaCounter(caseEvidenceDTO.getAdjudicaCounter()); + caseApplication1.setObjectiJuris(caseEvidenceDTO.getObjectiJuris()); + caseApplication1.setRespondentIsWrittenHear(caseEvidenceDTO.getRespondentIsWrittenHear()); + List arbitrators = caseEvidenceDTO.getArbitrators(); + if (arbitrators != null && arbitrators.size() > 0) { + List ids = arbitrators.stream().map(Arbitrator::getId).collect(Collectors.toList()); + List arbitratorNames = arbitrators.stream().map(Arbitrator::getArbitratorName).collect(Collectors.toList()); + String idstr = ids.stream().map(Object::toString).collect(Collectors.joining(",")); + String arbitratorNamestr = arbitratorNames.stream().map(Object::toString).collect(Collectors.joining(",")); + caseApplication1.setArbitratorId(idstr); + caseApplication1.setArbitratorName(arbitratorNamestr); + } + //修改案件状态 + caseApplication1.setCaseStatus(CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL_SUBMMIT); + + + int i = caseApplicationMapper.submitCaseApplication(caseApplication1); + if (i > 0) { + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CONFIRMDED_PENDING_TRIAL_SUBMMIT, ""); + + return AjaxResult.success("提交成功"); + } + } + return null; + } + + @Transactional + @Override + public AjaxResult batchUpload(MultipartFile[] files, Integer annexType, Long id, String userName, Long userId) { + List successList = new ArrayList<>(); + try { + String filePath = RuoYiConfig.getUploadPath(); + for (MultipartFile file : files) { + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + CaseAttach caseAttach = CaseAttach.builder().caseAppliId(id) + .annexName(fileName) + .annexPath(filePath) + .annexType(annexType) + .userId(userId) + .userName(userName) + .isBatchUpload(1) + .build(); + int count = caseAttachMapper.save(caseAttach); + if (count > 0 && annexType != null && annexType != 8) { + CaseAttach caseAttachselect = new CaseAttach(); + caseAttachselect.setAnnexId(caseAttach.getAnnexId()); + caseAttachselect.setAnnexName(caseAttach.getAnnexName()); + caseAttachselect.setAnnexType(caseAttach.getAnnexType()); + successList.add(caseAttachselect); + } + } + + + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error("上传失败"); + } + // 给秘书发送短信 + // 根据caseid查询该案件的法律顾问,根据案件id查申请表,查到申请机构id,然后拿申请机构id查询在哪个人下并且角色要是法律顾问 + CaseAffiliate caseAffiliate = caseAffiliateMapper.selectCaseAffiliateByIdentityType(id, 1); + if(caseAffiliate!= null && StrUtil.isNotEmpty(caseAffiliate.getApplicationOrganId())){ + List userList= sysUserMapper.selectByDeptIdAndRole(caseAffiliate.getApplicationOrganId(),"法律顾问"); + if(CollectionUtil.isNotEmpty(userList)){ + // 新增短信记录 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + // 1992106 普通短信 修改证据资料通知 尊敬的{1}用户,您的{2}仲裁案件,有新的证据上传,请知晓,如非本人操作,请忽略本短信。 + request.setTemplateId("1992106"); + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + caseApplication = caseApplicationMapper.selectCaseApplication(caseApplication); + for (SysUser user : userList) { + request.setPhone(user.getPhonenumber()); + request.setTemplateParamSet(new String[]{user.getNickName(),caseApplication.getCaseNum()}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseAffiliate.getCaseAppliId()); + + smsSendRecord.setCaseNum(caseApplication.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + user.getNickName() + ",您的"+caseApplication.getCaseNum()+"仲裁案件,有新的证据上传,请知晓,如非本人操作,请忽略本短信。"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + + } + } + + + return AjaxResult.success("上传成功", successList); + + } + + @Override + public AjaxResult fileList(Long caseAppliId, List annexTypeList) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseAppliId); + caseApplication.setAnnexTypeList(annexTypeList); + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication); + if (CollectionUtil.isNotEmpty(caseAttachList)) { + for (CaseAttach caseAttach : caseAttachList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + } + return AjaxResult.success(caseAttachList); + } + return null; + } + + @Override + public int deleteFile(List fileIds) { + return caseAttachMapper.deleteByFileIds(fileIds); + } + + @Override + public List selectEvidenceTreeList(CaseEvidenceDirectory caseEvidenceDirectory) { + List caseEvidenceDirectorys = SpringUtils.getAopProxy(this).selectCaseEvidenceList(caseEvidenceDirectory); + return buildCaseEvidenceTreeSelect(caseEvidenceDirectorys); + } + + @Override + public List selectCaseEvidenceList(CaseEvidenceDirectory caseEvidenceDirectory) { + return caseEvidenceDirectoryMapper.selectList(caseEvidenceDirectory); + } + + @Override + public List buildCaseEvidenceTree(List caseEvidenceDirectorys) { + List returnList = new ArrayList<>(); + List tempList = caseEvidenceDirectorys.stream().map(CaseEvidenceDirectory::getId).collect(Collectors.toList()); + for (CaseEvidenceDirectory caseEvidenceDirectory : caseEvidenceDirectorys) { + String annexName = caseEvidenceDirectory.getAnnexName(); + if (annexName!=null){ + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseEvidenceDirectory.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if(startIndexnew!=-1){ + String annexNamenew = annexName.substring(startIndexnew+1); + caseEvidenceDirectory.setAnnexName(annexNamenew); + } + } + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(caseEvidenceDirectory.getParentId())) { + recursionFn(caseEvidenceDirectorys, caseEvidenceDirectory); + returnList.add(caseEvidenceDirectory); + } + } + if (returnList.isEmpty()) + { + returnList = caseEvidenceDirectorys; + } + return returnList; + } + + @Override + public List buildCaseEvidenceTreeSelect(List caseEvidenceDirectorys) { + List caseEvidenceDirectories = buildCaseEvidenceTree(caseEvidenceDirectorys); + return caseEvidenceDirectories.stream().map(CaseEvidenceDirectoryVO::new).collect(Collectors.toList()); + } + + @Override + @Transactional + public AjaxResult uploadRecord(MultipartFile file, Integer annexType, Long id, String username, Long userId) { + if (file.isEmpty()) { + return AjaxResult.error("请选择要上传的文件"); + } + try { + String filePath = RuoYiConfig.getUploadPath(); + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + CaseAttach caseAttach = CaseAttach.builder().caseAppliId(id) + .annexName(fileName) + .annexPath(filePath) + .annexType(annexType) + .userId(userId) + .userName(username) + .build(); + + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setId(id); + caseApplicationsel.setAnnexType(7); + List caseAttachs = caseAttachMapper.queryCaseAttachList(caseApplicationsel); + if(caseAttachs!=null&&caseAttachs.size()>0){ + caseAttachMapper.deleteCaseAttachByCasedIdAndType(id,7); + int count = caseAttachMapper.save(caseAttach); + }else { + int count = caseAttachMapper.save(caseAttach); + } + + return AjaxResult.success("上传成功"); + } catch (IOException e) { + e.printStackTrace(); + } + + return AjaxResult.error("上传失败"); + + } + + /** + * 递归列表 + */ + private void recursionFn(List list, CaseEvidenceDirectory t) { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (CaseEvidenceDirectory tChild : childList) { + if (hasChild(list, tChild)) { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, CaseEvidenceDirectory t) { + List tlist = new ArrayList<>(); + Iterator it = list.iterator(); + while (it.hasNext()) { + CaseEvidenceDirectory n = it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, CaseEvidenceDirectory t) { + return getChildList(list, t).size() > 0; + } + + private List getCaseEvidenceVOList(String identityNum, List caseStatusList, Integer identityType) { + List caseListByRespondent = caseEvidenceMapper.getCaseListByRespondent(identityNum, caseStatusList, identityType); + // todo 返回房间号和开庭时间 + if (caseListByRespondent != null && caseListByRespondent.size() > 0) { + for (CaseEvidenceVO caseEvidenceVO : caseListByRespondent) { + //根据案件id查询姓名 + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseEvidenceVO.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); + for (CaseAffiliate affiliate : caseAffiliates) { + if (affiliate.getIdentityType() == 1) { //申请人 + caseEvidenceVO.setApplicantName(affiliate.getName()); + } else { + caseEvidenceVO.setRespondentName(affiliate.getName()); + } + } + } + return caseListByRespondent; + } + return null; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseImportValid.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseImportValid.java new file mode 100644 index 0000000..cff4ad5 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseImportValid.java @@ -0,0 +1,328 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.util.IdcardUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.SpringUtil; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * @author wangqiong + * @description excel导入校验 + * @date 2023-12-11 11:45 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CaseImportValid { + private CaseApplication caseApplication; + private Map deptMap; + // 手机号正则 + private static final Pattern TELEPHONE_REGX = Pattern.compile("^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$"); + // 邮箱正则 + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"); + private static SysUserMapper sysUserMapper= SpringUtil.getBean(SysUserMapper.class); + + /** + * 导入校验 + * + * @param caseApplication + * @param + */ + public void importValid(CaseApplication caseApplication, Map deptMap) { + StringBuilder failureMsg = new StringBuilder(); + caseApplication.setErrorMsg(failureMsg); + // 校验基本字段 + validBaseColumn(caseApplication, failureMsg); + // 校验申请人信息 + validApplicationColumn(caseApplication, failureMsg); + // 校验申请人代理信息 + validApplicationAgentColumn(caseApplication, failureMsg, deptMap); + // 校验被申请人信息 + validDebtorApplicationColumn(caseApplication, failureMsg); + // 校验被申请人代理信息 + validDebtorApplicationAgentColumn(caseApplication, failureMsg); + } + + /** + * 校验被申请人代理信息 + * + * @param caseApplication + * @param failureMsg + */ + private void validDebtorApplicationAgentColumn(CaseApplication caseApplication, StringBuilder failureMsg) { + if (StrUtil.isEmpty(caseApplication.getDebtorNameAgent())) { + failureMsg.append("【被申请人主体信息-代理人姓名】字段不能为空;"); + } else if (caseApplication.getDebtorNameAgent().length() > 50) { + failureMsg.append("【被申请人主体信息-代理人姓名】字段超出指定长度,最大长度为50;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorIdentityNumAgent())) { + failureMsg.append("【被申请人主体信息-代理人身份证号】字段不能为空;"); + } else if (!IdcardUtil.isValidCard((caseApplication.getDebtorIdentityNumAgent()))) { + failureMsg.append("【被申请人主体信息-代理人身份证号】不合法;"); + } + String debtorContactTelphoneAgent = caseApplication.getDebtorContactTelphoneAgent(); + if (StrUtil.isEmpty(debtorContactTelphoneAgent)) { + failureMsg.append("【被申请人主体信息-代理人联系电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(debtorContactTelphoneAgent).matches()) { + failureMsg.append("【被申请人主体信息-代理人联系电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorContactAddressAgent())) { + failureMsg.append("【被申请人主体信息-代理人联系地址】字段不能为空;"); + } else if (caseApplication.getDebtorContactAddressAgent().length() > 50) { + failureMsg.append("【被申请人主体信息-代理人联系地址】字段超出指定长度,最大长度为50;"); + } + } + + /** + * 校验被申请人信息 + * + * @param caseApplication + * @param failureMsg + */ + private void validDebtorApplicationColumn(CaseApplication caseApplication, StringBuilder failureMsg) { + if (StrUtil.isEmpty(caseApplication.getDebtorName())) { + failureMsg.append("【被申请人主体信息-申请人姓名】字段不能为空;"); + } else if (caseApplication.getDebtorName().length() > 50) { + failureMsg.append("【被申请人主体信息-申请人姓名】字段超出指定长度,最大长度为50;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorIdentityNum())) { + failureMsg.append("【被申请人主体信息-身份证号】字段不能为空;"); + } else if (!IdcardUtil.isValidCard(caseApplication.getDebtorIdentityNum())) { + failureMsg.append("【被申请人主体信息-身份证号】不合法;"); + } + String debtorContactTelphone = caseApplication.getDebtorContactTelphone(); + if (StrUtil.isEmpty(debtorContactTelphone)) { + failureMsg.append("【被申请人主体信息-联系电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(debtorContactTelphone).matches()) { + failureMsg.append("【被申请人主体信息-联系电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorContactAddress())) { + failureMsg.append("【被申请人主体信息-联系地址】字段不能为空;"); + } else if (caseApplication.getDebtorContactAddress().length() > 50) { + failureMsg.append("【被申请人主体信息-联系地址】字段超出指定长度,最大长度为50;"); + } + String debtorWorkTelphone = caseApplication.getDebtorWorkTelphone(); + if (StrUtil.isEmpty(debtorWorkTelphone)) { + failureMsg.append("【被申请人主体信息-单位电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(debtorWorkTelphone).matches()) { + failureMsg.append("【被申请人主体信息-单位电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorWorkAddress())) { + failureMsg.append("【被申请人主体信息-单位地址】字段不能为空;"); + } else if (caseApplication.getDebtorWorkAddress().length() > 50) { + failureMsg.append("【被申请人主体信息-单位地址】字段超出指定长度,最大长度为50;"); + } + if (StrUtil.isEmpty(caseApplication.getResponSex())) { + failureMsg.append("【被申请人主体信息-性别】字段不能为空;"); + } else if (caseApplication.getResponSex().length() > 1) { + failureMsg.append("【被申请人主体信息-性别】字段超出指定长度,最大长度为1;"); + } + if (caseApplication.getResponBirth() == null) { + failureMsg.append("【被申请人主体信息-出生年月日】字段不合法;"); + } else if (caseApplication.getResponBirth().after(new Date())) { + failureMsg.append("【被申请人主体信息-出生年月日】字段不合法,不能超过当前日期;"); + } + if (StrUtil.isEmpty(caseApplication.getDebtorEmail())) { + failureMsg.append("【被申请人主体信息-邮箱】字段不能为空;"); + } else if (!EMAIL_PATTERN.matcher(caseApplication.getDebtorEmail()).matches()) { + + failureMsg.append("【被申请人主体信息-邮箱】字段不合法;"); + } + } + + /** + * 校验申请人代理信息 + * + * @param caseApplication + * @param failureMsg + */ + private void validApplicationAgentColumn(CaseApplication caseApplication, StringBuilder failureMsg, Map deptMap) { + if (StrUtil.isEmpty(caseApplication.getNameAgent())) { + failureMsg.append("【申请人主体信息-代理人姓名】字段不能为空;"); + } else if (caseApplication.getNameAgent().length() > 50) { + failureMsg.append("【申请人主体信息-代理人姓名】字段超出指定长度,最大长度为50;"); + } + if (StrUtil.isEmpty(caseApplication.getIdentityNumAgent())) { + failureMsg.append("【申请人主体信息-代理人身份证号】字段不能为空;"); + } else if (!IdcardUtil.isValidCard(caseApplication.getIdentityNumAgent())) { + failureMsg.append("【申请人主体信息-代理人身份证号】不合法;"); + } + validAgentInfo(caseApplication, failureMsg, deptMap); + String contactTelphoneAgent = caseApplication.getContactTelphoneAgent(); + if (StrUtil.isEmpty(contactTelphoneAgent)) { + failureMsg.append("【申请人主体信息-代理人联系电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(contactTelphoneAgent).matches()) { + failureMsg.append("【申请人主体信息-代理人联系电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getContactAddressAgent())) { + failureMsg.append("【申请人主体信息-代理人联系地址】字段不能为空;"); + } else if (caseApplication.getContactAddressAgent().length() > 50) { + failureMsg.append("【申请人主体信息-代理人联系地址】字段超出指定长度,最大长度为50;"); + } + } + + /** + * 校验代理人与组织机构关系 + * + * @param caseApplication + * @param failureMsg + * @return + */ + private void validAgentInfo(CaseApplication caseApplication, StringBuilder failureMsg, Map deptMap) { + // 申请机构与代理人都不为空,校验代理人与组织机构关系(代理人必须在该部门下) + if (StrUtil.isNotEmpty(caseApplication.getName()) && StrUtil.isNotEmpty(caseApplication.getNameAgent())) { + String applicationOrganId = ""; + // 申请机构已经存在 + if (deptMap.containsKey(caseApplication.getName())) { + applicationOrganId = String.valueOf(deptMap.get(caseApplication.getName())); + } + // 根据代理人身份证去用户表查询 + SysUser agentUser = sysUserMapper.selectUserByIdCard(caseApplication.getIdentityNumAgent()); + // 代理人的部门和申请机构不匹配 + if (null != agentUser && null != agentUser.getDeptId() && !String.valueOf(agentUser.getDeptId()).equals(applicationOrganId)) { +// return "该申请代理人已在"+agentUser.getDeptName()+"申请机构下存在,请检查填写信息是否正确"; + if (null != agentUser.getDept() && StrUtil.isNotEmpty(agentUser.getDept().getDeptName())) { + failureMsg.append("该申请代理人已在【").append(agentUser.getDept().getDeptName()).append("】申请机构下存在,请检查填写信息是否正确"); + } else { + failureMsg.append("该申请代理人已存在,与申请机构不匹配,请检查填写信息是否正确"); + } + } + + } + } + + /** + * 校验申请人主题信息 + * + * @param caseApplication + * @param failureMsg + */ + private void validApplicationColumn(CaseApplication caseApplication, StringBuilder failureMsg) { + if (StrUtil.isEmpty(caseApplication.getName())) { + failureMsg.append("【申请人主体信息-申请人(机构)】字段不能为空;"); + } else if (caseApplication.getName().length() > 20) { + failureMsg.append("【申请人主体信息-申请人(机构)】字段超出指定长度,最大长度为20;"); + } + if (StrUtil.isNotEmpty(caseApplication.getIdentityNum()) && caseApplication.getIdentityNum().length() > 50) { + failureMsg.append("【申请人主体信息-代码】字段超出指定长度,最大长度为50;"); + } + String contactTelphone = caseApplication.getContactTelphone(); + if (StrUtil.isEmpty(contactTelphone)) { + failureMsg.append("【申请人主体信息-联系电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(contactTelphone).matches()) { + failureMsg.append("【申请人主体信息-联系电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getContactAddress())) { + failureMsg.append("【申请人主体信息-联系地址】字段不能为空;"); + } else if (caseApplication.getName().length() > 50) { + failureMsg.append("【申请人主体信息-联系地址】字段超出指定长度,最大长度为50;"); + } + String workTelphone = caseApplication.getWorkTelphone(); + if (StrUtil.isEmpty(workTelphone)) { + failureMsg.append("【申请人主体信息-单位电话】字段不能为空;"); + } else if (!TELEPHONE_REGX.matcher(workTelphone).matches()) { + failureMsg.append("【申请人主体信息-单位电话】字段不合法;"); + } + if (StrUtil.isEmpty(caseApplication.getWorkAddress())) { + failureMsg.append("【申请人主体信息-单位地址】字段不能为空;"); + } else if (caseApplication.getWorkAddress().length() > 50) { + failureMsg.append("【申请人主体信息-单位地址】字段超出指定长度,最大长度为50;"); + } + if (StrUtil.isEmpty(caseApplication.getEmail())) { + failureMsg.append("【申请人主体信息-邮箱】字段不能为空;"); + } else if (!EMAIL_PATTERN.matcher(caseApplication.getEmail()).matches()) { + + failureMsg.append("【申请人主体信息-邮箱】字段不合法;"); + } + } + + /** + * 校验基本字段 + * + * @param caseApplication + * @param failureMsg + */ + private void validBaseColumn(CaseApplication caseApplication, StringBuilder failureMsg) { + if (StrUtil.isEmpty(caseApplication.getCaseName())) { + failureMsg.append("【案件名称】字段不能为空;"); + } else if (caseApplication.getCaseName().length() > 50) { + failureMsg.append("【案件名称】字段超出指定长度,最大长度为50;"); + } + BigDecimal caseSubjectAmount = caseApplication.getCaseSubjectAmount(); + if (null == caseSubjectAmount) { + failureMsg.append("【案件标的】字段不合法;"); + } else { + if (caseSubjectAmount.compareTo(new BigDecimal("0")) < 0 || caseSubjectAmount.compareTo(new BigDecimal("99999999.99")) > 0) { + failureMsg.append("【案件标的】字段超出范围,范围为[0,100000000);"); + } + if (caseSubjectAmount.scale() > 2) { + failureMsg.append("【案件标的】字段超出指定精度(10^-2);"); + } + } + if (caseApplication.getLoanStartDate() == null) { + failureMsg.append("【借款开始日期】字段不合法;"); + } + if (caseApplication.getLoanEndDate() == null) { + failureMsg.append("【借款结束日期】字段不合法;"); + } + if (caseApplication.getLoanStartDate() != null && caseApplication.getLoanEndDate() != null && caseApplication.getLoanStartDate().after(caseApplication.getLoanEndDate())) { + failureMsg.append("【借款结束日期】不能早于【借款开始日期】;"); + } + if (StrUtil.isEmpty(caseApplication.getContractNumber())) { + failureMsg.append("【合同编号】字段不能为空;"); + } else if (caseApplication.getContractNumber().length() > 50) { + failureMsg.append("【合同编号】字段超出指定长度,最大长度为50;"); + } + BigDecimal claimPrinciOwed = caseApplication.getClaimPrinciOwed(); + if (null == claimPrinciOwed) { + failureMsg.append("【申请人主张欠本金】字段不合法;"); + } else { + if (claimPrinciOwed.compareTo(new BigDecimal("0")) < 0 || claimPrinciOwed.compareTo(new BigDecimal("99999999.99")) > 0) { + failureMsg.append("【申请人主张欠本金】字段超出范围,范围为[0,100000000);"); + } + if (claimPrinciOwed.scale() > 2) { + failureMsg.append("【申请人主张欠本金】字段超出指定精度(10^-2);"); + } + } + BigDecimal claimInterestOwed = caseApplication.getClaimInterestOwed(); + if (null == claimInterestOwed) { + failureMsg.append("【申请人主张欠利息】字段不合法;"); + } else { + if (claimInterestOwed.compareTo(new BigDecimal("0")) < 0 || claimInterestOwed.compareTo(new BigDecimal("99999999.99")) > 0) { + failureMsg.append("【申请人主张欠利息】字段超出范围,范围为[0,100000000);"); + } + if (claimInterestOwed.scale() > 2) { + failureMsg.append("【申请人主张欠利息】字段超出指定精度(10^-2);"); + } + } + BigDecimal claimLiquidDamag = caseApplication.getClaimLiquidDamag(); + if (null == claimLiquidDamag) { + failureMsg.append("【申请人主张违约金】字段不合法;"); + } else { + if (claimLiquidDamag.compareTo(new BigDecimal("0")) < 0 || claimLiquidDamag.compareTo(new BigDecimal("99999999.99")) > 0) { + failureMsg.append("【申请人主张违约金】字段超出范围,范围为[0,100000000);"); + } + if (claimLiquidDamag.scale() > 2) { + failureMsg.append("【申请人主张违约金】字段超出指定精度(10^-2);"); + } + } + if (StrUtil.isEmpty(caseApplication.getArbitratClaims())) { + failureMsg.append("【申请人仲裁请求及事实和理由】字段不能为空;"); + } else if (caseApplication.getArbitratClaims().length() > 10000) { + failureMsg.append("【申请人仲裁请求及事实和理由】字段超出指定长度,最大长度为10000;"); + } + if (StrUtil.isNotEmpty(caseApplication.getArbitratClaims()) && caseApplication.getArbitratClaims().length() > 10000) { + failureMsg.append("【申请人请求仲裁庭裁决】字段超出指定长度,最大长度为10000;"); + } + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java new file mode 100644 index 0000000..78ff7f5 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java @@ -0,0 +1,51 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.mapper.CaseLogRecordMapper; +import com.ruoyi.wisdomarbitrate.service.ICaseLogRecordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class CaseLogRecordServiceImpl implements ICaseLogRecordService { + @Autowired + private CaseLogRecordMapper caseLogRecordMapper; + + + @Override + public List selectCaseLogRecordList(CaseLogRecord caseLogRecord) { + List records = caseLogRecordMapper.selectCaseLogRecordList(caseLogRecord); + if(CollectionUtil.isNotEmpty(records)){ + records.forEach(record->{ + StringBuilder contentBuilder = new StringBuilder(); + String caseNodeTime=""; + if(record.getCaseNodeTime()!=null){ + caseNodeTime= DateUtil.format(record.getCaseNodeTime(), DatePattern.NORM_DATETIME_FORMATTER); + } + + contentBuilder.append(Optional.ofNullable(record.getCreateNickName()).orElse("")).append("(").append(record.getCreateBy()).append(")").append("于").append(caseNodeTime); + if(StrUtil.isNotEmpty(record.getContent())){ + contentBuilder.append(record.getContent()); + } + if(StrUtil.isNotEmpty(record.getNotes())){ + contentBuilder.append(",").append(record.getNotes()); + } + record.setContent(contentBuilder.toString()); + + }); + } + return records; + } + + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseNumRuleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseNumRuleServiceImpl.java new file mode 100644 index 0000000..754e6dd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseNumRuleServiceImpl.java @@ -0,0 +1,72 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.wisdomarbitrate.domain.CaseNumRule; +import com.ruoyi.wisdomarbitrate.mapper.CaseNumRuleMapper; +import com.ruoyi.wisdomarbitrate.service.ICaseNumRuleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class CaseNumRuleServiceImpl implements ICaseNumRuleService { + @Autowired + private CaseNumRuleMapper caseNumRuleMapper; + + + @Override + @Transactional + public AjaxResult insertCaseNumRule(CaseNumRule caseNumRule) { + int countCaseNumRule = caseNumRuleMapper.countCaseNumRule(caseNumRule); + if (countCaseNumRule>0){ + return AjaxResult.error("不能新增相同案件编号规则"); + } + int i = caseNumRuleMapper.insertCaseNumRule(caseNumRule); + if (i>0){ + return AjaxResult.success("新增成功"); + } + return AjaxResult.error("新增失败"); + + } + + @Override + @Transactional + public AjaxResult updateCaseNumRule(CaseNumRule caseNumRule) { + int countCaseNumRule = caseNumRuleMapper.countCaseNumRule(caseNumRule); + if (countCaseNumRule>0){ + return AjaxResult.error("不能修改相同案件编号规则"); + } + int i = caseNumRuleMapper.updateCaseNumRule(caseNumRule); + if (i > 0) { + return AjaxResult.success("修改成功"); + } + return AjaxResult.error("新增失败"); + + + } + + @Override + @Transactional + public AjaxResult deleteCaseNumRule(CaseNumRule caseNumRule) { + int i = caseNumRuleMapper.deleteCaseNumRule(caseNumRule); + if (i > 0) { + return AjaxResult.success("删除成功"); + } + return AjaxResult.error(); + + + } + + @Override + public List selectCaseNumRule(CaseNumRule caseNumRule) { + return caseNumRuleMapper.selectCaseNumRules(caseNumRule); + + } + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java new file mode 100644 index 0000000..968ef42 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java @@ -0,0 +1,491 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + + +import cn.hutool.core.collection.CollectionUtil; +import com.ruoyi.ElegentPay; +import com.ruoyi.common.constant.CaseApplicationConstants; +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.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.dto.CaseConfirmPayDTO; +import com.ruoyi.wisdomarbitrate.domain.vo.CasePayListVO; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.ICaseApplicationService; +import com.ruoyi.wisdomarbitrate.utils.CaseLogUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.dto.PayRequest; +import com.ruoyi.dto.PayResponse; +import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO; +import com.ruoyi.wisdomarbitrate.service.ICasePaymentService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +@Service +public class CasePaymentServiceImpl implements ICasePaymentService { + private final ElegentPay elegentPay; + private final CaseApplicationMapper caseApplicationMapper; + private final CasePaymentRecordMapper casePaymentRecordMapper; + private final CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + + @Autowired + public CasePaymentServiceImpl(ElegentPay elegentPay + , CaseApplicationMapper caseApplicationMapper + , CasePaymentRecordMapper casePaymentRecordMapper + , CaseAffiliateMapper caseAffiliateMapper + ) { + this.elegentPay = elegentPay; + this.caseApplicationMapper = caseApplicationMapper; + this.casePaymentRecordMapper = casePaymentRecordMapper; + this.caseAffiliateMapper = caseAffiliateMapper; + } + + @Autowired + private ICaseApplicationService caseApplicationService; + + @Override + @Transactional + public AjaxResult casePay(CasePayDTO casePayDTO) { + PayRequest payRequest = new PayRequest(); + payRequest.setBody("案件缴费"); + payRequest.setOrderSn(System.currentTimeMillis() + ""); + payRequest.setTotalFee(casePayDTO.getTotalFee()); + PayResponse response = elegentPay.requestPay(payRequest, casePayDTO.getTradeType(), casePayDTO.getPlatform()); + if (response.getCode_url() == null) { + return AjaxResult.error(); + } + List caseIds = casePayDTO.getCaseIds(); + if (CollectionUtil.isEmpty(caseIds)) { + return AjaxResult.error("请检查参数是否有误"); + } + for (Long caseId : caseIds) { + //缴费记录表里新增数据 + CasePaymentRecord casePaymentRecord = new CasePaymentRecord(); + casePaymentRecord.setCaseId(caseId); + casePaymentRecord.setOrderNumber(payRequest.getOrderSn()); + casePaymentRecord.setPaymentStatus(0); + casePaymentRecord.setCreateTime(new Date()); + int count = casePaymentRecordMapper.saveRecord(casePaymentRecord); + if (count < 1) { + return AjaxResult.error("请检查参数是否有误"); + } + } + return AjaxResult.success(response); + } + + @Transactional + public AjaxResult callback(String orderNumber) { + //查询记录 + List casePaymentRecords = casePaymentRecordMapper.queryRecord(orderNumber); + if(casePaymentRecords!=null&&casePaymentRecords.size()>0){ + for (CasePaymentRecord casePaymentRecord:casePaymentRecords){ + Long caseId = casePaymentRecord.getCaseId(); + //更改记录表里的支付状态和支付时间 + casePaymentRecord.setPaymentStatus(1); + casePaymentRecord.setPaymentTime(new Date()); + casePaymentRecord.setUpdateTime(new Date()); + casePaymentRecordMapper.update(casePaymentRecord); + } + }else { + return AjaxResult.error("未查询到相关记录"); + } + return AjaxResult.success("支付成功"); + } + + @Override + @Transactional + public AjaxResult confirmPayment( List ids) { + for (Long id : ids) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(id); + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_CROSSEXAMI); + caseApplicationMapper.submitCaseApplication(caseApplication); + //发送短信通知 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); //获取案件关联人信息 + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + //查询案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 == null) { + continue; + } + String caseName = "仲裁"; //这里案件名称表里未定义,暂时写死 + String caseNum = caseApplication1.getCaseNum(); + if (identityType == 1) { //申请人 + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("1928003"); //传入申请人模板id + // 这个值,要看你的模板中是否预留了占位符,如果没有则不需要设置 + // 模板id:1928003 普通短信 案件受理通知 + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已成功受理。"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } else { //被申请人 + + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("1952840"); + // 1952840 尊敬的{1}用户,您的{2}案件{3}已成功受理,请点击链接:https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 选择是否应诉。如非本人操作,请忽略本短信 + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已成功受理,请点击链接:https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 选择是否应诉。如非本人操作,请忽略本短信"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } + //更改记录表里的支付状态和支付时间 + CasePaymentRecord casePaymentRecord = new CasePaymentRecord(); + casePaymentRecord.setPaymentStatus(1); + casePaymentRecord.setPaymentTime(new Date()); + casePaymentRecord.setUpdateTime(new Date()); + casePaymentRecordMapper.update(casePaymentRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_CROSSEXAMI, ""); + } + } + + return AjaxResult.success(); + } + + @Transactional + @Override + public AjaxResult confirmPay(CaseConfirmPayDTO payDTO) { + List caseIds = payDTO.getCaseIds(); + if (caseIds == null || caseIds.size() == 0) { + return AjaxResult.error("案件id参数有误"); + } + if (payDTO.getPayType() != null) { + // 修改支付方式 + caseApplicationMapper.updatePayType(payDTO); + } + for (Long caseId : caseIds) { + if (CollectionUtil.isNotEmpty(payDTO.getPayOrderList())) { + for (CaseAttach caseAttach : payDTO.getPayOrderList()) { + caseAttach.setCaseAppliId(caseId); + caseAttachMapper.updateCaseAttach(caseAttach); + } + } + // 修改节点状态 + //根据案件id查询案件信息 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseId); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM); + //修改案件状态 + int i = caseApplicationMapper.submitCaseApplication(caseApplication1); + if (i > 0) { + // 修改支付状态 + CasePaymentRecord paymentRecord = new CasePaymentRecord(); + paymentRecord.setPayType(payDTO.getPayType()); + paymentRecord.setCaseId(caseId); + paymentRecord.setPaymentStatus(1); + casePaymentRecordMapper.saveRecord(paymentRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_PAYMENT_CONFIRM, ""); + } + } + + return AjaxResult.success("确认缴费成功"); + + } + + @Override + public AjaxResult casePayList(CasePayDTO casePayDTO) { + //参数校验 + List caseIds = casePayDTO.getCaseIds(); + if (caseIds == null || caseIds.size() == 0) { + return null; + } + BigDecimal totalCost = new BigDecimal(0); + BigDecimal sum = totalCost; + CasePayListVO listVO = new CasePayListVO(); + listVO.setCaseTotal(caseIds.size()); + List caseApplicationList = new ArrayList<>(); + for (Long caseId : caseIds) { + CaseApplication caseApplication = new CaseApplication(); + CaseApplicationPay caseApplicationPay = new CaseApplicationPay(); + caseApplication.setId(caseId); + CaseApplication caseApplication1 = caseApplicationService.selectCaseApplication(caseApplication); + BigDecimal feePayable = caseApplication1.getFeePayable(); + sum = sum.add(feePayable); + listVO.setTotalFee(sum); + caseApplicationPay.setCaseAppName(caseApplication1.getApplicantName()); + caseApplicationPay.setCaseResName(caseApplication1.getRespondentName()); + caseApplicationPay.setCaseNum(caseApplication1.getCaseNum()); + caseApplicationPay.setCaseStatus(caseApplication1.getCaseStatus()); + caseApplicationPay.setCaseSubjectAmount(caseApplication1.getCaseSubjectAmount()); + caseApplicationPay.setFeePayable(caseApplication1.getFeePayable()); + caseApplicationList.add(caseApplicationPay); + listVO.setCaseApplicationList(caseApplicationList); + } + + if (sum.compareTo(BigDecimal.ZERO) == 0) { + return AjaxResult.error("没有可支付的费用"); + } + return AjaxResult.success(listVO); + } + + @Override + @Transactional + public AjaxResult confirmPayBatch(CasePayDTO payDTO) { + + String batchNumber = payDTO.getBatchNumber(); + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + List caseIds = caseApplications.stream().map(CaseApplication::getId).collect(Collectors.toList()); + if(caseApplications!=null&&caseApplications.size()>0){ + if (payDTO.getPayType() != null) { + payDTO.setCaseIds(caseIds); + // 修改支付方式 + CaseConfirmPayDTO caseConfirmPayDTO = new CaseConfirmPayDTO(); + BeanUtils.copyProperties(payDTO, caseConfirmPayDTO); + caseApplicationMapper.updatePayType(caseConfirmPayDTO); + } + for (Long caseId : caseIds) { + if (CollectionUtil.isNotEmpty(payDTO.getPayOrderList())) { + for (CaseAttach caseAttach : payDTO.getPayOrderList()) { + caseAttach.setCaseAppliId(caseId); + caseAttachMapper.updateCaseAttach(caseAttach); + } + } + + // 修改节点状态 + //根据案件id查询案件信息 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseId); + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM); + //修改案件状态 + int i = caseApplicationMapper.submitCaseApplication(caseApplication1); + if (i > 0) { + // 修改支付状态 + CasePaymentRecord paymentRecord = new CasePaymentRecord(); + paymentRecord.setPayType(payDTO.getPayType()); + paymentRecord.setCaseId(caseId); + paymentRecord.setPaymentStatus(1); + casePaymentRecordMapper.saveRecord(paymentRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.PENDING_PAYMENT_CONFIRM, ""); + } + + } + + }else{ + throw new ServiceException("这个批号没有批量缴费的案件"); + } + + return AjaxResult.success("确认缴费成功"); + } + + @Override + public AjaxResult casePayListBatch(CasePayDTO casePayDTO) { + String batchNumber = casePayDTO.getBatchNumber(); + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); +// caseApplicationsel.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + CasePayListVO listVO = new CasePayListVO(); + BigDecimal sum = new BigDecimal(0); + if(caseApplications!=null&&caseApplications.size()>0){ + for(CaseApplication caseApplication:caseApplications){ + BigDecimal feePayable = caseApplication.getFeePayable(); + sum = sum.add(feePayable); + } + listVO.setTotalFee(sum); + } + if (sum.compareTo(BigDecimal.ZERO) == 0) { + return AjaxResult.error("没有可支付的费用"); + } + return AjaxResult.success(listVO); + } + + @Override + @Transactional + public AjaxResult confirmPaymentBatch(String batchNumber) { + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + + if (caseApplications != null && caseApplications.size() > 0) { + List caseIds = caseApplications.stream().map(CaseApplication::getId).collect(Collectors.toList()); + for (Long caseId : caseIds) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseId); + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_CROSSEXAMI); + caseApplicationMapper.submitCaseApplication(caseApplication); + //发送短信通知 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + CaseAffiliate caseAffiliate = new CaseAffiliate(); + caseAffiliate.setCaseAppliId(caseApplication.getId()); + List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); //获取案件关联人信息 + if (caseAffiliates != null && caseAffiliates.size() > 0) { + for (CaseAffiliate affiliate : caseAffiliates) { + //获取身份类型 + int identityType = affiliate.getIdentityType(); + //查询案件详细信息 + CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplication1 == null) { + continue; + } + String caseName = "仲裁"; //这里案件名称表里未定义,暂时写死 + String caseNum = caseApplication1.getCaseNum(); + if (identityType == 1) { //申请人 + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("1928003"); //传入申请人模板id + // 这个值,要看你的模板中是否预留了占位符,如果没有则不需要设置 + // 模板id:1928003 普通短信 案件受理通知 + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已成功受理。"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } else { //被申请人 + + request.setPhone(affiliate.getContactTelphone()); + request.setTemplateId("1952840"); + // 1952840 尊敬的{1}用户,您的{2}案件{3}已成功受理,请点击链接:https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 选择是否应诉。如非本人操作,请忽略本短信 + String name = affiliate.getName(); + request.setTemplateParamSet(new String[]{name, caseName, caseNum}); + Boolean aBoolean = SmsUtils.sendSms(request); + //保存短信发送记录 + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseNum); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + name + "用户,您的" + caseName + "案件" + caseNum + "已成功受理,请点击链接:https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 选择是否应诉。如非本人操作,请忽略本短信"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + if (aBoolean) { + smsSendRecord.setSendStatus(1); + } else { + smsSendRecord.setSendStatus(0); + } + smsRecordMapper.saveSmsSendRecord(smsSendRecord); + } + } + //更改记录表里的支付状态和支付时间 + CasePaymentRecord casePaymentRecord = new CasePaymentRecord(); + casePaymentRecord.setPaymentStatus(1); + casePaymentRecord.setCaseId(caseId); + casePaymentRecord.setPaymentTime(new Date()); + casePaymentRecord.setUpdateTime(new Date()); + casePaymentRecordMapper.update(casePaymentRecord); + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_CROSSEXAMI, ""); + + + } + + } + }else{ + throw new ServiceException("这个批号没有批量缴费确认的案件"); + } + return AjaxResult.success(); + } + + @Override + @Transactional + public AjaxResult casePayBatch(CasePayDTO casePayDTO) { + PayRequest payRequest = new PayRequest(); + payRequest.setBody("案件缴费"); + payRequest.setOrderSn(System.currentTimeMillis() + ""); + payRequest.setTotalFee(casePayDTO.getTotalFee()); + PayResponse response = elegentPay.requestPay(payRequest, casePayDTO.getTradeType(), casePayDTO.getPlatform()); + if (response.getCode_url() == null) { + return AjaxResult.error(); + } + String batchNumber = casePayDTO.getBatchNumber(); + if(StringUtils.isEmpty(batchNumber) ){ + return AjaxResult.error("请检查参数是否有误"); + } + CaseApplication caseApplicationsel = new CaseApplication(); + caseApplicationsel.setBatchNumber(Integer.parseInt(batchNumber)); + caseApplicationsel.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT); + List caseApplications = caseApplicationMapper.listCaseApplicationByBatchNumber(caseApplicationsel); + if(caseApplications!=null&&caseApplications.size()>0){ + List caseIds = caseApplications.stream().map(CaseApplication::getId).collect(Collectors.toList()); + for (Long caseId : caseIds) { + //缴费记录表里新增数据 + CasePaymentRecord casePaymentRecord = new CasePaymentRecord(); + casePaymentRecord.setCaseId(caseId); + casePaymentRecord.setOrderNumber(payRequest.getOrderSn()); + casePaymentRecord.setPaymentStatus(0); + casePaymentRecord.setCreateTime(new Date()); + int count = casePaymentRecordMapper.saveRecord(casePaymentRecord); + if (count < 1) { + return AjaxResult.error(); + } + } + + } + + return AjaxResult.success(response); + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseZipImportImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseZipImportImpl.java new file mode 100644 index 0000000..b67e8c4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseZipImportImpl.java @@ -0,0 +1,1035 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.constant.Constants; +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.enums.UpdateSubmitStatus; +import com.ruoyi.common.utils.*; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.common.utils.thread.MultipleThreadListParam; +import com.ruoyi.common.utils.thread.MultipleThreadWorkUtil; +import com.ruoyi.common.utils.thread.ThreadPoolUtil; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.*; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.ColumnValue; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.task.CaseZipImportTask; +import com.ruoyi.wisdomarbitrate.utils.CaseLogUtils; +import com.ruoyi.wisdomarbitrate.utils.OCRUtils; +import com.ruoyi.wisdomarbitrate.utils.UnZipFileUtils; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static com.ruoyi.common.core.domain.AjaxResult.error; +import static com.ruoyi.common.core.domain.AjaxResult.success; +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +/** + * @author wangqiong + * @description 案件压缩包导入 + * @date 2023-12-11 11:45 + */ +@Service +public class CaseZipImportImpl { + @Autowired + private CaseApplicationServiceImpl caseApplicationService; + @Autowired + private FatchRuleMapper fatchRuleMapper; + @Autowired + private SysDictDataMapper dictDataMapper; + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private SysDeptMapper sysDeptMapper; + @Autowired + private SysRoleMapper roleMapper; + @Autowired + private SysUserMapper userMapper; + @Autowired + private SysUserRoleMapper userRoleMapper; + @Autowired + private CaseAffiliateLogMapper caseAffiliateLogMapper; + @Autowired + private CaseAttachLogMapper caseAttachLogMapper; + @Autowired + private SmsRecordMapper smsRecordMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private ColumnValueMapper columnValueMapper; + @Autowired + private ColumnValueLogMapper columnValueLogMapper; + @Autowired + private CaseAffiliateMapper caseAffiliateMapper; + @Autowired + private CaseApplicationLogMapper caseApplicationLogMapper; + // 申请人角色id + private long roleId; + private Integer maxCaseNum; + + +@Transactional + public AjaxResult zipImport(MultipartFile file, Long templateId) { + UUID uuid = UUID.randomUUID(); + // todo + String targetPath = "/home/ruoyi/uploadPath/upload/unzipFile/" + uuid + "/"; +// String targetPath = "D:/home/ruoyi/uploadPath/upload/unzipFile/"+uuid+ "/"; + File zipFile = null; + InputStream ins = null; + try { + ins = file.getInputStream(); + //上传的压缩包保存的路径 + // todo + String savePath = "/home/ruoyi/uploadPath/upload/zipFile/"; +// String savePath = "D:/home/ruoyi/uploadPath/upload/zipFile/"; + String saveName = uuid + "_" + file.getOriginalFilename(); + zipFile = new File(savePath + saveName); + inputChangeToFile(ins, zipFile); + } catch (IOException e) { + e.printStackTrace(); + } + //解压缩上传的压缩包 + boolean unzipSuccess = UnZipFileUtils.unZipFile(zipFile, targetPath); + if (!unzipSuccess) { + // 解压失败 + throw new ServiceException("解压失败"); + } + // 查询抓取规则 + // todo 批次需要再上传压缩包时用户填写 + List fatchRuleList = fatchRuleMapper.listByTemplateId(templateId); + if (CollectionUtil.isEmpty(fatchRuleList)) { + throw new ServiceException("未设置抓取规则"); + } + // 在系统表中查询案件内置字段 + SysDictData sysDictData = new SysDictData(); + sysDictData.setDictType("case_built_type"); + List dictDataList = dictDataMapper.selectDictDataList(sysDictData); + // 查询所有的组织机构,组装成map + List deptList = sysDeptMapper.selectDeptList(new SysDept()); + // 所有部门 + Map deptMap = new HashMap<>(); + if (CollectionUtil.isNotEmpty(deptList)) { + deptMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptName, SysDept::getDeptId, (oldV, newV) -> newV)); + + } + // 查询申请人角色id + roleId = roleMapper.selectRoleIdByName("申请人"); + /** + * 用户表已存在的用户 + */ + List existUsers = userMapper.selectUserList(new SysUser()); + Map userMap = new HashMap<>(); + if (CollectionUtil.isNotEmpty(existUsers)) { + userMap = existUsers.stream().collect(Collectors.toMap(SysUser::getPhonenumber, Function.identity(), (n1, n2) -> n2)); + } + //查询出当天的案件编号的最大值 + String currentDay = DateUtils.dateTime(); + String caseNum = "zc" + currentDay; + maxCaseNum = caseApplicationMapper.selectCaseNumLike(caseNum, caseNum.length()); + // 抓取内容 + Map fatchMap = new HashMap<>(); + // 从抓取规则表取字段和字典表取基本字段,字典表的字段名塞到基本表,is_default=1自定义字段塞到columnValue + // 抓取规则,0-内置字段,1-自定义字段 + Map> fatchRuleMap = fatchRuleList.stream().collect(Collectors.groupingBy(FatchRule::getFileName)); + + File directory = new File(targetPath); + if (!directory.exists()) { + throw new ServiceException("文件不存在"); + } + // 找出案件文件夹 + if (!directory.isDirectory() || directory.listFiles() == null) { + throw new ServiceException("未找到文件夹"); + } + Integer maxBatchNumber = caseApplicationMapper.selectBatchNumberLike(); + if (maxBatchNumber == null) { + maxBatchNumber = 1; + + } else { + maxBatchNumber = maxBatchNumber + 1; + + } + File[] files = directory.listFiles(); + CaseZipImportTask caseZipImportTask = null; + try { + caseZipImportTask = new CaseZipImportTask(this, templateId, fatchRuleList, fatchMap, fatchRuleMap, userMap, dictDataList, files , deptMap, SecurityUtils.getLoginUser(),maxBatchNumber); + } catch (Exception e) { + return error("导入失败"); + } + Future> future = ThreadPoolUtil.submit(caseZipImportTask); + try { + if(future.get()!=null){ + return success("导入成功"); + } + } catch (InterruptedException e) { + e.printStackTrace(); + return success("导入失败"); + } catch (ExecutionException e) { + + e.printStackTrace(); + return success("导入失败"); + } + return error("导入失败"); + + + } + @Transactional + public CaseApplication buildCaseInfo(File file, Long templateId, List fatchRuleList, Map> fatchRuleMap, Map fatchMap, Map userMap, List dictDataList, Map deptMap,LoginUser loginUser, Integer maxBatchNumber) { + // fileMap> + Map fileMap = findFile(file, fatchRuleList); + if (fileMap != null && fileMap.size()> 0) { + // 根据抓取规则循环抓取 + for (Map.Entry> entry : fatchRuleMap.entrySet()) { + getFatchContent(fileMap, entry.getKey(), fatchMap, entry.getValue()); + } + + if (fatchMap.size() > 0) { + + // 尊敬的{1},您的代理的案件已接入仲裁系统,复制访问https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 进入小程序进行认证注册。如非本人操作,请忽略本短信 + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1956159"); + + // 新增的案件 + // 组装案件内置字段主表内容 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(IdWorkerUtil.getId()); + caseApplication.setTemplateId(templateId); + Map> defaultRuleMap = fatchRuleList.stream().collect(Collectors.groupingBy(FatchRule::getIsDefault)); + // 自定义字段,组装columnValue表 + List columnValueList = new ArrayList<>(); + if (defaultRuleMap.size() > 0 && defaultRuleMap.containsKey(1)) { + List columnRules = defaultRuleMap.get(1); + columnRules.forEach(columnRule -> { + ColumnValue columnValue = new ColumnValue(); + columnValue.setColumn(columnRule.getColumn()); + columnValue.setName(columnRule.getColumnName()); + columnValue.setValue(fatchMap.get(columnRule.getColumnName())); + columnValue.setIsDefault(1); + columnValue.setCaseId(caseApplication.getId()); + columnValueList.add(columnValue); + }); + caseApplication.setColumnValues(columnValueList); + } + + // 角色用户 + List userRoleList = new ArrayList<>(); + + // 组装机构 + List sysDepts = new ArrayList<>(); + // 案件附件 + List caseAttachs = new ArrayList<>(); + //发送短信列表 + List smsSendRecordList = new ArrayList<>(); + // 短信记录 + List smsRequestList = new ArrayList<>(); + + // 需要新增的用户 + List addUsers = new ArrayList<>(); + caseApplication.setCaseStatus(CaseApplicationConstants.CASE_APPLICATION); + caseApplication.setCaseLogId(IdWorkerUtil.getId()); + caseApplication.setUpdateSubmitStatus(UpdateSubmitStatus.UNCOMMITTED.getCode()); + caseApplication.setCaseAppliId(caseApplication.getId()); + + // 设置批号 + caseApplication.setBatchNumber(maxBatchNumber); + // 设置编号 + String maxCaseNumStr = generateCaseNum(); + caseApplication.setCaseNum(maxCaseNumStr); + caseApplication.setCreateBy(loginUser!=null?loginUser.getUsername():"admin"); + caseApplication.setVersion(1); + // 组装案件内置字段主表内容 + + // 组装内置字段 + buildDefaultColumn(caseApplication, dictDataList, fatchMap, deptMap, sysDepts, userMap, addUsers, userRoleList, smsSendRecordList, smsRequestList); + // 组装附件 + for (Map.Entry entry : fileMap.entrySet()) { + String fileUrl = entry.getValue(); + if (StrUtil.isEmpty(fileUrl)) { + continue; + } + // 上传 + String filePath = RuoYiConfig.getUploadPath(); + + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setCaseAppliId(caseApplication.getId()); + caseAttach.setAnnexPath(filePath); + if (StrUtil.isNotEmpty(fileUrl)) { + String fileName = fileUrl.replace(filePath, "/profile/upload"); + caseAttach.setAnnexName(fileName); + } + // 申请人提供的证据材料 + caseAttach.setAnnexType(2); + caseAttachs.add(caseAttach); + if (fileUrl.contains("仲裁申请书")) { + CaseAttach applyFile = new CaseAttach(); + BeanUtil.copyProperties(caseAttach, applyFile); + applyFile.setAnnexType(1); + caseAttachs.add(applyFile); + } + + } + caseApplication.setCaseAttachList(caseAttachs); + // 案件压缩包导入 + caseApplication.setImportFlag(2); + // 多线程执行 +// List execList = new ArrayList<>(); +// if (CollectionUtil.isNotEmpty(addUsers)) { +// Function, Integer> function = userMapper::batchSave; +// execList.add(new MultipleThreadListParam(function, addUsers)); +// } +// if (CollectionUtil.isNotEmpty(userRoleList)) { +// Function, Integer> function = userRoleMapper::batchUserRole; +// execList.add(new MultipleThreadListParam(function, userRoleList)); +// +// } +// if (CollectionUtil.isNotEmpty(sysDepts)) { +// Function, Integer> function = sysDeptMapper::batchSave; +// execList.add(new MultipleThreadListParam(function, sysDepts)); +// +// } +// if (CollectionUtil.isNotEmpty(caseApplications)) { +// Function, Integer> function = caseApplicationMapper::batchSave; +// execList.add(new MultipleThreadListParam(function, caseApplications)); +// Function, Integer> functionLog = caseApplicationLogMapper::batchSave; +// execList.add(new MultipleThreadListParam(functionLog, caseApplications)); +// +// } +// if (CollectionUtil.isNotEmpty(caseAffiliates)) { +// Function, Integer> function = caseAffiliateMapper::batchCaseAffiliate; +// execList.add(new MultipleThreadListParam(function, caseAffiliates)); +// Function, Integer> functionLog = caseAffiliateLogMapper::batchCaseAffiliate; +// execList.add(new MultipleThreadListParam(functionLog, caseAffiliates)); +// } +// if (CollectionUtil.isNotEmpty(caseAttachs)) { +// Function, Integer> function = caseAttachMapper::batchSave; +// execList.add(new MultipleThreadListParam(function, caseAttachs)); +// Function, Integer> functionLog = caseAttachLogMapper::batchSave; +// execList.add(new MultipleThreadListParam(functionLog, caseAttachs)); +// } +// if (CollectionUtil.isNotEmpty(columnValueList)) { +// Function, Integer> function = columnValueMapper::batchSave; +// execList.add(new MultipleThreadListParam(function, columnValueList)); +// Function, Integer> functionLog = columnValueLogMapper::batchSave; +// execList.add(new MultipleThreadListParam(functionLog, columnValueList)); +// } +// if (CollectionUtil.isNotEmpty(execList)) { +// MultipleThreadWorkUtil.execListFun(execList.toArray(new MultipleThreadListParam[execList.size()])); +// } + // 多线程执行 + ThreadPoolUtil.execute(() -> { + try { + caseApplicationMapper.insertCaseApplication(caseApplication); + caseApplicationLogMapper.insert(caseApplication); + // 多线程执行 + if (CollectionUtil.isNotEmpty(addUsers)) { + userMapper.batchSave(addUsers); + + } + if (CollectionUtil.isNotEmpty(userRoleList)) { + userRoleMapper.batchUserRole(userRoleList); + + } + if (CollectionUtil.isNotEmpty(sysDepts)) { + sysDeptMapper.batchSave(sysDepts); + + } + if (CollectionUtil.isNotEmpty(caseApplication.getCaseAffiliates())) { + caseAffiliateMapper.batchCaseAffiliate(caseApplication.getCaseAffiliates()); + caseAffiliateLogMapper.batchCaseAffiliate(caseApplication.getCaseAffiliates()); + } + if (CollectionUtil.isNotEmpty(caseAttachs)) { + caseAttachMapper.batchSave(caseAttachs); + caseAttachLogMapper.batchSave(caseAttachs); + + } + if (CollectionUtil.isNotEmpty(columnValueList)) { + columnValueMapper.batchSave(columnValueList); + columnValueLogMapper.batchSave(columnValueList); + } + // 新增日志 + CaseLogUtils.insertCaseLog(caseApplication.getId(), CaseApplicationConstants.CASE_APPLICATION, "",loginUser); + // 发送短信 + if (CollectionUtil.isNotEmpty(smsRequestList)) { + Map sendRecordMap = null; + if (CollectionUtil.isNotEmpty(smsSendRecordList)) { + sendRecordMap = smsSendRecordList.stream().collect(Collectors.toMap(SmsSendRecord::getCaseId, Function.identity())); + for (SmsUtils.SendSmsRequest sendSmsRequest : smsRequestList) { + Boolean aBoolean = SmsUtils.sendSms(request); + if (sendRecordMap != null && sendRecordMap.containsKey(sendSmsRequest.getCaseId())) { + if (aBoolean) { + sendRecordMap.get(sendSmsRequest.getCaseId()).setSendStatus(1); + } else { + sendRecordMap.get(sendSmsRequest.getCaseId()).setSendStatus(0); + } + } + } + smsRecordMapper.batchSaveSmsSendRecord(smsSendRecordList); + } + + + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("导入失败,请检查抓取规则是否正确"); + } + + }); + return caseApplication; + } + } + return null; + } + + /** + * 获取抓取内容 + * + * @param andConvertPDF 文件路径map + * @param mapKey 文件名 + * @param map 抓取内容map + * @param fatchRules 抓取规则 + */ + private void getFatchContent(Map andConvertPDF, String mapKey, Map map, List fatchRules) { + String fileURL =null; + for (Map.Entry entry : andConvertPDF.entrySet()) { + if(entry.getKey().contains(mapKey)){ + fileURL=entry.getValue(); + } + } + if (StrUtil.isEmpty(fileURL)) { + return; + } + if (fileURL.endsWith("txt")) { + String readerFile = ReadFileUtils.readerTxtFile(fileURL); + OCRUtils.fatchRuleGetContent(readerFile, fatchRules, map); + } else if (fileURL.endsWith("doc") || fileURL.endsWith("docx")) { + // doc,docx,text识别内容 + String readerFile = null; + try { + readerFile = ReadFileUtils.readWord(fileURL); + } catch (Exception e) { + e.printStackTrace(); + } + OCRUtils.fatchRuleGetContent(readerFile, fatchRules, map); + + } else if (fileURL.endsWith("pdf")) { + //获取文件的页数 + int fileNumPage = getFileNumPage(fileURL); + //文件转成base64 + String base64 = OCRUtils.pdfConvertBase64(fileURL); + if (base64 == null) { + throw new ServiceException("pdf转base64失败"); + // return false; + } + StringBuilder ocrText = new StringBuilder(); // 创建一个StringBuilder对象 + for (int i = 1; i <= fileNumPage; i++) { + //对接腾讯云接口.识别里面的数据 + String text = OCRUtils.pdfIdentifyText(base64, i, fatchRules); + ocrText.append(text); // 拼接当前的字符串 + + + } + // 根据抓取规则截取内容 + OCRUtils.fatchRuleGetContent(ocrText.toString(), fatchRules, map); + } + + + } + + /** + * 查找文件 + * + * @param directory + * @param fatchRuleList + * @return + */ + private Map findFile(File directory, List fatchRuleList) { + Map filePathMap = new HashMap<>(); + if (directory.isFile()) { + String path = ""; + // 如果传入的参数是一个文件 + path = directory.getAbsolutePath(); + filePathMap.put(directory.getName(), path); + + } else if (directory.isDirectory()) { + searchAndConvertPDF(directory, filePathMap); + } else { + return null; + } + return filePathMap; + } + + /** + * 递归查找文件夹 + * + * @param directory + * @param filePathMap + */ + public static void searchAndConvertPDF(File directory, Map filePathMap) { + File[] files = directory.listFiles(); + + if (files != null) { + for (File file : files) { + if (file.getName().contains("zip") || file.getName().contains("rar")) { + continue; + } + if (file.isFile()) { + + filePathMap.put(file.getName(), file.getAbsolutePath()); + } else if (file.isDirectory()) { + // 如果是目录,递归查找 + searchAndConvertPDF(file, filePathMap); + } + } + } + } + + /** + * 获取自动编码 + * + * @return + */ + + public String generateCaseNum() { + // 自动编码格式 zc+yyyyMMdd+001 + String currentDay = DateUtils.dateTime(); + String caseNum = "zc" + currentDay; + + + if (null == maxCaseNum) { + maxCaseNum = 1; + caseNum = caseNum + "001"; + } else { + maxCaseNum = maxCaseNum + 1; + caseNum = caseNum + String.format("%03d", maxCaseNum); + } + return caseNum; + + } + + public void inputChangeToFile(InputStream instream, File file) { + try { + OutputStream outStr = new FileOutputStream(file); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead = instream.read(buffer, 0, 1024)) != -1) { + outStr.write(buffer, 0, bytesRead); + } + outStr.flush(); + outStr.close(); + instream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 查找文件 + * + * @param directory + * @param + * @return + */ + public static Map> findAndConvertPDF(File directory) { + // caseMap> + Map> caseMap = new HashMap<>(); + if (directory.isFile()) { + String path = ""; + // 如果传入的参数是一个文件 + path = directory.getAbsolutePath(); + List fileList = new ArrayList<>(); + fileList.add(directory); + caseMap.put(IdWorkerUtil.getId(), fileList); + + } else if (directory.isDirectory()) { + searchAndConvertPDF(directory, caseMap, 1, new HashMap<>()); + } else { + return null; + } + return caseMap; + } + + public static boolean isPDF(File file) { + String extension = FileUtils.getFileExtension(file); + return extension.equalsIgnoreCase("pdf"); + } + + + /** + * 递归查找文件夹 + * + * @param directory + * @param caseMap> + * @param i 第几层文件夹 + * @param fileMap> + */ + public static void searchAndConvertPDF(File directory, Map> caseMap, int i, Map fileMap) { + File[] files = directory.listFiles(); + // 约定压缩包第二层一个文件夹为一个案件 + if (files != null) { + if (i == 2) { + for (File file : files) { + fileMap.put(file.getAbsolutePath(), IdWorkerUtil.getId()); + } + } + i++; + for (File file : files) { + + if (file.getName().contains("zip") || file.getName().contains("rar")) { + continue; + } + if (file.isFile()) { + for (Map.Entry entry : fileMap.entrySet()) { + // 为同一个案件 + if (!file.getAbsolutePath().contains(entry.getKey())) { + continue; + } + List fileList; + if (caseMap.containsKey(entry.getValue())) { + fileList = caseMap.get(entry.getValue()); + } else { + fileList = new ArrayList<>(); + } + fileList.add(file); + caseMap.put(entry.getValue(), fileList); + + } + + } else if (file.isDirectory()) { + // 如果是目录,递归查找 + searchAndConvertPDF(file, caseMap, i, fileMap); + } + } + } + } + + + private static int getFileNumPage(String pdfUrl) { + File pdfFile = new File(pdfUrl); + int pageCount = 0; + try (PDDocument document = PDDocument.load(pdfFile)) { + pageCount = document.getNumberOfPages(); + } catch (IOException e) { + e.printStackTrace(); + } + return pageCount; + } + + /** + * 获取模板和正文中替换符的内容 + * + * @param a + * @param b + * @return + */ + public static List getReplaceList(String a, String b) { + String aTmpe = filterString(a); + String bTmpe = filterString(b); + String regex = "(\\{[^}}]*})"; + String[] ptTemplate = aTmpe.replaceAll(regex, "@=").split("@="); + String replace = ""; + for (int i = 0; i < ptTemplate.length; i++) { + if (ptTemplate[i] == null || ptTemplate[i].equals(" ")) continue; + if (replace.equals("")) { + replace = bTmpe.replace(ptTemplate[i], "@="); + } else { + replace = replace.replace(ptTemplate[i], "@="); + } + } + List aList = new ArrayList<>(); + String[] split = replace.split("@="); + for (int i = 0; i < split.length; i++) { + if (split[i] == "" || split[i].equals("")) continue; + aList.add(split[i]); + } + return aList; + } + + // 去掉内容中的换行符 + public static String filterString(String str) { + if (str == null || str.equals("")) { + return null; + } + String regEx = "[\\r\\n]"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(str); + return m.replaceAll(" ").trim(); + } + + // 检索时,转换特殊字符 + public static String escapeQueryChars(String s) { + if (StringUtils.isBlank(s)) { + return s; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + // These characters are part of the query syntax and must be escaped + if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' + || c == ':' || c == '^' || c == '[' || c == ']' || c == '\"' + || c == '{' || c == '}' || c == '~' || c == '*' || c == '?' + || c == '|' || c == '&' || c == ';' || c == '/' || c == '.' + || c == '$' || Character.isWhitespace(c)) { + sb.append('\\'); + } + sb.append(c); + } + return sb.toString(); + } + + /** + * 组装内置字段 + * + * @param caseApplication 案件信息 + * @param dictDataList 内置字段 + * @param fatchMap 抓取字段内容 + */ + private void buildDefaultColumn(CaseApplication caseApplication, List dictDataList, Map fatchMap, + Map deptMap, List sysDepts, + Map userMap, List addUsers, List userRoleList, + List smsSendRecords, List smsRequestList) { + // 组装内置字段 + if (CollectionUtil.isEmpty(dictDataList)) { + return; + } + List caseAffiliates = new ArrayList<>(); + // 被申请人 + CaseAffiliate debtorAffiliate = new CaseAffiliate(); + debtorAffiliate.setCaseAppliId(caseApplication.getId()); + debtorAffiliate.setCaseAppliLogId(caseApplication.getCaseLogId()); + // 申请人 + CaseAffiliate affiliate = new CaseAffiliate(); + affiliate.setCaseAppliLogId(caseApplication.getCaseLogId()); + affiliate.setCaseAppliId(caseApplication.getId()); + for (SysDictData dictData : dictDataList) { + if (StrUtil.isNotEmpty(dictData.getDictLabel())) { + if (dictData.getDictLabel().contains("被申请人")) { + // 组装被申请人内置自段 + buildDebtorColumn(dictData, fatchMap, debtorAffiliate, caseApplication.getId()); + } else if (dictData.getDictLabel().contains("申请人") || dictData.getDictLabel().contains("统一社会信用代码") + || dictData.getDictLabel().contains("法定代表人") || dictData.getDictLabel().contains("委托代理人")) { + // 组装申请人内置自段 + buildAffilcateColumn(dictData, fatchMap, affiliate, deptMap, sysDepts, userMap, addUsers, userRoleList, caseApplication, smsSendRecords, smsRequestList); + } else if (dictData.getDictLabel().contains("合同编号")) { + // 合同编号 + String contractNumber = fatchMap.get("合同编号" ); + if (StrUtil.isNotEmpty(contractNumber)) { + // 提取字母和数字 + String regx = "[^a-zA-Z0-9]"; + String replaceAll = contractNumber.replaceAll(regx, ""); + caseApplication.setContractNumber(replaceAll.toUpperCase()); + } + } else if (dictData.getDictLabel().contains("案件标的")) { + String caseSubjectAmount = fatchMap.get(dictData.getDictLabel()); + if(StrUtil.isNotEmpty(caseSubjectAmount)) { + try { + BigDecimal bigDecimal = new BigDecimal(caseSubjectAmount); + caseApplication.setCaseSubjectAmount(bigDecimal); + // todo 案件标的名字要改,字典配置中也要改 + //todo 暂时设置计费比率为0.01 + BigDecimal feeRate = new BigDecimal(0.01); + BigDecimal feePayable = caseApplication.getCaseSubjectAmount().multiply(feeRate).setScale(2, BigDecimal.ROUND_HALF_UP); + caseApplication.setFeePayable(feePayable); + + } catch (Exception e) { + } + } + + } else { + ObjectFieldUtils.setValue(caseApplication, dictData.getDictValue(), fatchMap.get(dictData.getDictLabel() )); + } + + } else { + ObjectFieldUtils.setValue(caseApplication, dictData.getDictValue(), fatchMap.get(dictData.getDictLabel() )); + + } + + } + if (ObjectUtil.isNotEmpty(affiliate)) { + caseAffiliates.add(affiliate); + } + if (ObjectUtil.isNotEmpty(debtorAffiliate)) { + caseAffiliates.add(debtorAffiliate); + } + caseApplication.setCaseAffiliates(caseAffiliates); + + } + + /** + * 组装申请人内置字段 + * + * @param dictData 内置字段 + * @param fatchMap 抓取内容 + * @param affiliate 案件人员 + */ + private void buildAffilcateColumn(SysDictData dictData, Map fatchMap, CaseAffiliate affiliate, + Map deptMap, List sysDepts, + Map userMap, List addUsers, List userRoleList, CaseApplication caseApplication, + List smsSendRecords, List smsRequestList) { + + affiliate.setIdentityType(1); + + // 申请人 + switch (dictData.getDictLabel()) { + case "申请人姓名": + affiliate.setName((fatchMap.get(dictData.getDictLabel()))); + if (StrUtil.isNotEmpty(affiliate.getName())) { + // 组装申请机构 + // 将组织机构id设为申请人名称 + if (deptMap.containsKey(affiliate.getName())) { + affiliate.setApplicationOrganId(String.valueOf(deptMap.get(affiliate.getName()))); + affiliate.setApplicationOrganName(affiliate.getName()); + } else { + // 如果不存在则新增 + SysDept dept = new SysDept(); + dept.setParentId(0L); + dept.setDeptName(affiliate.getName()); + dept.setAncestors("0"); + dept.setOrderNum(1); + dept.setStatus("0"); + dept.setDelFlag("0"); + dept.setCreateBy(getUsername()); + dept.setUpdateBy(getUsername()); + dept.setDeptId(Long.valueOf(IdWorkerUtil.getId())); + sysDepts.add(dept); + deptMap.put(dept.getDeptName(), dept.getDeptId()); + affiliate.setApplicationOrganId(String.valueOf(dept.getDeptId())); + affiliate.setApplicationOrganName(affiliate.getName()); + + } + } + break; + case "统一社会信用代码": + affiliate.setIdentityNum((fatchMap.get(dictData.getDictLabel()))); + break; + case "法定代表人": + affiliate.setCompLegalPerson(fatchMap.get(dictData.getDictLabel())); + break; + case "法定代表人职位": + affiliate.setCompLegalperPost((fatchMap.get(dictData.getDictLabel()))); + break; + case "申请人住所": + affiliate.setResidenAffili((fatchMap.get(dictData.getDictLabel()))); + break; + case "申请人联系地址": + affiliate.setContactAddress(fatchMap.get(dictData.getDictLabel())); + break; + case "委托代理人姓名": + affiliate.setNameAgent(fatchMap.get(dictData.getDictLabel())); + break; + case "委托代理人联系电话": + affiliate.setContactTelphoneAgent(fatchMap.get(dictData.getDictLabel())); + if (StrUtil.isNotEmpty(affiliate.getContactTelphoneAgent())) { + SysUser agentUser = null; + // 用户已存在 + if (userMap.containsKey(affiliate.getContactTelphoneAgent())) { + agentUser = userMap.get(affiliate.getContactTelphoneAgent()); + if (null != agentUser.getDeptId() && String.valueOf(agentUser.getDeptId()).equals(affiliate.getApplicationOrganId())) { + // 同步用户表和案件关联人表的手机号和名称 + affiliate.setContactTelphoneAgent(agentUser.getPhonenumber()); + affiliate.setNameAgent(agentUser.getNickName()); + affiliate.setApplicantAgentUserId(String.valueOf(agentUser.getUserId())); + if (StrUtil.isNotEmpty(agentUser.getIdCard())) { + affiliate.setIdentityNumAgent(agentUser.getIdCard()); + } else { + affiliate.setIdentityNumAgent(affiliate.getIdentityNumAgent()); + } + List longList = new ArrayList<>(); + // 新增角色为申请人 + if (CollectionUtil.isNotEmpty(agentUser.getRoles())) { + longList = agentUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()); + if (!longList.contains(roleId)) { + insertAgentUserRole(agentUser, roleId, userRoleList); + } + } else { + + insertAgentUserRole(agentUser, roleId, userRoleList); + } + + } + } else { + // 用户不存在,新增 + agentUser = new SysUser(); + agentUser.setUserId(Long.valueOf(IdWorkerUtil.getId())); + agentUser.setIdCard(affiliate.getIdentityNumAgent()); + agentUser.setNickName(affiliate.getNameAgent()); + agentUser.setUserName(affiliate.getContactTelphoneAgent()); + agentUser.setPhonenumber(affiliate.getContactTelphoneAgent()); + agentUser.setPassword(SecurityUtils.encryptPassword("abc123456")); + agentUser.setDeptId(Long.valueOf(affiliate.getApplicationOrganId())); + addUsers.add(agentUser); + userMap.put(agentUser.getPhonenumber(), agentUser); + insertAgentUserRole(agentUser, roleId, userRoleList); + + } + if (addUsers != null) { + SysUser finalAgentUser = agentUser; + if (CollectionUtil.isNotEmpty(smsRequestList) && smsRequestList.stream().noneMatch(smsSendRecord -> smsSendRecord.getPhone().equals(finalAgentUser.getPhonenumber()))) { + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1956159"); + request.setPhone(agentUser.getPhonenumber()); + request.setTemplateParamSet(new String[]{agentUser.getNickName()}); + smsRequestList.add(request); + SmsSendRecord smsSendRecord = new SmsSendRecord(); + smsSendRecord.setCaseId(caseApplication.getId()); + smsSendRecord.setCaseNum(caseApplication.getCaseNum()); + smsSendRecord.setPhone(request.getPhone()); + smsSendRecord.setSendTime(new Date()); + String content = "尊敬的" + agentUser.getNickName() + ",您的代理的案件已接入仲裁系统,复制访问https://miniapp-3gpama6l759911ef-1321289474.tcloudbaseapp.com/jump-mp.html 进入小程序进行认证注册。如非本人操作,请忽略本短信"; + smsSendRecord.setSendContent(content); + smsSendRecord.setCreateBy(getUsername()); + smsSendRecords.add(smsSendRecord); + } + + + } + + } + break; + case "委托代理人电子邮件": + affiliate.setAgentEmail(StrUtil.isNotEmpty(fatchMap.get(dictData.getDictLabel())) ? fatchMap.get(dictData.getDictLabel()).replace("\n", "").replaceAll("\\s", "") : null); + break; + default: + ObjectFieldUtils.setValue(caseApplication, dictData.getDictValue(), fatchMap.get(dictData.getDictLabel() )); + break; + } + } + + /** + * 新增角色为申请人 + * + * @param agentUser + * @param roleId + */ + private void insertAgentUserRole(SysUser agentUser, Long roleId, List userRoleList) { + + SysUserRole sysUserRole = new SysUserRole(); + sysUserRole.setUserId(agentUser.getUserId()); + sysUserRole.setRoleId(roleId); + userRoleList.add(sysUserRole); + + } + + /** + * 组装被申请人内置字段 + * + * @param dictData 内置字段 + * @param fatchMap 抓取内容 + * @param debtorAffiliate 被申请人 + */ + private void buildDebtorColumn(SysDictData dictData, Map fatchMap, CaseAffiliate debtorAffiliate, Long caseId) { + + debtorAffiliate.setIdentityType(2); + // 被申请人 + switch (dictData.getDictLabel()) { + case "被申请人姓名": + debtorAffiliate.setName(fatchMap.get(dictData.getDictLabel() )); + break; + case "被申请人身份证号": + String identityNum = fatchMap.get(dictData.getDictLabel() ); + debtorAffiliate.setIdentityNum(fatchMap.get(dictData.getDictLabel() )); + // 出生年月日,从身份证抓取 + if (StrUtil.isNotEmpty(identityNum)) { + identityNum = identityNum.replace("\n", ""); + Map identityNumMap = IdCardUtils.getBirAgeSex(identityNum); + String birthday = identityNumMap.get("birthday"); + if (StrUtil.isNotEmpty(birthday)) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date birthdayDate = null; + try { + birthdayDate = simpleDateFormat.parse(birthday); + } catch (Exception e) { + e.printStackTrace(); + } + debtorAffiliate.setResponBirth(birthdayDate); + } + //从身份证抓取性别 + debtorAffiliate.setResponSex(identityNumMap.get("sexCode")); + } + + break; + case "被申请人住所": + debtorAffiliate.setResidenAffili(fatchMap.get(dictData.getDictLabel() )); + break; + case "被申请人联系电话": + debtorAffiliate.setContactTelphone(fatchMap.get(dictData.getDictLabel() )); + break; + case "被申请人电子邮件": + debtorAffiliate.setEmail(StrUtil.isNotEmpty(fatchMap.get(dictData.getDictLabel() )) ? fatchMap.get(dictData.getDictLabel() ).replace("\n", "").replaceAll("\\s", "") : null); + + break; + default: + break; + } + + } + + /** + * 获取抓取内容 + * + * @param fatchRules 抓取规则 + */ + private void getFatchContentList(File caseFile, Map fatchMap, List fatchRules, Long caseId) { + String fileURL = caseFile.getAbsolutePath(); + if (fileURL.endsWith("txt")) { + String readerFile = ReadFileUtils.readerTxtFile(fileURL); + OCRUtils.fatchRuleGetContent(readerFile, fatchRules, fatchMap, caseId); + } else if (fileURL.endsWith("doc") || fileURL.endsWith("docx")) { + // doc,docx,text识别内容 + String readerFile = null; + try { + readerFile = ReadFileUtils.readWord(fileURL); + } catch (Exception e) { + e.printStackTrace(); + } + OCRUtils.fatchRuleGetContent(readerFile, fatchRules, fatchMap, caseId); + + } else if (fileURL.endsWith("pdf")) { + //获取文件的页数 + int fileNumPage = getFileNumPage(fileURL); + //文件转成base64 + String base64 = OCRUtils.pdfConvertBase64(fileURL); + if (base64 == null) { + throw new ServiceException("pdf转base64失败"); + // return false; + } + StringBuilder ocrText = new StringBuilder(); // 创建一个StringBuilder对象 + for (int i = 1; i <= fileNumPage; i++) { + //对接腾讯云接口.识别里面的数据 + String text = OCRUtils.pdfIdentifyText(base64, i, fatchRules); + ocrText.append(text); // 拼接当前的字符串 + // 根据抓取规则截取内容 + OCRUtils.fatchRuleGetContent(ocrText.toString(), fatchRules, fatchMap, caseId); + + } + } + + + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/DeptIdentifyServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/DeptIdentifyServiceImpl.java new file mode 100644 index 0000000..93b0698 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/DeptIdentifyServiceImpl.java @@ -0,0 +1,652 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.FileTransformation; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SealUtil; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.system.domain.SysUserPost; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.domain.vo.SealListVO; +import com.ruoyi.wisdomarbitrate.domain.vo.TemplateFatchRule; +import com.ruoyi.wisdomarbitrate.mapper.*; +import com.ruoyi.wisdomarbitrate.service.IDeptIdentifyService; +import com.ruoyi.wisdomarbitrate.utils.SignAward; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.wisdomarbitrate.mapper.TemplateFatchRuleMapper; + +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.ruoyi.common.utils.PageUtils.startPage; +import static com.ruoyi.common.utils.SecurityUtils.getUsername; + +@Service +public class DeptIdentifyServiceImpl implements IDeptIdentifyService { + + @Autowired + private DeptIdentifyMapper deptIdentifyMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private SealManageMapper sealManageMapper; + @Autowired + private SysDeptMapper sysDeptMapper; + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private TemplateManageMapper templateManageMapper; + @Autowired + private SysUserPostMapper sysUserPostMapper; + @Autowired + private TemplateFatchRuleMapper templateFatchRuleMapper; + @Autowired + private FatchRuleMapper fatchRuleMapper; + @Autowired + private SysDictDataMapper dictDataMapper; + + + @Override + @Transactional + public List selectDeptIdentify(DeptIdentify deptIdentify) { + return deptIdentifyMapper.selectDeptIdentify(deptIdentify); + } + + @Override + @Transactional + public DeptIdentify selectDeptIndefiUrl(DeptIdentify deptIdentify) throws EsignDemoException { + List deptIdentifysnew = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + DeptIdentify deptIdentifynew = new DeptIdentify(); + if (deptIdentifysnew != null && deptIdentifysnew.size() > 0) { + Gson gson = new Gson(); + DeptIdentify deptIdentifyselect = deptIdentifysnew.get(0); + EsignHttpResponse identifyUrl = SignAward.deptIdentifyUrl(deptIdentifyselect); + JsonObject signUrlJsonObject = gson.fromJson(identifyUrl.getBody(), JsonObject.class); + int code = signUrlJsonObject.get("code").getAsInt(); + if (code == 0) { + JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); + String url = signUrlData.get("authUrl").getAsString(); + //获取本次认证授权流程ID + String authFlowId = signUrlData.get("authFlowId").getAsString(); + deptIdentify.setAuthFlowId(authFlowId); + deptIdentifynew.setIdentifyUrl(url); + deptIdentify.setIdentifyDate(new Date()); + int row = deptIdentifyMapper.updateDeptIdentify(deptIdentify); + } + } + return deptIdentifynew; + } + + @Override + @Transactional + public AjaxResult enableDept(DeptIdentify deptIdentify) { + //参数校验 + if (deptIdentify.getId() == null) { + return AjaxResult.error("请检查参数"); + } + List deptIdentifysnew = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + DeptIdentify deptIdentifyselect = deptIdentifysnew.get(0); + Integer identifyStatus = deptIdentifyselect.getIdentifyStatus(); + if (identifyStatus != 1) { + return AjaxResult.error("这个认证数据未进行认证,不能启用"); + } + deptIdentifyselect.setIsUse(1); + int i = deptIdentifyMapper.updateDeptIdentify(deptIdentifyselect); + if (i > 0) { + //把其他认证数据置为未使用 + DeptIdentify deptIdentify2 = new DeptIdentify(); + deptIdentify2.setIsUse(1); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify2); + for (DeptIdentify deptIdentify3 : deptIdentifies) { + if (deptIdentify3.equals(deptIdentifyselect)) { + continue; + } + deptIdentify3.setIsUse(0); + deptIdentifyMapper.updateDeptIdentify(deptIdentify3); + } + return AjaxResult.success("启用成功"); + } + + + return AjaxResult.error(); + } + + @Override + public AjaxResult sealUpload(Long id, String sealName, MultipartFile file) { + try { + if (file.isEmpty()) { + return AjaxResult.error("请选择要上传的文件"); + } + String filePath = RuoYiConfig.getUploadPath(); + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setId(id); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + for (DeptIdentify identify : deptIdentifies) { + //先判断企业用户是否授予资源管理权限 + String authFlowId = identify.getAuthFlowId(); + if (authFlowId == null) { + return AjaxResult.error("改机构尚未认证,不能上传自定义公章"); + } + EsignHttpResponse response1 = SealUtil.queryAuthProcess(authFlowId); + JSONObject jsonObject1 = JSONObject.parseObject(response1.getBody()); + int authorizedStatus = jsonObject1.getJSONObject("data").getIntValue("authorizedStatus"); + if (authorizedStatus == 1) {//授权流程状态 0流程过期失效 1已授权 2授权中 3审批未通过 + String prefix = "/profile"; + int startIndex = fileName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "home/ruoyi/uploadPath" + fileName.substring(startIndex); + //创建机构图片印章 + //String annexPath = "D:\\develop\\2.jpg"; + + EsignHttpResponse response = SignAward.createOrgByImage(identify, sealName, annexPath); + JSONObject jsonObject = JSONObject.parseObject(response.getBody()); + int code = jsonObject.getIntValue("code"); + if (code == 0) { //业务码,0表示成功,非0表示异常。 + String sealId = jsonObject.getJSONObject("data").getString("sealId"); + //保存到表里 + SealManage sealManage = new SealManage(); + sealManage.setIdentifyId(identify.getId()); + sealManage.setSealName(sealName); + sealManage.setSealId(sealId); + sealManage.setSealStatus(0); //默认为未审核 + sealManage.setIsUse(0); //默认为禁用 + int i = sealManageMapper.insertSealManage(sealManage); + if (i > 0) { + return AjaxResult.success("上传成功"); + } + } + return AjaxResult.error(jsonObject.getString("message")); + } + return AjaxResult.error("企业用户未授予资源管理权限"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (EsignDemoException e) { + e.printStackTrace(); + } + return AjaxResult.error(); + } + + @Override + public AjaxResult receiveNotify(String body) { + /* 请求Body数据格式如下: + { + "action":"SEAL_AUDIT", + "auditStatus":1, + "psnId":"c7e00294**41e7", + "rejectReason":"", + "sealBizType":"COMMON", + "sealId":"af80ba0f-xx-xx-xx-a2da292d7f7f", + "sealName":"赵四的图片印章", + "statusDescription":"通过" + }*/ + //解析body数据 + try { + JSONObject jsonObject = JSONObject.parseObject(body); + String action = jsonObject.getString("action"); + if (action.equals("SEAL_AUDIT")) { //SEAL_AUDIT表示图片印章审核结果通知 + String auditStatus = jsonObject.getString("auditStatus"); + if (auditStatus.equals("1")) { //图片印章审核结果 1通过 ,0驳回 + //审核通过,拿到印章id和机构账号ID + String orgId = jsonObject.getString("orgId"); + String sealId = jsonObject.getString("sealId"); + //查询指定印章详情(机构) + EsignHttpResponse response = SignAward.getOrgSeal(orgId, sealId); + JSONObject jsonObject1 = JSONObject.parseObject(response.getBody()); + if (jsonObject1.getIntValue("code") == 0) { //业务码,0表示成功,非0表示异常。 + int sealStatus = jsonObject1.getJSONObject("data").getIntValue("sealStatus"); + if (sealStatus == 1) { //印章状态 1已启用,2待审核,3审核不通过,4 挂起 + String sealImageDownloadUrl = jsonObject1.getString("sealImageDownloadUrl"); + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".pdf"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String savePath = "/home/ruoyi/uploadPath/upload/"; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + String resultFilePath = saveFolderPath + "/" + fileName; + File resultFilePathFile = new File(resultFilePath); + if (!resultFilePathFile.exists()) { + resultFilePathFile.createNewFile(); + } + boolean downLoadFile = FileTransformation.downLoadFileByUrl(sealImageDownloadUrl, resultFilePath); + if (downLoadFile) { + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setAnnexType(10); //10代表印章图片 + caseAttach.setAnnexPath(savePath); + caseAttach.setAnnexName(saveName); + int i1 = caseAttachMapper.save(caseAttach); + if (i1 > 0) { + //将附件id保存到公章管理表里 + Integer annexId1 = caseAttach.getAnnexId(); + SealManage sealManage = new SealManage(); + sealManage.setSealId(sealId); + List selectSealList = sealManageMapper.selectSealList(sealManage); + if (selectSealList != null && selectSealList.size() > 0) { + SealManage sealManage1 = selectSealList.get(0); + sealManage1.setAnnexId(annexId1); + sealManage1.setSealStatus(1); //启用 + sealManageMapper.updateSealManage(sealManage1); + } + } + } + } + } + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return new AjaxResult(200, "success"); + } + + @Override + public List getSealList(DeptIdentify deptIdentify) { + if (deptIdentify.getId() == null) { + return null; + } + SealManage sealManage = new SealManage(); + sealManage.setIdentifyId(deptIdentify.getId()); + List selectSealList = sealManageMapper.selectSealList(sealManage); + if (selectSealList != null && selectSealList.size() > 0) { + for (SealManage sealManage1 : selectSealList) { + Integer annexId = sealManage1.getAnnexId(); + if (annexId != null) { + //根据附件id查询路径 + CaseAttach caseAttach = caseAttachMapper.queryAnnexById(annexId); + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + sealManage1.setAnnexPath(annexPath); + } else { + sealManage1.setAnnexPath(null); + } + } + } + return selectSealList; + } + + @Override + public AjaxResult updateSealLockStatus(SealManage sealManage) { + sealManageMapper.updateSealManage(sealManage); + return AjaxResult.success(); + } + + @Override + public AjaxResult insertDeptIdentify(DeptIdentify deptIdentify) { + //参数校验 + String identifyName = deptIdentify.getIdentifyName(); + if (identifyName == null) { + AjaxResult.error("请检查参数是否完整"); + } + Integer identifyType = deptIdentify.getIdentifyType(); + if (identifyType == null) { + deptIdentify.setIdentifyType(1); // 设置机构默认为仲裁机构 + } + deptIdentify.setIdentifyStatus(0); //设置认证状态默认为未认证 + deptIdentify.setIsUse(0); //设置机构默认为未启用 + //将机构名称保存到部门表里 + SysDept sysDept = new SysDept(); + sysDept.setDeptName(identifyName); + sysDept.setParentId(0L); + sysDept.setDeptType(1); + int i1 = sysDeptMapper.insertDept(sysDept); + if (i1 > 0) { + /* //将经办人信息存入到用户表里 + Long deptId = sysDept.getDeptId(); + SysUser sysUser = new SysUser(); + sysUser.setDeptId(deptId); + sysUser.setUserName(deptIdentify.getOperUserName()); + sysUser.setNickName(operName); + sysUser.setPhonenumber(operPhone); + SysUser sysUser1 = sysUserMapper.selectUserByUserName(deptIdentify.getOperUserName()); + if (sysUser1== null) { + sysUserMapper.insertUser(sysUser); + } + Long userId = sysUser.getUserId(); + deptIdentify.setDeptId(deptId); + deptIdentify.setUserId(userId); + List sysUserPosts = new ArrayList<>(); + SysUserPost sysUserPost = new SysUserPost(); + sysUserPost.setUserId(userId); + sysUserPost.setPostId(5L); + sysUserPosts.add(sysUserPost); + sysUserPostMapper.batchUserPost(sysUserPosts);*/ + Long deptId = sysDept.getDeptId(); + deptIdentify.setDeptId(deptId); + } + + int i = deptIdentifyMapper.insertDeptIdentify(deptIdentify); + if (i > 0) { + return AjaxResult.success("新增成功"); + } + return AjaxResult.error(); + } + + @Override + public AjaxResult deleteDeptIdentify(Long id) { + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setId(id); + deptIdentify.setDelFlag(2); + int i = deptIdentifyMapper.updateDeptIdentify(deptIdentify); + if (i > 0) { + //删除部门表数据 + sysDeptMapper.deleteDeptById(id); + return AjaxResult.success("删除成功"); + } + return AjaxResult.error(); + } + + @Override + public AjaxResult updateDeptIdentify(DeptIdentify deptIdentify) { + Long id = deptIdentify.getId(); + if (id == null) { + return AjaxResult.error(); + } + DeptIdentify deptIdentifyNew = new DeptIdentify(); + deptIdentifyNew.setId(id); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentifyNew); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + DeptIdentify deptIdentify1 = deptIdentifies.get(0); + if (deptIdentify1.getIdentifyStatus() == 1) { + return AjaxResult.error("已认证的机构不允许修改"); + } + int i = deptIdentifyMapper.updateDeptIdentify(deptIdentify); + if (i > 0) { + //修改部门表数据 + SysDept sysDept = new SysDept(); + sysDept.setDeptId(deptIdentify1.getDeptId()); + sysDept.setDeptName(deptIdentify.getIdentifyName()); + sysDeptMapper.updateDept(sysDept); + return AjaxResult.success("修改成功"); + } + } + + return null; + } + + @Override + public AjaxResult insertTemplate(TemplateManage templateManage, MultipartFile file) { + //参数校验 + if (templateManage.getIdentifyId() == null || file == null || templateManage.getTemName() == null) { + return AjaxResult.error("请检查参数是否完整"); + } + if (templateManage.getTemType() == null) { + templateManage.setTemType(1); //默认模板类型为1(裁决书) + } + try { + String filePath = RuoYiConfig.getUploadPath(); + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + String prefix = "/profile"; + int startIndex = fileName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "uploadPath" + fileName.substring(startIndex); + templateManage.setTemOrigPath(annexPath); + String format = getFileExtension(fileName); + templateManage.setTemFormat(format); + String subFileName = fileName.substring(fileName.lastIndexOf("/") + 1); + templateManage.setFileName(subFileName); + templateManage.setCreateBy(getUsername()); + int i = templateManageMapper.insertTemplateManage(templateManage); + if (i > 0) { + return AjaxResult.success("新增成功"); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public AjaxResult updateTemplate(TemplateManage templateManage, MultipartFile file) { + Long id = templateManage.getId(); + if (id == null) { + return AjaxResult.error(); + } + try { + if (file != null && file.getSize() > 0) { + String filePath = RuoYiConfig.getUploadPath(); + // 上传 + String fileName = FileUploadUtils.upload(filePath, file); + String prefix = "/profile"; + int startIndex = fileName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "uploadPath" + fileName.substring(startIndex); + templateManage.setTemOrigPath(annexPath); + String subFileName = fileName.substring(fileName.lastIndexOf("/") + 1); + templateManage.setFileName(subFileName); + String format = getFileExtension(fileName); + templateManage.setTemFormat(format); + } + templateManage.setUpdateBy(getUsername()); + int i = templateManageMapper.updateTemplateManage(templateManage); + if (i > 0) { + return AjaxResult.success("修改成功"); + } + } catch (IOException e) { + e.printStackTrace(); + } + return AjaxResult.error(); + } + + @Override + public AjaxResult deleteTemplate(Long id) { + TemplateManage templateManage = new TemplateManage(); + templateManage.setId(id); + templateManage.setDelFlag(2); + int i = templateManageMapper.updateTemplateManage(templateManage); + if (i > 0) { + return AjaxResult.success("删除成功"); + } + return AjaxResult.error(); + } + + @Override + public List getTemplateList(DeptIdentify deptIdentify) { + TemplateManage templateManage = new TemplateManage(); + templateManage.setIdentifyId(deptIdentify.getId()); + List templateManages = templateManageMapper.selectTemplateList(templateManage); + if (templateManages != null && templateManages.size() > 0) { + for (TemplateManage manage : templateManages) { + //根据机构id查询机构名称 + Long identifyId = manage.getIdentifyId(); + if (identifyId != null) { + deptIdentify.setId(identifyId); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + manage.setIdentifyName(deptIdentifies.get(0).getIdentifyName()); + } + } + } + } + return templateManages; + } + + @Override + public List selectPostUserByDeptId(DeptIdentify deptIdentify) { + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + deptIdentify = deptIdentifies.get(0); + if (deptIdentify.getDeptId() != null) { + //默认查询经办人的 + Long roleId = 106L; + List sysUserList = sysUserMapper.selectRoleUserByDeptId(deptIdentify.getDeptId(), roleId); + return sysUserList; + } + + } + return null; + } + + @Override + public AjaxResult bindHandler(DeptIdentify deptIdentify) { + if (deptIdentify.getId() == null || deptIdentify.getUserId() == null) { + return AjaxResult.error("请检查参数是否完整"); + } + //根据userid查询用户信息 + SysUser sysUser = sysUserMapper.selectUserById(deptIdentify.getUserId()); + if (sysUser != null) { + deptIdentify.setOperName(sysUser.getNickName()); + deptIdentify.setOperPhone(sysUser.getPhonenumber()); + deptIdentify.setOperUserName(sysUser.getUserName()); + deptIdentify.setUserId(deptIdentify.getUserId()); + //更新 + int i = deptIdentifyMapper.updateDeptIdentify(deptIdentify); + if (i > 0) { + return AjaxResult.success("绑定成功"); + } + } + return null; + } + + @Override + public List getFatchRuleByTemplateid(TemplateManage templateManage) { + + FatchRule fatchRule = new FatchRule(); + fatchRule.setTemplateId(templateManage.getId()); + return fatchRuleMapper.selectFatchRuleList(fatchRule); + + } + + @Override + @Transactional + public AjaxResult saveFatchRules(TemplateManage templateManage) { + TemplateFatchRule templateFatchRule = new TemplateFatchRule(); + templateFatchRule.setTemplateId(templateManage.getId()); + templateFatchRuleMapper.deleteTemplateFatchRule(templateManage.getId()); + + List fatchRules = templateManage.getFatchRules(); + + Map columnmap = fatchRules.stream().collect(Collectors.groupingBy(fatchRule -> fatchRule.getColumn(), Collectors.counting())); + Stream columnStream = columnmap.entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()); + List strlist1 = new ArrayList<>(); + columnStream.forEach(column -> { + strlist1.add(column.toString()); + }); + if(strlist1!=null&&strlist1.size()>0){ + throw new ServiceException("字段' " + String.join(",", strlist1) + " '重复"); + } + + Map columnNamemap = fatchRules.stream().collect(Collectors.groupingBy(fatchRule -> fatchRule.getColumnName(), Collectors.counting())); + Stream columnNameStream = columnNamemap.entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()); + List strlist2 = new ArrayList<>(); + columnNameStream.forEach(column -> { + strlist2.add(column.toString()); + }); + if(strlist2!=null&&strlist2.size()>0){ + throw new ServiceException("字段' " + String.join(",", strlist2) + " '重复"); + } + + if(fatchRules!=null&&fatchRules.size()>0){ + for (FatchRule fatchRule : fatchRules) { + //保存抓取规则数据 + fatchRuleMapper.insertFatchRule(fatchRule); + //保存模板抓取规则关联关系 + Long fatchRuleId = fatchRule.getId(); + if(fatchRuleId!=null){ + templateFatchRule.setFatchRuleId(fatchRuleId); + templateFatchRuleMapper.insertTemplateFatchRule(templateFatchRule); + } + } + return AjaxResult.success("新增成功"); + } + return AjaxResult.error(); + } + + @Override + public List selectColumnandComment() { + List fatchRules = new ArrayList<>(); + FatchRule fatchRuleselect = new FatchRule(); + fatchRuleselect.setDatabaseName("test_smart_arbitration"); + fatchRules = fatchRuleMapper.selectColumnandComment(fatchRuleselect); + return fatchRules; + } + + @Override + public FatchRule selectColumnbycomment(FatchRule fatchRule) { + fatchRule.setDatabaseName("test_smart_arbitration"); + FatchRule fatchRulesel = fatchRuleMapper.selectColumnbycomment(fatchRule); + return fatchRulesel; + } + + /** + * 根据模板id查询模板字段列表 + * @param templateManage + * @return + */ + @Override + public List getTemplateInfoById(TemplateManage templateManage) { + FatchRule fatchRule = new FatchRule(); + fatchRule.setTemplateId(templateManage.getId()); + List fatchRuleList = fatchRuleMapper.selectFatchRuleList(fatchRule); + if(CollectionUtil.isEmpty(fatchRuleList)){ + fatchRuleList=new ArrayList<>(); + } + List columnNameList = fatchRuleList.stream().map(FatchRule::getColumnName).collect(Collectors.toList()); + // 在系统表中查询案件内置字段 + SysDictData sysDictData = new SysDictData(); + sysDictData.setDictType("case_built_type"); + List dictDataList = dictDataMapper.selectDictDataList(sysDictData); + if(CollectionUtil.isNotEmpty(dictDataList)){ + for (SysDictData dictData : dictDataList) { + if(StrUtil.isEmpty(dictData.getDictLabel())||columnNameList.contains(dictData.getDictLabel())){ + continue; + } + FatchRule rule=new FatchRule(); + rule.setColumn(dictData.getDictValue()); + rule.setColumnName(dictData.getDictLabel()); + fatchRuleList.add(rule); + } + } + + return fatchRuleList; + } + + private String getFileExtension(String fileName) { + int lastDotIndex = fileName.lastIndexOf("."); + if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) { + return fileName.substring(lastDotIndex + 1); + } + return ""; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java new file mode 100644 index 0000000..d6e69d7 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java @@ -0,0 +1,233 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.SM2; +import cn.hutool.crypto.symmetric.SymmetricCrypto; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +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.utils.SecurityUtils; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.mapper.IdentityAuthenticationMapper; +import com.ruoyi.wisdomarbitrate.service.IdentityAuthenticationService; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.faceid.v20180301.FaceidClient; +import com.tencentcloudapi.faceid.v20180301.models.GetEidResultRequest; +import com.tencentcloudapi.faceid.v20180301.models.GetEidResultResponse; +import com.tencentcloudapi.faceid.v20180301.models.GetEidTokenRequest; +import com.tencentcloudapi.faceid.v20180301.models.GetEidTokenResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; + +@Service +public class IdentityAuthenticationServiceImpl implements IdentityAuthenticationService { + + @Value("${identityAuthentication.credentialSecretId}") + private String credentialSecretId; + @Value("${identityAuthentication.credentialSecretKey}") + private String credentialSecretKey; + @Value("${identityAuthentication.merchantId}") + private String merchantId; + @Value("${identityAuthentication.privateKeyHexDecodeinfo}") + private String privateKeyHexDecodeinfo; + + + @Autowired + private IdentityAuthenticationMapper identityAuthenticationMapper; + private SysUserMapper sysUserMapper; + + private static final Logger log = LoggerFactory.getLogger(IdentityAuthenticationServiceImpl.class); + + + @Override + public IdentityAuthentication selectIdentityAuthentication(IdentityAuthentication identityAuthentication) { + IdentityAuthentication identityAuthenticationselect = identityAuthenticationMapper.selectIdentityAuthentication(identityAuthentication); + if (identityAuthenticationselect != null) { + identityAuthenticationselect.setCertificationStatusName("已身份认证"); + } else { + IdentityAuthentication identityAuthenticationselectnew = new IdentityAuthentication(); + identityAuthenticationselectnew.setCertificationStatusName("未身份认证"); + identityAuthenticationselectnew.setCertificationStatus(0); + return identityAuthenticationselectnew; + } + return identityAuthenticationselect; + + } + + /** + * 检查是否已经认证的用户 + * + * @param identityAuthentication + * @return + */ + @Override + public String checkIsAuthentication(IdentityAuthentication identityAuthentication) { + IdentityAuthentication identityAuthenticationselect = identityAuthenticationMapper.selectIdentityAuthentication(identityAuthentication); + if (identityAuthenticationselect != null) { + return "1"; + } else { + return "0"; + } + } + + /** + * 获取EIDtoken + * + * @return + */ + @Override + public JSONObject selectIdentityAuthenticaEIDtoken() { + JSONObject objJSON = new JSONObject(); + objJSON.put("EidToken", ""); + try { + Credential cred = new Credential(credentialSecretId, credentialSecretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("faceid.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + FaceidClient client = new FaceidClient(cred, "", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + GetEidTokenRequest req = new GetEidTokenRequest(); + req.setMerchantId(merchantId); + // 返回的resp是一个GetEidTokenResponse的实例,与请求对象对应 + GetEidTokenResponse resp = client.GetEidToken(req); + // 输出json格式的字符串回包 + String respJSON = GetEidTokenResponse.toJsonString(resp); + objJSON = JSON.parseObject(respJSON); + } catch (TencentCloudSDKException e) { + System.out.println(e.toString()); + System.out.println("获取Eidtoken失败"); + } + return objJSON; + } + + /** + * 解密用户信息 + */ + public JSONObject DecodeUserInfo(String deskey, String userInfo) { + JSONObject parse = null; + try { + byte[] desKeyBytes = Base64.decode(deskey); + final SM2 sm2 = new SM2(privateKeyHexDecodeinfo, null, null); + sm2.usePlainEncoding(); + byte[] sm4KeyBytes = sm2.decrypt(desKeyBytes); + SymmetricCrypto sm4 = SmUtil.sm4(sm4KeyBytes); + byte[] plaintext = sm4.decrypt(Base64.decode(userInfo)); + if (plaintext != null && plaintext.length > 0) { + String s = new String(plaintext); + parse = JSON.parseObject(s); + } + } catch (Exception e) { + System.out.println(e.toString()); + } + return parse; + } + + /** + * 小程序人脸核身后查询身份认证结果 + * + * @param ientityAuthentication + * @return + */ + @Override + @Transactional + public AjaxResult selectIdentityAuthenticaRespon(IdentityAuthentication ientityAuthentication) { + String eidToken = ientityAuthentication.getEidToken(); + IdentityAuthentication authentication = new IdentityAuthentication(); + try { + Credential cred = new Credential(credentialSecretId, credentialSecretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("faceid.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + FaceidClient client = new FaceidClient(cred, "", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + GetEidResultRequest req = new GetEidResultRequest(); + req.setEidToken(eidToken); + // 返回的resp是一个GetEidResultResponse的实例,与请求对象对应 + GetEidResultResponse resp = client.GetEidResult(req); + // 输出json格式的字符串回包 + String s = GetEidResultResponse.toJsonString(resp); + JSONObject objJSON = JSON.parseObject(s); + //查看是否核验成功 + JSONObject text = objJSON.getJSONObject("Text"); + if (text != null) { + Integer comparestatus = text.getInteger("Comparestatus"); + if (comparestatus != null && comparestatus == 0) { + JSONObject eidInfo = objJSON.getJSONObject("EidInfo"); + if (eidInfo != null) { + String desKey = eidInfo.getString("DesKey"); + String userInfo = eidInfo.getString("UserInfo"); + //1.解密用户的信息 + JSONObject info = DecodeUserInfo(desKey, userInfo); + if (info != null) { + String idcardno = info.getString("idnum"); + String name = info.getString("name"); + //2.在用户认证表中插入用户认证记录 + // LoginUser loginUser = SecurityUtils.getLoginUser(); + + /** + * 用户名 + * 用户名id + * 姓名 + * 身份证号 + * 认证时间 + * 认证状态0表示成功 + * 请求id + */ + // authentication.setUserName(loginUser.getUsername()); + // authentication.setUserId(loginUser.getUserId()); + + authentication.setIdentityNo(idcardno); + // 查询认证表是否已存在该身份证信息的认证,不存在则新增,存在不处理 + IdentityAuthentication identityAuthentication = identityAuthenticationMapper.selectIdentityAuthentication(authentication); + if(identityAuthentication!=null) { + return AjaxResult.success(identityAuthentication); + } + authentication.setName(name); + authentication.setCertificationTime(new Date()); + authentication.setCertificationStatus(0); + authentication.setCreateBy(name); + // authentication.setCreateBy(loginUser.getUsername()); + try { + identityAuthenticationMapper.insertIdentityAuthentication(authentication); + authentication.setId(authentication.getId()); + } catch (Exception e) { + System.out.println("认证记录新增失败"); + } + } + + } + } + } + return AjaxResult.success(authentication); + } catch (TencentCloudSDKException e) { + System.out.println(e.toString()); + } + return AjaxResult.success(); + } + + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/SendMailRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/SendMailRecordServiceImpl.java new file mode 100644 index 0000000..25d9bed --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/SendMailRecordServiceImpl.java @@ -0,0 +1,26 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.domain.SendMailRecord; +import com.ruoyi.wisdomarbitrate.mapper.SendMailRecordMapper; +import com.ruoyi.wisdomarbitrate.service.ISendMailRecordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SendMailRecordServiceImpl implements ISendMailRecordService { + @Autowired + private SendMailRecordMapper sendMailRecordMapper; + + + @Override + public List selectSendMailRecordList(SendMailRecord sendMailRecord) { + List records = sendMailRecordMapper.selectSendMailRecord(sendMailRecord); + return records; + } + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/TemplateServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/TemplateServiceImpl.java new file mode 100644 index 0000000..cbefff2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/TemplateServiceImpl.java @@ -0,0 +1,54 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.wisdomarbitrate.domain.DeptIdentify; +import com.ruoyi.wisdomarbitrate.domain.TemplateManual; +import com.ruoyi.wisdomarbitrate.mapper.TemplateManualMapper; +import com.ruoyi.wisdomarbitrate.service.ITemplateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +@Service +public class TemplateServiceImpl implements ITemplateService { + @Autowired + private TemplateManualMapper templateManualMapper; + @Override + @Transactional + public AjaxResult insertTemplate(TemplateManual templateManual) { + int i = templateManualMapper.insertTemplateManual(templateManual); + if (i>0){ + return AjaxResult.success("新增成功"); + } + return AjaxResult.error("新增失败"); + } + + @Override + @Transactional + public AjaxResult deleteTemplate(Long id) { + TemplateManual templateManual = new TemplateManual(); + templateManual.setId(id); + templateManual.setDelFlag(2); + int i = templateManualMapper.updateTemplateManual(templateManual); + if (i > 0) { + return AjaxResult.success("删除成功"); + } + return AjaxResult.error(); + } + + @Override + @Transactional + public AjaxResult updateTemplate(TemplateManual templateManual) { + int i = templateManualMapper.updateTemplateManual(templateManual); + if (i > 0) { + return AjaxResult.success("修改成功"); + } + return AjaxResult.error(); + } + + @Override + public List selectTemplate(TemplateManual templateManual) { + return templateManualMapper.selectTemplateManual(templateManual); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/VideoServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/VideoServiceImpl.java new file mode 100644 index 0000000..0aa35dc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/VideoServiceImpl.java @@ -0,0 +1,485 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.AjaxResult; +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.redis.RedisCache; +import com.ruoyi.common.utils.PdfUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.CaseAttach; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; +import com.ruoyi.wisdomarbitrate.mapper.CaseApplicationMapper; +import com.ruoyi.wisdomarbitrate.mapper.CaseAttachMapper; +import com.ruoyi.wisdomarbitrate.mapper.IdentityAuthenticationMapper; +import com.ruoyi.wisdomarbitrate.mapper.WeChatUserMapper; +import com.ruoyi.wisdomarbitrate.service.VideoService; +import com.ruoyi.wisdomarbitrate.service.WeChatUserService; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.trtc.v20190722.TrtcClient; +import com.tencentcloudapi.trtc.v20190722.models.*; +import com.tencentcloudapi.vod.v20180717.VodClient; +import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest; +import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse; +import com.tencentyun.TLSSigAPIv2; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ResourceUtils; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static com.ruoyi.common.core.domain.AjaxResult.success; +import static com.ruoyi.common.utils.file.FileUploadUtils.getAbsoluteFile; +import static com.ruoyi.common.utils.file.FileUploadUtils.getPathFileName; + +/** + * @author wangqiong + * @description 视频录制 + * @date 2023-10-26 11:45 + */ +@Service +@Slf4j +public class VideoServiceImpl implements VideoService { + // 腾讯云即时通信sdkAppId + @Value("${imConfig.sdkAppId}") + private long sdkAppId; + // 腾讯云即时通信密钥 + @Value("${imConfig.sdkSecretKey}") + private String sdkSecretKey; + // 腾讯云个人账户secretId + @Value("${imConfig.secretId}") + private String secretId; + // 腾讯云个人账户密钥 + @Value("${imConfig.secretKey}") + private String secretKey; + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private SysRoleMapper roleMapper; + + /** + * 功能:第三方回调sign校验 + * 参数: + * key:控制台配置的密钥key + * body:腾讯云回调返回的body体 + * sign:腾讯云回调返回的签名值sign + * 返回值: + * Status:OK 表示校验通过,FAIL 表示校验失败,具体原因参考Info + * Info:成功/失败信息 + * @param body + * @param request + * @throws Exception + */ + @Override + public void videoRollBack(String body, HttpServletRequest request) { + String key = "key"; + String sdkAppId = request.getHeader("SdkAppId"); + String sign = request.getHeader("Sign"); + // String resultSign = getResultSign(key,body); + // log.info("resultSign:"+resultSign); + // if (resultSign.equals(sign)) { + JSONObject jsonObject = (JSONObject) JSON.parse(body); + Integer eventType = jsonObject.getInteger("EventType"); // 事件类型 + String eventInfo = jsonObject.getString("EventInfo"); // 事件信息 + JSONObject jsonObject1 = (JSONObject) JSON.parse(eventInfo); + String roomId = jsonObject1.getString("RoomId"); + String taskId = jsonObject1.getString("TaskId"); // 任务ID + String payload = jsonObject1.getString("Payload"); // 根据不同事件类型定义不同 + JSONObject jsonObject2 = (JSONObject) JSON.parse(payload); + String tencentVod = jsonObject2.getString("TencentVod"); // 点播平台信息 + JSONObject jsonObject3 = (JSONObject) JSON.parse(tencentVod); + // 录制视频上传成功 + if (eventType == 311) { + // 点播平台的唯一 ID + String fileId = jsonObject3.getString("FileId"); + // 点播平台的播放地址 + String videoUrl = jsonObject3.getString("VideoUrl"); + // 主辅流标识,main 代表主流(摄像头),aux 代表辅流(屏幕分享),mix 代表混流录制 + String mediaId = jsonObject3.getString("MediaId"); + // 建立相关的数据库用来存储音视频录制地址并和相关的业务ID绑定,用于后续下载 + try { + downloadImage(fileId,videoUrl,roomId); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + } + + @Override + public AjaxResult bindCaseId(Long caseId, String roomId) { + caseApplicationMapper .bindCaseId(caseId,roomId); + return success(); + } + + @Override + public AjaxResult videoList(Long caseId) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseId); + caseApplication.setAnnexType(9); + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication); + if(CollectionUtil.isEmpty(caseAttachList)){ + return success(); + } + for (CaseAttach caseAttach : caseAttachList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + } + return success(caseAttachList); + } + + /** + * 开启腾讯云录制 + * @param roomId + * @return + */ + @Override + public AjaxResult openCloudRecording(long caseId,long roomId) { + try { + String userId="recorder_"+roomId; + + Credential cred = new Credential(secretId, secretKey); + + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("trtc.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile); + + // 实例化一个请求对象,每个接口都会对应一个request对象 + CreateCloudRecordingRequest req = new CreateCloudRecordingRequest(); + req.setSdkAppId(sdkAppId); // SdkAppId – TRTC的[SdkAppId](https://cloud.tencent.com/document/product/647/46351#sdkappid),和录制的房间所对应的SdkAppId相同 + req.setRoomId(String.valueOf(roomId)); // RoomId – TRTC的[RoomId](https://cloud.tencent.com/document/product/647/46351#roomid),录制的TRTC房间所对应的RoomId + req.setRoomIdType(1L); + /** + * 录制机器人用于进入TRTC房间拉流的[UserId](https://cloud.tencent.com/document/product/647/46351#userid), + * 注意这个UserId不能与其他TRTC房间内的主播或者其他录制任务等已经使用的UserId重复,建议可以把房间ID作为userId的标识的一部分, + * 即录制机器人进入房间的userid应保证独立且唯一 + */ + req.setUserId(userId); + + TLSSigAPIv2 api = new TLSSigAPIv2(sdkAppId, sdkSecretKey); + String userSign = api.genUserSig(userId, 60 * 60 * 10); + req.setUserSig(userSign); // 录制机器人用于进入TRTC房间拉流的用户签名,当前 UserId 对应的验证签名,相当于登录密码 + RecordParams recordParams = new RecordParams(); + // 混流录制 + recordParams.setMaxIdleTime(60L*5); // 5分钟内房间里面没有主播,自动停止录制 + recordParams.setStreamType(0L); // 0:录制音频+视频流(默认); 1:仅录制音频流; 2:仅录制视频流 + recordParams.setRecordMode(2L); // 1:单流录制,分别录制房间的订阅UserId的音频和视频,将录制文件上传至云存储; 2:混流录制,将房间内订阅UserId的音视频混录成一个音视频文件,将录制文件上传至云存储; + recordParams.setOutputFormat(0L); // 0:(默认)输出文件为hls格式。1:输出文件格式为hls+mp4。2:输出文件格式为hls+aac + MixLayoutParams mixLayoutParams = new MixLayoutParams(); + // 布局模式: 1:悬浮布局;2:屏幕分享布局;3:九宫格布局(默认);4:自定义布局; + mixLayoutParams.setMixLayoutMode(3L); + req.setMixLayoutParams(mixLayoutParams); + + StorageParams storageParams1 = new StorageParams(); + CloudVod cloudVod = new CloudVod(); + TencentVod tencentVod = new TencentVod(); + tencentVod.setSubAppId(1304001529L); + // 录制的文件永久保存 + tencentVod.setExpireTime(0L); + // 录制文件名拼接前缀 + tencentVod.setUserDefineRecordId(caseId+""); + cloudVod.setTencentVod(tencentVod); // 腾讯云点播相关参数。 + storageParams1.setCloudVod(cloudVod); // 必填】腾讯云云点播的账号信息,目前仅支持存储至腾讯云点播VOD。 + req.setRecordParams(recordParams); // 云端录制控制参数 + req.setStorageParams(storageParams1); // 云端录制文件上传到云存储的参数(目前只支持使用腾讯云点播作为存储) + // 返回的resp是一个CreateCloudRecordingResponse的实例,与请求对象对应 + CreateCloudRecordingResponse resp = client.CreateCloudRecording(req); + + return success((JSONObject) JSON.toJSON(resp)); + } catch (TencentCloudSDKException e) { + return AjaxResult.error(e.toString()); + } + } + + @Override + public AjaxResult closeDeleteCloudRecording(String taskId) { + + try { + if (taskId != null) { + taskId = taskId.replaceAll(" ", "+"); + } + // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 + // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 + // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 + Credential cred = new Credential(secretId, secretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("trtc.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + DeleteCloudRecordingRequest req = new DeleteCloudRecordingRequest(); + req.setSdkAppId(sdkAppId); // SdkAppId – TRTC的SDKAppId,和录制的房间所对应的SDKAppId相同 + req.setTaskId(taskId); // TaskId – 录制任务的唯一Id,在启动录制成功后会返回 + // 返回的resp是一个DeleteCloudRecordingResponse的实例,与请求对象对应 + DeleteCloudRecordingResponse resp = client.DeleteCloudRecording(req); + // 输出json格式的字符串回包 + return success((JSONObject) JSON.toJSON(resp)); + } catch (TencentCloudSDKException e) { + return AjaxResult.error(e.toString()); + } + + } + + @Override + public AjaxResult dissolveRoom( Long roomId) { + Credential cred = new Credential(secretId, secretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("trtc.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile); + DismissRoomRequest req = new DismissRoomRequest(); + req.setSdkAppId(sdkAppId); + req.setRoomId(roomId); + try { + DismissRoomResponse resp = client.DismissRoom(req); + return success((JSONObject) JSON.toJSON(resp)); + } catch (TencentCloudSDKException e) { + return AjaxResult.error("解散房间失败"); + } + + } + + @Override + public AjaxResult secretaryRoleByUserId(Long userId) { + List roles = roleMapper.selectRolePermissionByUserId(userId); + JSONObject jsonObject = new JSONObject(); + boolean isSecretaryRole=false; + if(CollectionUtil.isNotEmpty(roles)){ + for (SysRole role : roles) { + if("法律顾问".equals(role.getRoleName()) || "秘书".equals(role.getRoleName())){ + isSecretaryRole=true; + break; + } + } + } + jsonObject.put("isSecretaryRole",isSecretaryRole); + return success(jsonObject); + } + + /** + * 根据html字符串转pdf并和案件关联 + * @param reservedConferenceVO + * @return + */ + @Override + public AjaxResult htmlToPDF(ReservedConferenceVO reservedConferenceVO) { + String currentFileName = System.currentTimeMillis() + ".pdf"; + String fileName = null; + try { + fileName = getPathFileName(RuoYiConfig.getHtml2PDFPath(), currentFileName); + } catch (IOException e) { + throw new RuntimeException(e); + } + String htmlContent = " 庭审笔录

庭审笔录

" +reservedConferenceVO.getHtmlContent()+""; + // html转pdf并上传到服务器 + boolean convertFlag = PdfUtils.htmlStringConvertToPDF(RuoYiConfig.getHtml2PDFPath() +"/"+ currentFileName, htmlContent); + + // 绑定案件 + if(convertFlag){ + CaseAttach caseAttach = CaseAttach.builder().caseAppliId(reservedConferenceVO.getCaseId()) + .annexName(fileName) + .annexPath(RuoYiConfig.getHtml2PDFPath()) + .annexType(7) + .build(); + caseAttachMapper.save(caseAttach); + return AjaxResult.success(); + }else { + return AjaxResult.error("pdf转换失败"); + } + } + + @Override + public AjaxResult attachListByCaseId(Long caseAppliId, Integer annexType) { + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(caseAppliId); + caseApplication.setAnnexType(annexType); + List caseAttachList = caseAttachMapper.queryCaseAttachList(caseApplication); + if(CollectionUtil.isEmpty(caseAttachList)){ + return success(caseAttachList); + } + + // 附件转换 + if (caseAttachList != null && caseAttachList.size() > 0) { + for (CaseAttach caseAttach : caseAttachList) { + String annexName = caseAttach.getAnnexName(); + String prefix = "/profile"; + int startIndex = annexName.indexOf(prefix); + startIndex += prefix.length(); + String annexPath = "/uploadPath" + annexName.substring(startIndex); + caseAttach.setAnnexPath(annexPath); + int startIndexnew = annexName.lastIndexOf("/"); + if (startIndexnew != -1) { + String annexNamenew = annexName.substring(startIndexnew + 1); + caseAttach.setAnnexName(annexNamenew); + } + + + } + } + return success(caseAttachList); + } + + + /** + * 查询出音视频集合,并下载,在将云点播上面的音视频删除 + * @param fileIds 点播平台唯一ID集合 + * @throws Exception + */ + private void downloadVideo(String [] fileIds) throws Exception { + try{ + //创建文件对象 + Properties properties = new Properties(); + //加载文件获取数据 文件带后缀 + properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream + ("application.properties")); + //根据key来获取value + String secretId = properties.getProperty("secretid"); + String secretKey = properties.getProperty("secretkey"); + // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 + // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 + // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 + Credential cred = new Credential(secretId, secretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("vod.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + VodClient client = new VodClient(cred, "ap-beijing", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + DescribeMediaInfosRequest req = new DescribeMediaInfosRequest(); + req.setFileIds(fileIds); + String[] basicInfos = {"basicInfo"}; + req.setFilters(basicInfos); + // 返回的resp是一个DescribeMediaInfosResponse的实例,与请求对象对应 + DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req); + // 输出json格式的字符串回包 + log.info(DescribeMediaInfosResponse.toJsonString(resp)); + String json = DescribeMediaInfosResponse.toJsonString(resp); + JSONObject jsonObject = (JSONObject) JSON.parse(json); + JSONArray jsonArray = jsonObject.getJSONArray("MediaInfoSet"); // 媒体文件信息列表。 + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject1 = jsonArray.getJSONObject(i); + String fileId = jsonObject1.getString("FileId"); // 点播平台的唯一 ID + String basicInfo = jsonObject1.getString("BasicInfo"); // 基础信息 + JSONObject jsonObject2 = (JSONObject) JSON.parse(basicInfo); + String mediaUrl = jsonObject2.getString("MediaUrl"); // 文件地址 + String downPath = downloadImage(null,null,mediaUrl); // 下载音视频(返回本地下载地址) + // 将未下载的音视频列表查询出来,进行下载到服务器上面,并更新数据库数据 + log.info(downPath); // 本地地址 + } + log.info("下载音视频成功"); + } catch (TencentCloudSDKException e) { + log.info(e.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + log.info("腾讯云测试成功"); + } + + /** + * 将视频下载到本地 + * @param fileUrl 视频路径 + * @return + */ + @Transactional + public String downloadImage(String fileId,String fileUrl,String roomId) throws IOException { + String staticAndMksDir = null; + if (fileUrl != null) { + //下载时文件名称 + String fileName = fileUrl.substring(fileUrl.lastIndexOf("/")); + fileName = fileName.replace("/", ""); + fileName=fileId+fileName; + String absPath = getAbsoluteFile(RuoYiConfig.getVideoUploadPath(), fileName).getAbsolutePath(); + staticAndMksDir = Paths.get(absPath).toFile().toString(); + long downloadFile = HttpUtil.downloadFile(fileUrl, staticAndMksDir); + if(downloadFile>0) { + Long caseId = caseApplicationMapper.selectCaseIdByRoomId(roomId); + String annexName = getPathFileName(RuoYiConfig.getVideoUploadPath(), fileName); + // 存入数据库 + CaseAttach caseAttach = CaseAttach.builder().caseAppliId(caseId) + .annexName(annexName) + .annexPath(RuoYiConfig.getVideoUploadPath()) + .annexType(9) + .build(); + caseAttachMapper.save(caseAttach); + return annexName; + } + } + return ""; + + } + /** + * @param key 回调秘钥 + * @param body 入参 + * @return 签名 Sign 计算公式中 key 为计算签名 Sign 用的加密密钥。 + * @throws Exception + */ + private static String getResultSign(String key, String body) throws Exception { + Mac hmacSha256 = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + hmacSha256.init(secret_key); + return Base64.getEncoder().encodeToString(hmacSha256.doFinal(body.getBytes())); + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/WeChatUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/WeChatUserServiceImpl.java new file mode 100644 index 0000000..1256c3c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/WeChatUserServiceImpl.java @@ -0,0 +1,146 @@ +package com.ruoyi.wisdomarbitrate.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.SmsUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication; +import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO; +import com.ruoyi.wisdomarbitrate.mapper.IdentityAuthenticationMapper; +import com.ruoyi.wisdomarbitrate.service.WeChatUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * @author wangqiong + * @description 微信小程序用户注册登录 + * @date 2023-10-16 11:45 + */ +@Service +@Slf4j +public class WeChatUserServiceImpl implements WeChatUserService { + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private IdentityAuthenticationMapper identityAuthenticationMapper; + + @Override + public AjaxResult sendCode(WeChatUserVO userVO) { + + Random random = new Random(); + String code = ""; + for (int i = 0; i < 6; i++) { + + code += random.nextInt(10); + } + SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest(); + request.setTemplateId("1955047"); + // 1954926 普通短信 短信验证码 验证码:,为了保证您的账户安全,请勿想他人泄露验证码信息。如非本人操作,请忽略本短信。 + request.setPhone(userVO.getPhone()); + request.setTemplateParamSet(new String[]{ code}); + Boolean flag = SmsUtils.sendSms(request); + if(flag){ + setCodeCache(userVO.getPhone(),code); + return AjaxResult.success("短信发送成功"); + }else { + return AjaxResult.warn("短信发送失败"); + } + } + /** + * 设置验证码缓存 + * + * @param key 参数键 + * @param code 验证码 + */ + public static void setCodeCache(String key, String code) + { + SpringUtils.getBean(RedisCache.class).setCacheObject(getVerifyCodeCacheKey(key), code, 5,TimeUnit.MINUTES); + } + + + /** + * 获取字典缓存 + * + * @param key 参数键 + * @return dictDatas 字典数据列表 + */ + public static String getCodeCache(String key) + { + String codeCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getVerifyCodeCacheKey(key)); + if (StringUtils.isNotNull(codeCache)) + { + return codeCache; + } + return null; + } + + private static String getVerifyCodeCacheKey(String key) { + return CacheConstants.WE_CHAT_SMS_VERIFY_CODE_KEY + key; + } + @Transactional + @Override + public AjaxResult registerUser(IdentityAuthentication ientityAuthentication) { + String codeCache = getCodeCache(ientityAuthentication.getPhone()); + // 校验短信验证码 + if(StrUtil.isEmpty(codeCache)){ + return AjaxResult.warn("验证码校验失败"); + }else if(!codeCache.equals(ientityAuthentication.getVerifyCode())){ + return AjaxResult.warn("验证码校验失败"); + } + SysUser sysUserName=sysUserMapper.checkUserNameUnique(ientityAuthentication.getUserName()); + if(sysUserName!=null){ + return AjaxResult.warn("账号已存在"); + } + SysUser checkPhoneUnique = sysUserMapper.checkPhoneUnique(ientityAuthentication.getPhone()); + if(checkPhoneUnique!=null){ + return AjaxResult.warn("手机号已存在"); + } + SysUser checkEmailUnique = sysUserMapper.checkEmailUnique(ientityAuthentication.getEmail()); + if(checkEmailUnique!=null){ + return AjaxResult.warn("邮箱已存在"); + } + + // 根据身份证查询系统用户表中是否存在该用户,存在则同步已认证的信息,不存在则新增 + SysUser sysUser=sysUserMapper.selectUserByIdCard(ientityAuthentication.getIdentityNo()); + if(sysUser!=null){ + sysUser.setIdCard(ientityAuthentication.getIdentityNo()); + sysUser.setNickName(ientityAuthentication.getName()); + sysUser.setUserName(ientityAuthentication.getUserName()); + sysUser.setPhonenumber(ientityAuthentication.getPhone()); + sysUser.setEmail(ientityAuthentication.getEmail()); + sysUser.setPassword(SecurityUtils.encryptPassword(ientityAuthentication.getPassWord())); + sysUserMapper.updateUser(sysUser); + ientityAuthentication.setUserId(sysUser.getUserId()); + }else { + sysUser=new SysUser(); + sysUser.setIdCard(ientityAuthentication.getIdentityNo()); + sysUser.setNickName(ientityAuthentication.getName()); + sysUser.setUserName(ientityAuthentication.getUserName()); + sysUser.setPhonenumber(ientityAuthentication.getPhone()); + sysUser.setEmail(ientityAuthentication.getEmail()); + sysUser.setCreateBy(ientityAuthentication.getUserName()); + sysUser.setPassword(SecurityUtils.encryptPassword(ientityAuthentication.getPassWord())); + int row = sysUserMapper.insertUser(sysUser); + if(row<1) { + return AjaxResult.warn("注册失败"); + } + } + + ientityAuthentication.setUserId(sysUser.getUserId()); + ientityAuthentication.setUserName(sysUser.getUserName()); + // 已经认证过的用户才能注册,认证表中已经有该数据 + identityAuthenticationMapper.updateIdentityAuthentication(ientityAuthentication); + return AjaxResult.success("注册成功"); + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/task/CaseZipImportTask.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/task/CaseZipImportTask.java new file mode 100644 index 0000000..74409fb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/task/CaseZipImportTask.java @@ -0,0 +1,72 @@ +package com.ruoyi.wisdomarbitrate.task; + + +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.wisdomarbitrate.domain.CaseApplication; +import com.ruoyi.wisdomarbitrate.domain.FatchRule; +import com.ruoyi.wisdomarbitrate.service.impl.CaseZipImportImpl; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * @description rbd调用xfta计算任务类 + * @Author mingYang + * @Date 2021/11/12 15:35 + * @Version V1.0 + **/ + +public class CaseZipImportTask implements Callable> { + private CaseZipImportImpl caseZipImportImpl; + private Long templateId; + private List fatchRuleList; + private Map fatchMap; + private Map> fatchRuleMap; + private Map userMap; + private List dictDataList; + private File[] files; + private Map deptMap; + private LoginUser loginUser; + private Integer maxBatchNumber; + + public CaseZipImportTask(CaseZipImportImpl caseZipImportImpl, Long templateId, List fatchRuleList, Map fatchMap, Map> fatchRuleMap, Map userMap, List dictDataList, File[] files, Map deptMap, LoginUser loginUser,Integer maxBatchNumber) { + this.caseZipImportImpl = caseZipImportImpl; + this.templateId = templateId; + this.fatchRuleList = fatchRuleList; + this.fatchMap = fatchMap; + this.fatchRuleMap = fatchRuleMap; + this.userMap = userMap; + this.dictDataList = dictDataList; + this.files = files; + this.deptMap = deptMap; + this.loginUser = loginUser; + this.maxBatchNumber = maxBatchNumber; + } + + @Override + public List call() { + List caseApplications = new ArrayList<>(); + try { + for (File file1 : files) { + if (file1.isDirectory() && file1.listFiles() != null) { + + for (File file2 : file1.listFiles()) { + CaseApplication caseApplication = caseZipImportImpl.buildCaseInfo(file2, templateId, fatchRuleList, fatchRuleMap, fatchMap, userMap, dictDataList, deptMap, loginUser,maxBatchNumber); + if (caseApplication != null) { + caseApplications.add(caseApplication); + } + } + } + } + } catch (Exception e) { + throw new RuntimeException("导入失败"); + } + + return caseApplications; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/CaseLogUtils.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/CaseLogUtils.java new file mode 100644 index 0000000..64475ac --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/CaseLogUtils.java @@ -0,0 +1,84 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import cn.hutool.extra.spring.SpringUtil; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord; +import com.ruoyi.wisdomarbitrate.mapper.CaseLogRecordMapper; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 案件记录日志文件 + * + * @author wangqiong + */ +public class CaseLogUtils +{ + private static CaseLogRecordMapper caseLogRecordMapper= SpringUtil.getBean(CaseLogRecordMapper.class); + private static SysUserMapper userMapper= SpringUtil.getBean(SysUserMapper.class); + + /** + * 新增案件日志 + * @param caseAppliId 案件id,不能为空 + * @param caseNode 案件节点,不能为空 + * @param notes 备注 + */ + public static void insertCaseLog(@NotNull Long caseAppliId, @NotEmpty Integer caseNode, String notes ){ + CaseLogRecord operLog = new CaseLogRecord(); + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if(loginUser!=null) { + SysUser sysUser = userMapper.selectUserById(loginUser.getUserId()); + operLog.setCreateBy(sysUser.getUserName()); + operLog.setCreateNickName(sysUser.getNickName()); + operLog.setUpdateBy(sysUser.getUserName()); + }else { + operLog.setCreateBy("admin"); + operLog.setCreateNickName("管理员"); + operLog.setUpdateBy("admin"); + } + operLog.setCaseAppliId(caseAppliId); + operLog.setCaseNode(caseNode); + operLog.setNotes(notes); + caseLogRecordMapper.insertCaseLogRecord(operLog); + } + /** + * 新增案件日志 + * @param caseAppliId 案件id,不能为空 + * @param caseNode 案件节点,不能为空 + * @param notes 备注 + */ + public static void insertCaseLog(@NotNull Long caseAppliId, @NotEmpty Integer caseNode, String notes ,LoginUser loginUser ){ + CaseLogRecord operLog = new CaseLogRecord(); + // 获取当前的用户 + if(loginUser!=null) { + SysUser sysUser = userMapper.selectUserById(loginUser.getUserId()); + operLog.setCreateBy(sysUser.getUserName()); + operLog.setCreateNickName(sysUser.getNickName()); + operLog.setUpdateBy(sysUser.getUserName()); + }else { + operLog.setCreateBy("admin"); + operLog.setCreateNickName("管理员"); + operLog.setUpdateBy("admin"); + } + operLog.setCaseAppliId(caseAppliId); + operLog.setCaseNode(caseNode); + operLog.setNotes(notes); + caseLogRecordMapper.insertCaseLogRecord(operLog); + } + /** + * 批量新增案件日志 + * @param list + */ + public static void batchInsertCaseLog(List list ){ + + caseLogRecordMapper.batchInsertRecord(list); + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/FixSelectFlowDetailUtils.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/FixSelectFlowDetailUtils.java new file mode 100644 index 0000000..c37bcef --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/FixSelectFlowDetailUtils.java @@ -0,0 +1,362 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.ruoyi.common.constant.CaseApplicationConstants; +import com.ruoyi.common.constant.FileTransformation; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.utils.SealUtil; +import com.ruoyi.common.utils.file.SaaSAPIFileUtils; +import com.ruoyi.wisdomarbitrate.domain.*; +import com.ruoyi.wisdomarbitrate.mapper.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Component +public class FixSelectFlowDetailUtils { + + @Autowired + private CaseApplicationMapper caseApplicationMapper; + @Autowired + private SealSignRecordMapper sealSignRecordMapper; + @Autowired + private CaseAttachMapper caseAttachMapper; + @Autowired + private DeptIdentifyMapper deptIdentifyMapper; + @Autowired + private SealManageMapper sealManageMapper; + + /* + 定时查询签署流程详情 + */ + @Scheduled(cron = "0/10 * * * * ?") + @Transactional + public void fixExecuteSelectFlowDetailUtils() { + Gson gson = new Gson(); + + SealSignRecord sealSignRecordselect = new SealSignRecord(); + // sealSignRecordselect.setSignFlowStatus(1); + List sealSignRecords = sealSignRecordMapper.selectSealSignRecordbyStat(sealSignRecordselect); + + try { + if (sealSignRecords != null && sealSignRecords.size() > 0) { + for (int i = 0; i < sealSignRecords.size(); i++) { + SealSignRecord sealSignRecord = sealSignRecords.get(i); + EsignHttpResponse signFlowDetail = SignAward.signFlowDetail(sealSignRecord); + JsonObject signFlowDetailJsonObject = gson.fromJson(signFlowDetail.getBody(), JsonObject.class); + JsonObject flowDetailData = signFlowDetailJsonObject.getAsJsonObject("data"); + JsonArray signersArray = flowDetailData.get("signers").getAsJsonArray(); + Integer psnsignStatus = null; + Integer orgsignStatus = null; + for (int j = 0; j < signersArray.size(); j++) { + JsonObject signerObject = (JsonObject) signersArray.get(j); + + if (!(signerObject.get("psnSigner").toString()).equals("null")) { + JsonObject psnSignerData = signerObject.getAsJsonObject("psnSigner"); + if (psnSignerData != null) { + psnsignStatus = signerObject.get("signStatus").getAsInt(); + } + } + if (!(signerObject.get("orgSigner").toString()).equals("null")) { + JsonObject orgSignerData = signerObject.getAsJsonObject("orgSigner"); + if (orgSignerData != null) { + orgsignStatus = signerObject.get("signStatus").getAsInt(); + } + } + + } + if ((psnsignStatus.intValue() == 2) && (orgsignStatus.intValue() == 1)) { + //更新立案申请状态为待用印 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(sealSignRecord.getCaseAppliId()); + + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplicationselect != null) { + if ((caseApplicationselect.getCaseStatus() != null) && (caseApplicationselect.getCaseStatus().intValue() == CaseApplicationConstants.SIGN_ARBITRATION)) { + caseApplication.setCaseStatus(CaseApplicationConstants.ARBITRATED_SEAL); + caseApplicationMapper.submitCaseApplication(caseApplication); + + //修改"签署用印记录表"的状态为待用印 + sealSignRecord.setSignFlowStatus(2); + sealSignRecordMapper.updataSealSignRecord(sealSignRecord); + } + } + + } + if ((psnsignStatus.intValue() == 2) && (orgsignStatus.intValue() == 2)) { + //更新立案申请状态为待送达 + CaseApplication caseApplication = new CaseApplication(); + caseApplication.setId(sealSignRecord.getCaseAppliId()); + + CaseApplication caseApplicationselect = caseApplicationMapper.selectCaseApplication(caseApplication); + if (caseApplicationselect != null) { + if ((caseApplicationselect.getCaseStatus() != null) && (caseApplicationselect.getCaseStatus().intValue() == CaseApplicationConstants.ARBITRATED_SEAL)) { + caseApplication.setCaseStatus(CaseApplicationConstants.ARBITRATION_DELIVERY); + //下载审核完成的裁决书, + String signFlowId = sealSignRecord.getSignFlowid(); + EsignHttpResponse fileDownload = SaaSAPIFileUtils.fileDownloadUrl(signFlowId); + JsonObject fileDownloadJsonObject = gson.fromJson(fileDownload.getBody(), JsonObject.class); + JsonObject fileDownloadData = fileDownloadJsonObject.getAsJsonObject("data"); + JsonArray filesArray = fileDownloadData.get("files").getAsJsonArray(); + if (filesArray != null && filesArray.size() > 0) { + JsonObject fileObject = (JsonObject) filesArray.get(0); + String fileDownloadUrl = fileObject.get("downloadUrl").toString(); + //修改"签署用印记录表"的状态为签署完成 + sealSignRecord.setSignFlowStatus(3); + sealSignRecord.setFileDownloadUrl(fileDownloadUrl.substring(1, fileDownloadUrl.length() - 1)); + sealSignRecordMapper.updataSealSignRecord(sealSignRecord); + + String filearbitraUrl = fileDownloadUrl.substring(1, fileDownloadUrl.length() - 1); + caseApplication.setFilearbitraUrl(filearbitraUrl); + caseApplicationMapper.submitCaseApplication(caseApplication); + + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".pdf"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String savePath = "/home/ruoyi/uploadPath/upload/"; + + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + String resultFilePath = saveFolderPath + "/" + fileName; + File resultFilePathFile = new File(resultFilePath); + if (!resultFilePathFile.exists()) { + resultFilePathFile.createNewFile(); + } + + String fileDownloadUrlnew = fileDownloadUrl.substring(1, fileDownloadUrl.length() - 1); + boolean downLoadFile = FileTransformation.downLoadFileByUrl(fileDownloadUrlnew, resultFilePath); + if (downLoadFile) { + Long caseAppliId = sealSignRecord.getCaseAppliId(); + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setCaseAppliId(caseAppliId); + caseAttach.setAnnexType(3); + caseAttach.setAnnexPath(savePath); + caseAttach.setAnnexName(saveName); + caseAttachMapper.updateCaseAttachBycaseid(caseAttach); + } + + } + } + } + + } + } + + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * 定时查询企业认证状态 + * + * @throws Exception + */ + @Scheduled(cron = "*/30 * * * * *") + @Transactional + public void fixExecuteSelectDeptIndentifyUtils() throws Exception { + Gson gson = new Gson(); + DeptIdentify deptIdentify = new DeptIdentify(); + List deptIdentifysnew = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifysnew != null && deptIdentifysnew.size() > 0) { + for (int i = 0; i < deptIdentifysnew.size(); i++) { + DeptIdentify deptIdentify1 = deptIdentifysnew.get(i); + Integer identifyStatus = deptIdentify1.getIdentifyStatus(); + if (identifyStatus!=1){ + String authFlowId = deptIdentify1.getAuthFlowId(); + if (authFlowId != null) { + EsignHttpResponse identifyInfo = SignAward.getDeptIdentifyInfo(deptIdentify1); + JsonObject identifyInfoJsonObject = gson.fromJson(identifyInfo.getBody(), JsonObject.class); + int code = identifyInfoJsonObject.get("code").getAsInt(); + if (code == 0) { + JsonObject identifyInfoData = identifyInfoJsonObject.getAsJsonObject("data"); + int realnameStatus = identifyInfoData.get("realnameStatus").getAsInt(); + if (realnameStatus == 1) { + String orgId = identifyInfoData.get("orgId").getAsString(); + //查询企业内部印章 + EsignHttpResponse response = SignAward.deptIdentifySealList(orgId); + JsonObject jsonObject = gson.fromJson(response.getBody(), JsonObject.class); + int code1 = jsonObject.get("code").getAsInt(); + if (code1 == 0) { + JsonObject data = jsonObject.getAsJsonObject("data"); + JsonArray seals = data.get("seals").getAsJsonArray(); + if (seals.size() > 0) { + for (int j = 0; j < seals.size(); j++) { + //保存印章信息到数据库 + JsonObject asJsonObject = seals.get(j).getAsJsonObject(); + SealManage sealManage = new SealManage(); + String sealName = asJsonObject.get("sealName").toString(); + String sealId = asJsonObject.get("sealId").toString(); + String url = asJsonObject.get("sealImageDownloadUrl").toString(); + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".jpg"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String savePath = "/home/ruoyi/uploadPath/upload/"; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + String resultFilePath = saveFolderPath + "/" + fileName; + File resultFilePathFile = new File(resultFilePath); + if (!resultFilePathFile.exists()) { + resultFilePathFile.createNewFile(); + } + String fileDownloadUrlnew = url.substring(1, url.length() - 1); + boolean downLoadFile = FileTransformation.downLoadFileByUrl(fileDownloadUrlnew, resultFilePath); + if (downLoadFile) { + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setAnnexType(10); //10代表印章图片 + caseAttach.setAnnexPath(savePath); + caseAttach.setAnnexName(saveName); + int i1 = caseAttachMapper.save(caseAttach); + if (i1 > 0) { + //将印章信息保存到公章管理表里 + String sealName1 = sealName.substring(1, sealName.length() - 1); + String sealId1 = sealId.substring(1, sealId.length() - 1); + Integer annexId1 = caseAttach.getAnnexId(); + sealManage.setAnnexId(annexId1); + sealManage.setSealId(sealId1); + sealManage.setSealName(sealName1); + sealManage.setIdentifyId(deptIdentify1.getId()); + sealManage.setSealStatus(1); + sealManage.setIsUse(1); + sealManageMapper.insertSealManage(sealManage); + } + } + } + } + + } + //将orgId保存到数据库里 + deptIdentify1.setOrgId(orgId); + deptIdentify1.setIdentifyStatus(1); + deptIdentify1.setIsUse(0); //默认机构为未启用 + int row = deptIdentifyMapper.updateDeptIdentify(deptIdentify1); + } + }else { + deptIdentify1.setIdentifyStatus(2); + deptIdentifyMapper.updateDeptIdentify(deptIdentify1); + } + } + } + } + } + } + + + /** + * 定时查询印章审核状态 + */ + @Scheduled(cron = "0/30 * * * * ?") + @Transactional + public void searchForInstitutionalSeal() { + try { + SealManage sealManage = new SealManage(); + sealManage.setSealStatus(0); + List sealManageList = sealManageMapper.selectSealList(sealManage); + if (sealManageList != null && sealManageList.size() > 0) { + for (SealManage sealManage1 : sealManageList) { + //查询企业内部印章 + Integer annexId = sealManage1.getAnnexId(); + String sealId = sealManage1.getSealId(); + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setId(sealManage1.getIdentifyId()); + List deptIdentifies = deptIdentifyMapper.selectDeptIdentify(deptIdentify); + if (deptIdentifies != null && deptIdentifies.size() > 0) { + DeptIdentify deptIdentify1 = deptIdentifies.get(0); + String orgId = deptIdentify1.getOrgId(); + if (orgId == null) { + continue; + } + if (annexId == null) { + //说明之前没有下载过 + EsignHttpResponse response = SignAward.getOrgSeal(orgId, sealId); + JSONObject jsonObject = JSONObject.parseObject(response.getBody()); + int code = jsonObject.getIntValue("code"); + if (code == 0) { + JSONObject data = jsonObject.getJSONObject("data"); + int sealStatus = data.getIntValue("sealStatus"); + if (sealStatus == 1) {//印章状态 1已启用,2待审核,3审核不通过,4 挂起 + //已启用证明审核通过,下载到数据库 + String sealImageDownloadUrl = data.getString("sealImageDownloadUrl"); + LocalDate now = LocalDate.now(); + String year = Integer.toString(now.getYear()); + String month = String.format("%02d", now.getMonthValue()); + String day = String.format("%02d", now.getDayOfMonth()); + String saveFolderPath = "/home/ruoyi/uploadPath/upload/" + year + "/" + month + "/" + day; + String fileName = UUID.randomUUID().toString().replace("-", "") + ".jpg"; + String saveName = "/profile/upload/" + year + "/" + month + "/" + day + "/" + fileName; + String savePath = "/home/ruoyi/uploadPath/upload/"; + // 创建日期目录 + File saveFolder = new File(saveFolderPath); + if (!saveFolder.exists()) { + saveFolder.mkdirs(); + } + String resultFilePath = saveFolderPath + "/" + fileName; + File resultFilePathFile = new File(resultFilePath); + if (!resultFilePathFile.exists()) { + resultFilePathFile.createNewFile(); + } + boolean downLoadFile = FileTransformation.downLoadFileByUrl(sealImageDownloadUrl, resultFilePath); + if (downLoadFile) { + CaseAttach caseAttach = new CaseAttach(); + caseAttach.setAnnexType(10); //10代表印章图片 + caseAttach.setAnnexPath(savePath); + caseAttach.setAnnexName(saveName); + int i1 = caseAttachMapper.save(caseAttach); + if (i1 > 0) { + //将附件id保存到公章管理表里 + Integer annexId1 = caseAttach.getAnnexId(); + sealManage1.setAnnexId(annexId1); + sealManage1.setSealStatus(1); + sealManage1.setIsUse(0); + sealManageMapper.updateSealManage(sealManage1); + } + } + } + } + } + } + + } + } + } catch (EsignDemoException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} + + diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ImageToBase64Converter.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ImageToBase64Converter.java new file mode 100644 index 0000000..752b36b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ImageToBase64Converter.java @@ -0,0 +1,30 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import java.io.BufferedInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; + +public class ImageToBase64Converter { + public static String imageToBase64(String imagePath) throws Exception { + Path path = Paths.get(imagePath); + byte[] imageBytes = Files.readAllBytes(path); + String base64Image = Base64.getEncoder().encodeToString(imageBytes); + return base64Image; + } + + public static void main(String[] args) { + String imagePath = "D:\\develop\\2.jpg"; + try { + String base64Image = imageToBase64(imagePath); + System.out.println(base64Image); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/OCRUtils.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/OCRUtils.java new file mode 100644 index 0000000..b64d55d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/OCRUtils.java @@ -0,0 +1,275 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.wisdomarbitrate.domain.FatchRule; +import com.tencentcloudapi.bsca.v20210811.models.LicenseSummary; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.ocr.v20181119.OcrClient; +import com.tencentcloudapi.ocr.v20181119.models.*; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +public class OCRUtils { + //API的SecretId + private static final String SECRET_ID = "AKIDeEf2A8uX1HSainvvnXAc3X9ZlhtyvkMp"; + //API的SecretKey + private static final String SECRET_KEY = "QjphKo8zkHZigT8j9PVtFPJyfIvO3d6V"; + // 仲裁申请书识别字段 + private static final String[] applicantName = {"申请人", "统一社会信用代码", "负责人", "住所", "联系地址" + , "委托代理人", "联系电话", "电子邮件", "被申请人", "居民身份证号码", "仲裁请求", "事实和理由"}; + // 贷款合同识别字段 + private static final String[] contractName = { + "合同编号", "甲方(贷款人)", "或委托代理人签字:", "本合同的初始贷款年利率为", "乙方确认有效的电子信箱地址为"}; + // 调解协议识别字段 + private static final String[] accordName = {"金融消费纠纷基本情况", "经调解,双方自愿达成如下协议"}; + // 授权委托书识别字段 + private static final String[] powerAttorneyName = {"职务"}; + + /** + * pdf识别成文字 + * + * @param imageBase64 + * @param pageNumber + * @param fatchRules 抓取规则 + * @return + */ + public static String pdfIdentifyText(String imageBase64, Integer pageNumber, List fatchRules) { + StringBuilder respStr = new StringBuilder(); + try { + // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 + // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 + // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 + Credential cred = new Credential(SECRET_ID, SECRET_KEY); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("ocr.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + GeneralAccurateOCRRequest req = new GeneralAccurateOCRRequest(); + req.setImageBase64(imageBase64); + req.setIsPdf(true); + req.setPdfPageNumber(pageNumber.longValue()); + // 返回的resp是一个SmartStructuralOCRV2Response的实例,与请求对象对应 + GeneralAccurateOCRResponse resp = client.GeneralAccurateOCR(req); + // 输出json格式的字符串回包 + System.out.println(GeneralAccurateOCRResponse.toJsonString(resp)); + // 获取响应内容 + TextDetection[] textDetections = resp.getTextDetections(); + if (textDetections == null || textDetections.length == 0) { + return respStr.toString(); + } + for (TextDetection textDetection : textDetections) { + respStr.append(textDetection.getDetectedText()); + } + } catch (TencentCloudSDKException e) { + throw new ServiceException("ocr识别失败"); + } + if (respStr.toString().endsWith(String.valueOf(pageNumber))) { + int lastIndexOf = respStr.toString().lastIndexOf(String.valueOf(pageNumber)); + return respStr.toString().substring(0, lastIndexOf); + } + return respStr.toString(); + } + + + public static String pdfConvertBase64(String pathUrl) { + try { + File file = new File(pathUrl); + FileInputStream fileInputStream = new FileInputStream(file); + byte[] fileBytes = new byte[(int) file.length()]; + fileInputStream.read(fileBytes); + fileInputStream.close(); + // 将字节数组转换为Base64值 + return Base64.getEncoder().encodeToString(fileBytes); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据抓取规则获取内容 + * + * @param ocrText ocr识别的text + * @param fatchRules 抓取规则 + * @return + */ + public static void fatchRuleGetContent(String ocrText, List fatchRules, Map fatchMap) { + if (StrUtil.isEmpty(ocrText) || CollectionUtil.isEmpty(fatchRules)) { + return; + } + for (FatchRule fatchRule : fatchRules) { + // 从后往前抓取 + if (fatchRule.getFatchOrder() != null && fatchRule.getFatchOrder() == 1) { + reverseSubstringText(ocrText, fatchRule, fatchMap,null); + } else { + // 从前往后抓取 + substringText(ocrText, fatchRule, fatchMap,null); + + } + } + + + } + + /** + * 根据抓取规则获取内容 + * + * @param ocrText ocr识别的text + * @param fatchRules 抓取规则 + * @return + */ + public static void fatchRuleGetContent(String ocrText, List fatchRules, Map fatchMap, Long caseId) { + if (StrUtil.isEmpty(ocrText) || CollectionUtil.isEmpty(fatchRules)) { + return; + } + for (FatchRule fatchRule : fatchRules) { + // 从后往前抓取 + if (fatchRule.getFatchOrder() != null && fatchRule.getFatchOrder() == 1) { + reverseSubstringText(ocrText, fatchRule, fatchMap, caseId); + } else { + // 从前往后抓取 + substringText(ocrText, fatchRule, fatchMap, caseId); + + } + } + + + } + + + /** + * 正向截取字段 + * + * @param text + * @param fatchRule + * @param fatchMap + */ + private static void substringText(String text, FatchRule fatchRule, Map fatchMap, Long caseId) { + String startContent = fatchRule.getStartContent(); + String endContent = fatchRule.getEndContent(); + // 开始为空结束为空 + if (StrUtil.isEmpty(startContent) && StrUtil.isEmpty(endContent)) { + fatchMap.put(fatchRule.getColumnName(), trimStr(text)); + } else if (StrUtil.isNotEmpty(startContent) && StrUtil.isEmpty(endContent)) { + // 开始不为空结束为空 + int startContIndex = StrUtil.ordinalIndexOf(text, startContent, fatchRule.getStartContentRepeatOrder()); + if (startContIndex != -1 && text.length() >= (startContIndex + startContent.length())) { + String substring = text.substring(startContIndex + startContent.length()); + // 去除\n + fatchMap.put(fatchRule.getColumnName(), trimStr(substring)); + } + + } else if (StrUtil.isEmpty(startContent) && StrUtil.isNotEmpty(endContent)) { + // 开始为空结束不为空 + int endContIndex = StrUtil.ordinalIndexOf(text, endContent, fatchRule.getEndContentRepeatOrder()); + if (endContIndex != -1) { + String substring = text.substring(0, endContIndex); + fatchMap.put(fatchRule.getColumnName(), trimStr(substring)); + } + } else if (StrUtil.isNotEmpty(startContent) && StrUtil.isNotEmpty(endContent)) { + // 开始结束不为空 + int startIndexOf = StrUtil.ordinalIndexOf(text, startContent, fatchRule.getStartContentRepeatOrder()); + int endIndexOf = StrUtil.ordinalIndexOf(text, endContent, fatchRule.getEndContentRepeatOrder()); + if (startIndexOf != -1 && endIndexOf != -1 && endIndexOf >= (startIndexOf + startContent.length()) && text.length() >= endIndexOf) { + String substring = text.substring(startIndexOf + startContent.length(), endIndexOf); + + fatchMap.put(fatchRule.getColumnName(), trimStr(substring)); + + } + } + } + + + /** + * 从后往前截取字符串 + * + * @param text + * @param fatchRule + * @param fatchMap + */ + public static void reverseSubstringText(String text, FatchRule fatchRule, Map fatchMap, Long caseId) { + + // 反正字符串 + String reverseText = StrUtil.reverse(text); + // 结束截取字段 + String reverseEndContent = ""; + // 开始截取字段 + String reverseStartContent = ""; + if (StrUtil.isNotEmpty(fatchRule.getEndContent())) { + reverseEndContent = StrUtil.reverse(fatchRule.getEndContent()); + } + if (StrUtil.isNotEmpty(fatchRule.getStartContent())) { + reverseStartContent = StrUtil.reverse(fatchRule.getStartContent()); + } + // 开始和结束截取都为空 + if (StrUtil.isEmpty(reverseStartContent) && StrUtil.isEmpty(reverseEndContent)) { + fatchMap.put(fatchRule.getColumnName(), trimStr(text)); + } else if (StrUtil.isEmpty(reverseStartContent) && StrUtil.isNotEmpty(reverseEndContent)) { + // 开始为空,结束不为空 + // 根据截取的序号查找出位置 + int indexOf = StrUtil.ordinalIndexOf(reverseText, reverseEndContent, fatchRule.getEndContentRepeatOrder()); + if (indexOf != -1) { + String substring = reverseText.substring(0, indexOf); + if (StrUtil.isNotEmpty(substring)) { + fatchMap.put(fatchRule.getColumnName(), trimStr(StrUtil.reverse(substring))); + } + } + } else if (StrUtil.isNotEmpty(reverseStartContent) && StrUtil.isEmpty(reverseEndContent)) { + // 开始不为空,结束为空 + int indexOf = StrUtil.ordinalIndexOf(reverseText, reverseStartContent, fatchRule.getStartContentRepeatOrder()); + if (indexOf != -1 && (indexOf + reverseStartContent.length() <= text.length())) { + String substring = reverseText.substring(indexOf + reverseStartContent.length()); + if (StrUtil.isNotEmpty(substring)) { + fatchMap.put(fatchRule.getColumnName(), trimStr(StrUtil.reverse(substring))); + } + } + + } else if (StrUtil.isNotEmpty(reverseStartContent) && StrUtil.isNotEmpty(reverseEndContent)) { + // 开始结束都不为空 + int endIndexOf = StrUtil.ordinalIndexOf(reverseText, reverseEndContent, fatchRule.getEndContentRepeatOrder()); + int startIndexOf = StrUtil.ordinalIndexOf(reverseText, reverseStartContent, fatchRule.getStartContentRepeatOrder()); + if (startIndexOf != -1 && endIndexOf != -1 && endIndexOf >= (startIndexOf + reverseStartContent.length()) && text.length() >= endIndexOf) { + String substring = reverseText.substring(startIndexOf + reverseStartContent.length(), endIndexOf); + if (StrUtil.isNotEmpty(substring)) { + fatchMap.put(fatchRule.getColumnName(), trimStr(StrUtil.reverse(substring))); + } + } + } + + + } + + /** + * 去除末尾空格 + * + * @param substring + * @return + */ + private static String trimStr(String substring) { + if (StrUtil.isNotEmpty(substring)) { + return StrUtil.trim(substring); + } else { + return ""; + } + + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/SignAward.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/SignAward.java new file mode 100644 index 0000000..5fc8e05 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/SignAward.java @@ -0,0 +1,546 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.ruoyi.common.core.domain.entity.EsignHttpResponse; +import com.ruoyi.common.enums.EsignRequestType; +import com.ruoyi.common.exception.EsignDemoException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.EsignApplicaConfig; +import com.ruoyi.common.utils.EsignHttpHelper; +import com.ruoyi.common.utils.SealUtil; +import com.ruoyi.wisdomarbitrate.StringIdsReq; +import com.ruoyi.wisdomarbitrate.domain.DeptIdentify; +import com.ruoyi.wisdomarbitrate.domain.SealSignRecord; + +import java.io.File; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class SignAward { + + private static String eSignHost = EsignApplicaConfig.EsignHost; + private static String eSignAppId = EsignApplicaConfig.EsignAppId; + private static String eSignAppSecret = EsignApplicaConfig.EsignAppSecret; + + + public static void main(String[] args) throws EsignDemoException { + Gson gson = new Gson(); + + + + /* 发起签署*/ +// EsignHttpResponse createByFile = createByFile(sealSignRecord); +// JsonObject createByFileJsonObject = gson.fromJson(createByFile.getBody(), JsonObject.class); +// JsonObject createByFileData = createByFileJsonObject.getAsJsonObject("data"); +// String signFlowId = createByFileData.get("signFlowId").getAsString(); +// System.err.println("流程id:"+signFlowId); + + /* 获取文件签名印章位置*/ +// EsignHttpResponse positions = getPositions(sealSignRecord); +// JsonObject positionsJsonObject = gson.fromJson(positions.getBody(), JsonObject.class); +// JsonObject positionsData = positionsJsonObject.getAsJsonObject("data"); +// JsonArray keywordPositions = positionsData.get("keywordPositions").getAsJsonArray(); +// System.out.println("获取文件签名印章位置:" +keywordPositions.toString()); + +// String signFlowId = "c9955453716344f9971d308abdc13464"; + //获取合同文件签名链接 +// EsignHttpResponse signUrl = signUrl(sealSignRecord); +// JsonObject signUrlJsonObject = gson.fromJson(signUrl.getBody(), JsonObject.class); +// JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data"); +// String shortUrl = signUrlData.get("shortUrl").getAsString(); +// String url = signUrlData.get("url").getAsString(); +// System.out.println("签署短链接:" +shortUrl); +// System.out.println("签署长链接:"+url); + + //获取合同文件用印链接 +// EsignHttpResponse usesealUrl = usesealUrl(sealSignRecord); +// JsonObject usesealUrlJsonObject = gson.fromJson(usesealUrl.getBody(), JsonObject.class); +// JsonObject usesealUrlData = usesealUrlJsonObject.getAsJsonObject("data"); +// String shortusesealUrl = usesealUrlData.get("shortUrl").getAsString(); +// String sealUrl = usesealUrlData.get("url").getAsString(); +// System.out.println("签署长链接:" +shortusesealUrl); +// System.out.println("签署短链接:"+sealUrl); + + //查询机构认证信息 +// DeptIdentify deptIdentify = new DeptIdentify(); +// deptIdentify.setDeptName("西安云美电子科技有限公司"); +// EsignHttpResponse identifyInfo = getDeptIdentifyInfo(deptIdentify); +// JsonObject identifyInfoJsonObject = gson.fromJson(identifyInfo.getBody(), JsonObject.class); +// JsonObject identifyInfoData = identifyInfoJsonObject.getAsJsonObject("data"); +// int realnameStatus = identifyInfoData.get("realnameStatus").getAsInt(); +// String orgId = identifyInfoData.get("orgId").getAsString(); +// System.out.println("机构认证状态:" +realnameStatus); +// System.out.println("机构id:" +orgId); + +// EsignHttpResponse identifyInfo = deptIdentifySealList(orgId); +// JsonObject identifyInfoJsonObject = gson.fromJson(identifyInfo.getBody(), JsonObject.class); +// JsonObject identifyInfoData = identifyInfoJsonObject.getAsJsonObject("data"); +// JsonArray sealArray = identifyInfoData.get("seals").getAsJsonArray(); +// String sealNames = ""; +// if(sealArray.size()>0){ +// for (int i = 0; i < sealArray.size(); i++) { +// JsonObject sealObject = (JsonObject)sealArray.get(i); +// String sealName = sealObject.get("sealName").toString(); +// String sealNamenew = sealName.substring(1,sealName.length()-1); +// sealNames += sealNamenew +","; +// } +// } +// System.out.println("机构印章名称:" +sealNames.substring(0,sealNames.length()-1)); + + + //查询签署流程详情 +// EsignHttpResponse signFlowDetail = signFlowDetail(sealSignRecord); +// JsonObject signFlowDetailJsonObject = gson.fromJson(signFlowDetail.getBody(),JsonObject.class); +// JsonObject flowDetailData = signFlowDetailJsonObject.getAsJsonObject("data"); +// JsonArray signersArray = flowDetailData.get("signers").getAsJsonArray(); +// for (int i = 0; i < signersArray.size(); i++) { +// JsonObject signerObject = (JsonObject)signersArray.get(i); +// Integer psnsignStatus ; +// Integer orgsignStatus ; +// if(!(signerObject.get("psnSigner").toString()).equals("null")){ +// JsonObject psnSignerData = signerObject.getAsJsonObject("psnSigner"); +// if(psnSignerData!=null){ +// psnsignStatus = signerObject.get("signStatus").getAsInt(); +// sealSignRecord.setPsnsignStatus(psnsignStatus); +// } +// } +// if(!(signerObject.get("orgSigner").toString()).equals("null")){ +// JsonObject orgSignerData = signerObject.getAsJsonObject("orgSigner"); +// if(orgSignerData!=null){ +// orgsignStatus = signerObject.get("signStatus").getAsInt(); +// sealSignRecord.setOrgsignStatus(orgsignStatus); +// } +// +// } +// } + +// System.out.println(signFlowDetailJsonObject); + DeptIdentify deptIdentify = new DeptIdentify(); + deptIdentify.setAuthFlowId("OF-2b5883bf4508000c"); + EsignHttpResponse deptIdentifyInfo = getDeptIdentifyInfo(deptIdentify); + System.out.println(deptIdentifyInfo); + + } + + + /** + * 查询签署流程详情 + * + * @return + */ + public static EsignHttpResponse signFlowDetail(SealSignRecord sealSignRecord) throws EsignDemoException { + String signFlowId = sealSignRecord.getSignFlowid(); + String apiaddr = "/v3/sign-flow/" + signFlowId + "/detail"; + String jsonParm = null; + //请求方法 + EsignRequestType requestType = EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + + /** + * 发起签署 + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse createByFile(SealSignRecord sealSignRecord ,List sealIdList) throws EsignDemoException { + String apiaddr = "/v3/sign-flow/create-by-file"; + + String fileId = sealSignRecord.getFileid(); + String fileName = sealSignRecord.getFilename(); + + String psnAccount = sealSignRecord.getPensonAccount(); + String psnName = sealSignRecord.getPensonName(); + + String orgName = sealSignRecord.getOrgnizeName(); + String orgNamePsnAccount = sealSignRecord.getOrgnizeNamePsnAccount(); + String orgNamepsnName = sealSignRecord.getOrgnizeNamepsnName(); + + String positionPagepsn = sealSignRecord.getPositionPagepsn(); + double positionXpsn = sealSignRecord.getPositionXpsn(); + double positionYpsn = sealSignRecord.getPositionYpsn(); + + String positionPageorg = sealSignRecord.getPositionPageorg(); + double positionXorg = sealSignRecord.getPositionXorg(); + double positionYorg = sealSignRecord.getPositionYorg(); + String availableSealId = "209af82b-5f87-4e0a-b0d8-cc4923b6e652"; + + + String jsonParm = "{\n" + + " \"docs\": [\n" + + " {\n" + + " \"fileId\": \"" + fileId + "\",\n" + + " \"fileName\": \"" + fileName + "\"\n" + + " }\n" + + " ],\n" + + " \"signFlowConfig\": {\n" + + " \"signFlowTitle\": \"测试合同\",\n" + + " \"autoStart\": true,\n" + + " \"authConfig\": {\n" + + " \"willingnessAuthModes\": [\n" + + " \"CODE_SMS\"\n" + + " ],\n" + + " \"psnAvailableAuthModes\": [\n" + + " \"PSN_MOBILE3\"\n" + + " ],\n" + + " \"orgAvailableAuthModes\": [\n" + + " \"ORG_LEGALREP\"\n" + + " ]\n" + + " },\n" + + + " \"signConfig\": {\n" + + " \"availableSignClientTypes\": \"1\"\n" + + " },\n" + + + " \"autoFinish\": true\n" + + " },\n" + + + " \"signers\": [\n" + + " {\n" + + " \"psnSignerInfo\": {\n" + + " \"psnAccount\": \"" + psnAccount + "\",\n" + + " \"psnInfo\": {\n" + + " \"psnName\": \"" + psnName + "\"\n" + + " }\n" + + " },\n" + + " \"signFields\": [\n" + + " {\n" + + " \"fileId\": \"" + fileId + "\",\n" + + " \"normalSignFieldConfig\": {\n" + + " \"autoSign\": false,\n" + + " \"freeMode\": false,\n" + + " \"movableSignField\": false,\n" + + " \"signFieldPosition\": {\n" + + " \"positionPage\": \"" + positionPagepsn + "\",\n" + + " \"positionX\": " + positionXpsn + ",\n" + + " \"positionY\": " + positionYpsn + "\n" + + " },\n" + + " \"signFieldStyle\": 1\n" + + " },\n" + + " \"signFieldType\": 0\n" + + " }\n" + + " ],\n" + + " \"signerType\": 0\n" + + " },\n" + + + " {\n" + + " \"orgSignerInfo\": {\n" + + " \"orgName\": \"" + orgName + "\",\n" + + " \"transactorInfo\": {\n" + + " \"psnAccount\": \"" + orgNamePsnAccount + "\",\n" + + " \"psnInfo\": {\n" + + " \"psnName\": \"" + orgNamepsnName + "\"\n" + + " }\n" + + " }\n" + + " },\n" + + + " \"signFields\": [\n" + + " {\n" + + " \"fileId\": \"" + fileId + "\",\n" + + " \"normalSignFieldConfig\": {\n" + + " \"autoSign\": false,\n" + + " \"freeMode\": false,\n" + + + /* " \"availableSealIds\": [\n" + + " \"" + availableSealId + "\"\n" + + " ],\n" +*/ + // " \"availableSealIds\": " + new Gson().toJson(sealIdList) + ",\n" + + + " \"signFieldPosition\": {\n" + + " \"positionPage\": \"" + positionPageorg + "\",\n" + + " \"positionX\": " + positionXorg + ",\n" + + " \"positionY\": " + positionYorg + "\n" + + " },\n" + + " \"signFieldStyle\": 1\n" + + " },\n" + + " \"signFieldType\": 0\n" + + " }\n" + + " ],\n" + + " \"signerType\": 1\n" + + " }\n" + + + " ]\n" + + "}"; + + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + /** + * 获取合同文件签名链接 + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse signUrl(SealSignRecord sealSignRecord) throws EsignDemoException { + + String signFlowId = sealSignRecord.getSignFlowid(); + String psnAccount = sealSignRecord.getPensonAccount(); + + String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url"; + String jsonParm = "{\n" + + + " \"clientType\": \"PC\",\n" + + + " \"operator\": {\n" + + " \"psnAccount\": \"" + psnAccount + "\"\n" + + " }\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + /** + * 获取批量签页面链接 + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse batchSignUrl(StringIdsReq idsReq) throws EsignDemoException { + + List signFlowIds = idsReq.getIds(); + String psnAccount = idsReq.getPsnAccount(); + String apiaddr = "/v3/sign-flow/batch-sign-url"; + JSONObject paramObj = new JSONObject(); + paramObj.put("operatorId",idsReq.getPsnId()); + paramObj.put("signFlowIds",signFlowIds); + paramObj.put("clientType","PC"); + String jsonParm = JSON.toJSONString(paramObj); + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + /** + * 根据手机号获取账户id + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse identityInfo(StringIdsReq idsReq) throws EsignDemoException { + + List signFlowIds = idsReq.getIds(); + String psnAccount = idsReq.getPsnAccount(); + String apiaddr = "/v3/persons/identity-info?psnAccount=" +psnAccount; + + String jsonParm = "{}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.GET; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + + /** + * 获取合同文件用印链接 + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse usesealUrl(SealSignRecord sealSignRecord) throws EsignDemoException { + String signFlowId = sealSignRecord.getSignFlowid(); + String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url"; + + String psnAccount = sealSignRecord.getOrgnizeNamePsnAccount(); + String orgName = sealSignRecord.getOrgnizeName(); + + String jsonParm = "{\n" + + " \"operator\": {\n" + + + " \"psnAccount\": \"" + psnAccount + "\"\n" + + " },\n" + + " \"organization\": {\n" + + " \"orgName\": \"" + orgName + "\"\n" + + + " }\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + /** + * 获取机构认证&授权页面链接 + * + * @return + */ + public static EsignHttpResponse deptIdentifyUrl(DeptIdentify deptIdentify) throws EsignDemoException { + String apiaddr = "/v3/org-auth-url"; + String psnName = deptIdentify.getOperName(); + String phonenumber = deptIdentify.getOperPhone(); + String orgName = deptIdentify.getIdentifyName(); + String jsonParm = "{\n" + + " \"orgAuthConfig\": {\n" + + " \"orgName\": \"" + orgName + " \",\n" + + " \"transactorInfo\": {\n" + + " \"psnAccount\": \"" + phonenumber + "\",\n" + + " \"psnInfo\": {\n" + + " \"psnName\": \"" + psnName + "\",\n" + + " \"psnMobile\": \"" + phonenumber + "\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"authorizeConfig\": {\n" + + " \"authorizedScopes\": [\n" + + " \"get_org_identity_info\",\n" + + " \"get_psn_identity_info\",\n" + + " \"org_initiate_sign\",\n" + + " \"psn_initiate_sign\",\n" + + " \"manage_org_resource\",\n" + + " \"manage_psn_resource\",\n" + + " \"use_org_order\"\n" + + " ]\n" + + " }\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + /** + * 查询企业认证状态 + */ + public static EsignHttpResponse getDeptIdentifyInfo(DeptIdentify deptIdentify) throws EsignDemoException { + String apiaddr = "/v3/organizations/identity-info?orgName=" + deptIdentify.getIdentifyName(); + + String jsonParm = "{}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + + /** + * 查询企业内部印章 + */ + public static EsignHttpResponse deptIdentifySealList(String orgId) throws EsignDemoException { + int pageNum = 1; + int pageSize = 10; + String apiaddr = "/v3/seals/org-own-seal-list?orgId=" + orgId + "&pageNum=" + pageNum + "&pageSize=" + pageSize; + String jsonParm = null; + //请求方法 + EsignRequestType requestType = EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + + /** + * 获取文件签名印章位置 + * + * @return + * @throws EsignDemoException + */ + public static EsignHttpResponse getPositions(SealSignRecord sealSignRecord) throws EsignDemoException { + String fileId = sealSignRecord.getFileid(); + String apiaddr = "/v3/files/" + fileId + "/keyword-positions"; + String jsonParm = "{\n" + + " \"keywords\": [\n" + + " \"仲裁员:\",\n" + + " \"(仲裁委员会盖章)\"\n" + + " ]\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成请求签名鉴权方式的Header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + /** + * 创建机构图片印章 + * + * @return + */ + public static EsignHttpResponse createOrgByImage(DeptIdentify deptIdentify,String sealName, String filePath) throws EsignDemoException { + String apiaddr = "/v3/seals/org-seals/create-by-image"; + String orgId = deptIdentify.getOrgId(); + //上传印章图片 + //步骤一:获取印章图片上传地址fileUploadUrl + EsignHttpResponse response1 = SealUtil.getFileUploadUrl(filePath); + JSONObject jsonObject1 = JSONObject.parseObject(response1.getBody()); + String fileUploadUrl = jsonObject1.getJSONObject("data").getString("fileUploadUrl"); + //步骤二:将印章图片文件流上传到fileUploadUrl + EsignHttpResponse response2 = SealUtil.fileStreamUpload(fileUploadUrl, filePath); + JSONObject jsonObject2 = JSONObject.parseObject(response2.getBody()); + int errCode = jsonObject2.getIntValue("errCode"); + if (errCode == 0) { //业务码,0表示成功,非0表示异常。 + //获取步骤一里面的fileKey + String sealImageFileKey = jsonObject1.getJSONObject("data").getString("fileKey"); + + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm = "{\n" + + " \"orgId\": \"" + orgId + "\",\n" + + " \"sealImageFileKey\": \"" + sealImageFileKey + "\",\n" + + " \"sealName\": \"" + sealName + "\",\n" + + " \"sealWidth\": 50,\n" + + " \"sealHeight\": 50,\n" + + " \"sealBizType\": \"COMMON\"\n" + + "}"; + //请求方法 + EsignRequestType requestType = EsignRequestType.POST; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true); + } + + return null; + } + + + + + /** + * 查询指定印章详情(机构) + */ + + public static EsignHttpResponse getOrgSeal(String orgId, String sealId) throws EsignDemoException { + String apiaddr = "/v3/seals/org-seal-info?orgId=" + orgId + "&sealId=" + sealId; + + //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null + String jsonParm = null; + //请求方法 + EsignRequestType requestType = EsignRequestType.GET; + //生成签名鉴权方式的的header + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, false); + //发起接口请求 + return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, false); + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/Tset.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/Tset.java new file mode 100644 index 0000000..5859dd0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/Tset.java @@ -0,0 +1,130 @@ +package com.ruoyi.wisdomarbitrate.utils; + + +import com.documents4j.api.DocumentType; +import com.documents4j.api.IConverter; +import com.documents4j.job.LocalConverter; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.ocr.v20181119.OcrClient; +import com.tencentcloudapi.ocr.v20181119.models.GeneralAccurateOCRRequest; +import com.tencentcloudapi.ocr.v20181119.models.GeneralAccurateOCRResponse; +import com.tencentcloudapi.ocr.v20181119.models.SmartStructuralOCRV2Request; +import com.tencentcloudapi.ocr.v20181119.models.SmartStructuralOCRV2Response; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.json.JSONArray; +import org.json.JSONObject; + + +import java.io.*; +import java.util.*; + +public class Tset { + public static void main(String[] args) { + //API的SecretId + final String SECRET_ID = "AKIDeEf2A8uX1HSainvvnXAc3X9ZlhtyvkMp"; + //API的SecretKey + final String SECRET_KEY = "QjphKo8zkHZigT8j9PVtFPJyfIvO3d6V"; + + // String pdfFilePath = "http://121.40.189.20:9000/API/uploadPath/upload/ca2ca4697e5449ff9b9d23f95b221f58.pdf"; + // String pdfFilePath = "http://121.40.189.20:9000/API/uploadPath/upload/2023/11/14/ca2ca4697e5449ff9b9d23f95b221f58.pdf"; + String pdfFilePath ="D:/home/unzip/b92a7291-441e-4fad-95b4-7305f206eabd/仲裁材料/二、案件基本材料/2-1 仲裁申请书.pdf"; + try{ + // 读取文件内容到字节数组 + byte[] fileBytes = readFileToBytes(pdfFilePath); + // 将字节数组转换为Base64值 + String base64String = encodeBytesToBase64(fileBytes); + + // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 + // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 + // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 + Credential cred = new Credential(SECRET_ID, SECRET_KEY); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("ocr.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + SmartStructuralOCRV2Request req = new SmartStructuralOCRV2Request(); + req.setImageBase64(base64String); + req.setIsPdf(true); + req.setPdfPageNumber(1L); + String[] itemNames1 = {"申请人", "统一社会信用代码", "负责人", "住所", "联系地址" + , "委托代理人", "联系电话", "电子邮件", "被申请人", "居民身份证号码", "仲裁请求", "事实和理由"}; + req.setItemNames(itemNames1); + // 返回的resp是一个SmartStructuralOCRV2Response的实例,与请求对象对应 + SmartStructuralOCRV2Response resp = client.SmartStructuralOCRV2(req); + + + //解析数据 + String s = SmartStructuralOCRV2Response.toJsonString(resp); + // 解析JSON数据 + JSONObject jsonObject = new JSONObject(s); + JSONArray structuralList = jsonObject.getJSONArray("StructuralList"); + // 遍历StructuralList中的Groups,获取Key对应的AutoName和Value对应的AutoContent + StringBuilder stringBuilder = new StringBuilder(); // 创建一个StringBuilder对象 + for (int i = 0; i < structuralList.length(); i++) { + JSONArray groups = structuralList.getJSONObject(i).getJSONArray("Groups"); + for (int j = 0; j < groups.length(); j++) { + JSONArray lines = groups.getJSONObject(j).getJSONArray("Lines"); + for (int k = 0; k < lines.length(); k++) { + JSONObject line = lines.getJSONObject(k); + JSONObject key = line.getJSONObject("Key"); + JSONObject value = line.getJSONObject("Value"); + String autoName = key.getString("AutoName"); + String autoContent = value.getString("AutoContent"); + String text = autoName + ":" + autoContent; + if (stringBuilder.length() > 0) { + stringBuilder.append(","); // 在已有内容的情况下添加逗号分隔符 + } + stringBuilder.append(text); // 拼接当前的字符串 + } + } + } + System.out.println("stringBuilder======"+stringBuilder.toString()); + // 将字符串按逗号分隔符切割 + String[] fields = stringBuilder.toString().split(","); + Map> map = new HashMap<>(); + for (String field : fields) { + // 对于每个字段,再按冒号分隔符拆分出键和值 + String[] keyValue = field.split(":"); + if (keyValue.length == 2) { // 对于合法的键值对,将其添加到JSON对象中 + String key = keyValue[0]; + String value = keyValue[1]; + // 判断Map中是否已存在该键 + if (map.containsKey(key)) { + // 如果已存在,获取该键对应的值,并将新的值添加到集合中 + List values = map.get(key); + values.add(value); + } else { + // 如果不存在,创建一个新的集合,并将值添加到集合中 + List values = new ArrayList<>(); + values.add(value); + map.put(key, values); + } + } + } + System.out.println(map); + } catch (Exception e) { + System.out.println(e.toString()); + } + + } + private static byte[] readFileToBytes(String filePath) throws IOException { + File file = new File(filePath); + FileInputStream fileInputStream = new FileInputStream(file); + byte[] fileBytes = new byte[(int) file.length()]; + fileInputStream.read(fileBytes); + fileInputStream.close(); + return fileBytes; + } + + private static String encodeBytesToBase64(byte[] bytes) { + return Base64.getEncoder().encodeToString(bytes); + } +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/UnZipFileUtils.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/UnZipFileUtils.java new file mode 100644 index 0000000..3a6877d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/UnZipFileUtils.java @@ -0,0 +1,94 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +@Slf4j +public class UnZipFileUtils { + + public static void main(String[] args) { + File file = new File("D:\\home\\ruoyi\\仲裁委项目-测试单.zip"); + String targetPath = "D:\\home\\unzip\\"; + unZipFile(file,targetPath); + } + + public static boolean unZipFile(File aboriginalFile, String targetPath) { + if (!aboriginalFile.exists()) { + log.error("此文件不存在:", aboriginalFile.getPath()); + return false; + } + try { + ZipFile srcZipFile = new ZipFile(aboriginalFile, Charset.forName("GBK")); + for (Enumeration enumeration = srcZipFile.entries(); enumeration.hasMoreElements(); ) { + ZipEntry entryZip = (ZipEntry) enumeration.nextElement(); + //若是文件夹,就创建文件夹 + if (entryZip.isDirectory()) { + String directPath = targetPath + File.separator + entryZip.getName(); + File directFile = new File(directPath); + boolean makeDirs = directFile.mkdirs(); + System.out.println("创建文件夹是否成功:" + makeDirs); + } else { + //若是文件,就创建文件 + File sourceFile = new File(targetPath + File.separator + entryZip.getName()); + if (!sourceFile.getParentFile().exists()) { + boolean mDirect = sourceFile.getParentFile().mkdirs(); + System.out.println("创建压缩文件时,创建父文件夹是否成功:" + mDirect); + } + boolean newUnZipFile = sourceFile.createNewFile(); + if (newUnZipFile) { + // 将压缩文件内容写入到这个文件中 + try { + InputStream is = srcZipFile.getInputStream(entryZip); + FileOutputStream fos = new FileOutputStream(sourceFile); + int len; + byte[] buf = new byte[2048]; + while ((len = is.read(buf)) != -1) { + fos.write(buf, 0, len); + } + } catch (Exception e) { + log.error("解压失败", e); + } + } + } + } + return true; + + } catch (IOException e) { + log.error("解压失败", e); + return false; + } + + } + + + public static void getFiles(File fileSource, List allFiles) { + if (!fileSource.exists()) { + System.out.println("目录不存在"); + return; + } + File[] fileArray = fileSource.listFiles(); + if (fileArray != null && fileArray.length > 0) { + for (File fileIter : fileArray) { + if (fileIter.isDirectory()) { + getFiles(fileIter, allFiles); + } else { + allFiles.add(fileIter); + } + + } + + } + } + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ZipFileUtils.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ZipFileUtils.java new file mode 100644 index 0000000..18e8d69 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/utils/ZipFileUtils.java @@ -0,0 +1,48 @@ +package com.ruoyi.wisdomarbitrate.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipFileUtils { + + public static void main(String[] args) { + String file1 = "F:\\testZip\\123.pdf"; + String file2 = "F:\\testZip\\456.png"; + String zipFileOutPath = "F:\\testZip\\outputfile123.zip"; + + try { + FileOutputStream zfous = new FileOutputStream(zipFileOutPath); + ZipOutputStream zipFileOutstream = new ZipOutputStream(zfous); + FileInputStream fis1 = new FileInputStream(file1); + FileInputStream fis2 = new FileInputStream(file2); + zipFile(file1, fis1, zipFileOutstream); + zipFile(file2, fis2, zipFileOutstream); + + zipFileOutstream.close(); + zfous.close(); + System.out.println("文件成功打包成ZIP文件!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void zipFile(String zipfilePath, FileInputStream zipFileinsteam, ZipOutputStream zipfileOut) + throws IOException { + ZipEntry zipfileEntry = new ZipEntry(new File(zipfilePath).getName()); + zipfileOut.putNextEntry(zipfileEntry); + + // 从输入流读取数据并写入ZIP文件 + byte[] bytes = new byte[1024]; + int length; + while ((length = zipFileinsteam.read(bytes)) >= 0) { + zipfileOut.write(bytes, 0, length); + } + zipfileOut.closeEntry(); + zipFileinsteam.close(); + } +} diff --git a/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml new file mode 100644 index 0000000..ca39f47 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml new file mode 100644 index 0000000..588b191 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.dept_type,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, + dept_type, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values( + #{deptId}, + #{parentId}, + #{deptName}, + #{deptType}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate() + ); + + + insert into sys_dept( + dept_id, + parent_id, + dept_name, + dept_type, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values + + ( + #{item.deptId}, + #{item.parentId}, + #{item.deptName}, + #{item.deptType}, + #{item.ancestors}, + #{item.orderNum}, + #{item.leader}, + #{item.phone}, + #{item.email}, + #{item.status}, + #{item.createBy}, + sysdate() + ) + ; + + + + + update sys_dept + + parent_id = #{parentId}, + dept_name = #{deptName}, + dept_type = #{deptType}, + 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/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml new file mode 100644 index 0000000..8da9030 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml new file mode 100644 index 0000000..55b4075 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + 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/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml new file mode 100644 index 0000000..822d665 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml new file mode 100644 index 0000000..6762007 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml new file mode 100644 index 0000000..65d3079 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml new file mode 100644 index 0000000..96bc621 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml new file mode 100644 index 0000000..99f37ce --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark + from sys_post + + + + + + + + + + + + + + + + + + + + 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() + ) + + + + delete from sys_post where post_id = #{postId} + + + + delete from sys_post where post_id in + + #{postId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml new file mode 100644 index 0000000..7c4139b --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml new file mode 100644 index 0000000..783f153 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + 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/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml new file mode 100644 index 0000000..cb60a85 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml new file mode 100644 index 0000000..20cdafe --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, 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.ancestors, 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,u.id_card + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + id_card, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{idCard}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + sysdate() + ) + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + id_card, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + create_time + )values + + ( + #{item.userId}, + #{item.deptId}, + #{item.userName}, + #{item.nickName}, + #{item.idCard}, + #{item.email}, + #{item.avatar}, + #{item.phonenumber}, + #{item.sex}, + #{item.password}, + #{item.status}, + #{item.createBy}, + #{item.remark}, + sysdate() + ) + ; + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + id_card = #{idCard}, + 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 = sysdate() + + 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} + + + + update sys_user set del_flag = '2' where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml new file mode 100644 index 0000000..2b90bc4 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..dd72689 --- /dev/null +++ b/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/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitrateRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitrateRecordMapper.xml new file mode 100644 index 0000000..7947701 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitrateRecordMapper.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + insert into arbitrate_record( + case_appli_id, + eviden_determi, + fact_determi, + case_sketch, + ruling_follows, + verifica_opinion, + arbitrate_think, + + check_opinion, + case_check_reject, + arbitrate_reject, + create_by, + case_focus, + case_facts, + respondent_opinion, + applicant_opinion, + create_time + )values( + #{caseAppliId}, + #{evidenDetermi}, + #{factDetermi}, + #{caseSketch}, + #{rulingFollows}, + #{verificaOpinion}, + #{arbitrateThink}, + #{checkOpinion}, + #{caseCheckReject}, + #{arbitrateReject}, + #{createBy}, + #{caseFocus}, + #{caseFacts}, + #{respondentOpinion}, + #{applicantOpinion}, + sysdate() + ) + + + + + update arbitrate_record + + eviden_determi = #{evidenDetermi}, + fact_determi = #{factDetermi}, + case_sketch = #{caseSketch}, + arbitrate_think = #{arbitrateThink}, + ruling_follows = #{rulingFollows}, + verifica_opinion = #{verificaOpinion}, + check_opinion = #{checkOpinion}, + arbitra_check_opinion = #{arbitraCheckOpinion}, + annex_id = #{annexId}, + update_by = #{updateBy}, + case_focus = #{caseFocus}, + case_facts = #{caseFacts}, + respondent_opinion = #{respondentOpinion}, + applicant_opinion = #{applicantOpinion}, + case_check_reject = #{caseCheckReject}, + arbitrate_reject = #{arbitrateReject}, + deptor_reject = #{deptorReject}, + update_time = sysdate() + + where id = #{id} + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitratorMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitratorMapper.xml new file mode 100644 index 0000000..e394d00 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ArbitratorMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateLogMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateLogMapper.xml new file mode 100644 index 0000000..6c8dab1 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateLogMapper.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into case_affiliate_log(case_appli_log_id, identity_type,application_organ_id,application_organ_name,name,identity_num,contact_telphone, + contact_address,work_address,work_telphone ,name_agent,identity_num_agent,contact_telphone_agent, + comp_legal_person,comp_legalper_post,respon_sex ,respon_birth, + residen_affili,appli_agent_title, + contact_address_agent,email , send_email,track_num,applicant_agent_user_id,agent_email) values + + (#{item.caseAppliLogId},#{item.identityType},#{item.applicationOrganId},#{item.applicationOrganName},#{item.name},#{item.identityNum},#{item.contactTelphone}, + #{item.contactAddress},#{item.workAddress},#{item.workTelphone}, #{item.nameAgent},#{item.identityNumAgent},#{item.contactTelphoneAgent}, + #{item.compLegalPerson},#{item.compLegalperPost},#{item.responSex}, #{item.responBirth}, + #{item.residenAffili},#{item.appliAgentTitle}, + #{item.contactAddressAgent}, + #{item.email}, + #{item.sendEmail}, + #{item.trackNum}, + #{item.applicantAgentUserId}, + #{item.agentEmail} + ) + ; + + + + + + update case_affiliate_log + set + case_appli_log_id=#{caseAppliLogId}, + identity_type= #{identityType}, + application_organ_id= #{applicationOrganId}, + application_organ_name= #{applicationOrganName}, + name = #{name}, + identity_num = #{identityNum}, + contact_telphone = #{contactTelphone}, + contact_address = #{contactAddress}, + work_address = #{workAddress}, + work_telphone = #{workTelphone}, + + name_agent = #{nameAgent}, + identity_num_agent = #{identityNumAgent}, + contact_telphone_agent = #{contactTelphoneAgent}, + contact_address_agent = #{contactAddressAgent}, + send_email = #{sendEmail}, + residen_affili = #{residenAffili}, + email= #{email}, + track_num = #{trackNum}, + comp_legal_person=#{compLegalPerson}, + comp_legalper_post=#{compLegalperPost}, + applicant_agent_user_id=#{applicantAgentUserId}, + respon_sex=#{responSex}, + respon_birth=#{responBirth}, + residen_affili=#{residenAffili}, + appli_agent_title=#{appliAgentTitle} + + + ,agent_email=#{agentEmail} + + where id = #{id} + + + + + delete from case_affiliate_log where case_appli_log_id = #{caseAppliLogId} + + + + delete from case_affiliate_log where case_appli_log_id in + + #{item} + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateMapper.xml new file mode 100644 index 0000000..1a29b3f --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAffiliateMapper.xml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into case_affiliate(case_appli_id, identity_type,application_organ_id,application_organ_name,name,identity_num,contact_telphone, + contact_address,work_address,work_telphone ,name_agent,identity_num_agent,contact_telphone_agent, + comp_legal_person,comp_legalper_post,respon_sex ,respon_birth, + residen_affili,appli_agent_title, + contact_address_agent,email, send_email,track_num,applicant_agent_user_id,agent_email) values + + (#{item.caseAppliId},#{item.identityType},#{item.applicationOrganId},#{item.applicationOrganName},#{item.name},#{item.identityNum},#{item.contactTelphone}, + #{item.contactAddress},#{item.workAddress},#{item.workTelphone}, #{item.nameAgent},#{item.identityNumAgent},#{item.contactTelphoneAgent}, + #{item.compLegalPerson},#{item.compLegalperPost},#{item.responSex}, #{item.responBirth}, + #{item.residenAffili},#{item.appliAgentTitle}, + #{item.contactAddressAgent}, + #{item.email}, + #{item.sendEmail}, + #{item.trackNum}, + #{item.applicantAgentUserId}, + #{item.agentEmail} + ) + + + + + + + update case_affiliate + set + case_appli_id=#{caseAppliId}, + identity_type= #{identityType}, + application_organ_id= #{applicationOrganId}, + application_organ_name= #{applicationOrganName}, + name = #{name}, + identity_num = #{identityNum}, + contact_telphone = #{contactTelphone}, + contact_address = #{contactAddress}, + work_address = #{workAddress}, + work_telphone = #{workTelphone}, + name_agent = #{nameAgent}, + identity_num_agent = #{identityNumAgent}, + contact_telphone_agent = #{contactTelphoneAgent}, + contact_address_agent = #{contactAddressAgent}, + send_email = #{sendEmail}, + residen_affili = #{residenAffili}, + email= #{email}, + track_num = #{trackNum}, + comp_legal_person=#{compLegalPerson}, + comp_legalper_post=#{compLegalperPost}, + applicant_agent_user_id=#{applicantAgentUserId}, + respon_sex=#{responSex}, + respon_birth=#{responBirth}, + residen_affili=#{residenAffili}, + appli_agent_title=#{appliAgentTitle} + + + ,agent_email=#{agentEmail} + + where id = #{id} + + + + + + update case_affiliate + + + application_organ_id= #{item.applicationOrganId}, + application_organ_name= #{item.applicationOrganName}, + name = #{item.name}, + identity_num = #{item.identityNum}, + contact_telphone = #{item.contactTelphone}, + contact_address = #{item.contactAddress}, + work_address = #{item.workAddress}, + work_telphone = #{item.workTelphone}, + + name_agent = #{item.nameAgent}, + identity_num_agent = #{item.identityNumAgent}, + contact_telphone_agent = #{item.contactTelphoneAgent}, + contact_address_agent = #{item.contactAddressAgent}, + send_email = #{item.sendEmail}, + residen_affili = #{item.residenAffili}, + email= #{item.email}, + track_num = #{item.trackNum}, + comp_legal_person=#{item.compLegalPerson}, + comp_legalper_post=#{item.compLegalperPost}, + applicant_agent_user_id=#{item.applicantAgentUserId}, + respon_sex=#{item.responSex}, + respon_birth=#{item.responBirth}, + residen_affili=#{item.residenAffili}, + appli_agent_title=#{item.appliAgentTitle} + + + ,agent_email=#{agentEmail} + + + where case_appli_id = #{caseAppliId} and identity_type= #{item.identityType}; + + + + + delete from case_affiliate where case_appli_id = #{id} + + + + delete from case_affiliate where case_appli_id in + + #{item} + + + + delete from case_affiliate where case_appli_id = #{caseAppliId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationLogMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationLogMapper.xml new file mode 100644 index 0000000..5aca5c5 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationLogMapper.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into case_application_log( + id , + case_appli_id , + case_name , + case_num, + case_subject_amount, + + arbitrat_claims, + request_rule, + loan_start_date, + loan_end_date, + claim_princi_owed, + + claim_interest_owed, + claim_liquid_damag, + fee_payable, + contract_number, + create_by, + version, + update_submit_status, + proper_preser, + interest_rate, + outstanding_money, + facts, + party_a, + disputes, + loan_type, + loan_term, + mediation_agreement, + create_time + )values( + #{id} , + #{caseAppliId}, + #{caseName}, + #{caseNum}, + #{caseSubjectAmount}, + + #{arbitratClaims}, + #{requestRule}, + #{loanStartDate}, + #{loanEndDate}, + #{claimPrinciOwed}, + + #{claimInterestOwed}, + #{claimLiquidDamag}, + #{feePayable}, + #{contractNumber}, + #{createBy}, + #{version}, + #{updateSubmitStatus}, + #{properPreser}, + #{interestRate}, + #{outstandingMoney}, + #{facts}, + #{partyA}, + #{disputes}, + #{loanType}, + #{loanTerm}, + #{mediationAgreement}, + sysdate() + ) + + + insert into case_application_log( + id, + case_appli_id , + case_name , + case_num, + case_subject_amount, + arbitrat_claims, + request_rule, + loan_start_date, + loan_end_date, + claim_princi_owed, + claim_interest_owed, + claim_liquid_damag, + fee_payable, + contract_number, + create_by, + version, + update_submit_status, + proper_preser, + interest_rate, + outstanding_money, + facts, + party_a, + disputes, + loan_type, + loan_term, + mediation_agreement, + create_time + )values + + ( + id=#{item.id}, + #{item.caseAppliId}, + #{item.caseName}, + #{item.caseNum}, + #{item.caseSubjectAmount}, + #{item.arbitratClaims}, + #{item.requestRule}, + #{item.loanStartDate}, + #{item.loanEndDate}, + #{item.claimPrinciOwed}, + #{item.claimInterestOwed}, + #{item.claimLiquidDamag}, + #{item.feePayable}, + #{item.contractNumber}, + #{item.createBy}, + #{item.version}, + #{item.updateSubmitStatus}, + #{item.properPreser}, + #{item.interestRate}, + #{item.outstandingMoney}, + #{item.facts}, + #{item.partyA}, + #{item.disputes}, + #{item.loanType}, + #{item.loanTerm}, + #{item.mediationAgreement}, + sysdate() + ) + + + + update case_application_log + + + update_submit_status=#{updateSubmitStatus}, + + + + AND case_appli_id=#{caseId} + AND version=#{version} + + + + + + DELETE FROM case_application_log + WHERE id = #{id} + + + + delete from case_application_log l where l.id in + + #{item} + + ; + delete from case_affiliate_log l where l.case_appli_log_id in + + #{item} + + ; + delete from case_attach_log l where l.case_appli_log_id in + + #{item} + + ; + delete from column_value_log l where l.case_appli_log_id in + + #{item} + + ; + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml new file mode 100644 index 0000000..71c28e9 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml @@ -0,0 +1,1377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into case_application( + id , + case_name , + case_num, + case_subject_amount, + register_date, + arbitrat_method, + case_status, + hear_date, + arbitrat_claims, + request_rule, + loan_start_date, + loan_end_date, + claim_princi_owed, + + claim_interest_owed, + claim_liquid_damag, + fee_payable, + begin_video_date, + online_video_person, + + contract_number, + + adjudica_counter, + proper_preser, + + create_by, + import_flag, + version, + template_id, + facts, + mediation_agreement, + batch_number, + create_time + )values( + #{id} , + #{caseName}, + #{caseNum}, + #{caseSubjectAmount}, + sysdate(), + #{arbitratMethod}, + #{caseStatus}, + #{hearDate}, + #{arbitratClaims}, + #{requestRule}, + #{loanStartDate}, + #{loanEndDate}, + #{claimPrinciOwed}, + + #{claimInterestOwed}, + #{claimLiquidDamag}, + #{feePayable}, + #{beginVideoDate}, + #{onlineVideoPerson}, + + #{contractNumber}, + + #{adjudicaCounter}, + #{properPreser}, + + #{createBy}, + #{importFlag}, + #{version}, + #{templateId}, + + #{facts}, + #{mediationAgreement}, + #{batchNumber}, + sysdate() + ) + + + insert into case_application( + id, + case_name , + case_num, + case_subject_amount, + register_date, + arbitrat_method, + case_status, + hear_date, + arbitrat_claims, + request_rule, + loan_start_date, + loan_end_date, + claim_princi_owed, + + claim_interest_owed, + claim_liquid_damag, + fee_payable, + begin_video_date, + online_video_person, + + contract_number, + + adjudica_counter, + proper_preser, + + create_by, + import_flag, + version, + template_id, + facts, + mediation_agreement, + batch_number, + create_time + )values + + ( + #{item.id}, + #{item.caseName}, + #{item.caseNum}, + #{item.caseSubjectAmount}, + sysdate(), + #{item.arbitratMethod}, + #{item.caseStatus}, + #{item.hearDate}, + #{item.arbitratClaims}, + #{item.requestRule}, + #{item.loanStartDate}, + #{item.loanEndDate}, + #{item.claimPrinciOwed}, + + #{item.claimInterestOwed}, + #{item.claimLiquidDamag}, + #{item.feePayable}, + #{item.beginVideoDate}, + #{item.onlineVideoPerson}, + + #{item.contractNumber}, + + #{item.adjudicaCounter}, + #{item.properPreser}, + + #{item.createBy}, + #{item.importFlag}, + #{item.version}, + #{item.templateId}, + + #{item.facts}, + #{item.mediationAgreement}, + #{item.batchNumber}, + sysdate() + ) + ; + + + + update case_application + + case_subject_amount = #{caseSubjectAmount}, + register_date = #{registerDate}, + arbitrat_method = #{arbitratMethod}, + hear_date = #{hearDate}, + arbitrat_claims = #{arbitratClaims}, + request_rule = #{requestRule}, + loan_start_date = #{loanStartDate}, + loan_end_date = #{loanEndDate}, + claim_princi_owed = #{claimPrinciOwed}, + claim_interest_owed = #{claimInterestOwed}, + claim_liquid_damag = #{claimLiquidDamag}, + fee_payable = #{feePayable}, + begin_video_date = #{beginVideoDate}, + online_video_person = + #{onlineVideoPerson}, + + + contract_number = #{contractNumber}, + + case_name = #{caseName}, + case_describe = #{caseDescribe}, + case_result = #{caseResult}, + case_status = #{caseStatus}, + proper_preser = #{properPreser}, + + appli_iswrit_hear = #{applicantIsWrittenHear}, + respon_isWrit_hear = #{respondentIsWrittenHear}, + + update_by = #{updateBy}, + case_num = #{caseNum}, + version = #{version}, + facts = #{facts}, + mediation_agreement = + #{mediationAgreement}, + + update_time = sysdate() + + where id = #{id} + + + + update case_application + + case_status = #{caseStatus}, + arbitrator_id = #{arbitratorId}, + arbitrator_name = #{arbitratorName}, + pending_appoint_arbotrar = #{pendingAppointArbotrar}, + arbitrat_method = #{arbitratMethod}, + case_name = #{caseName}, + case_describe = #{caseDescribe}, + case_result = #{caseResult}, + is_agree_pend_tral = #{isAgreePendTral}, + adjudica_counter = #{adjudicaCounter}, + objecti_juris = #{objectiJuris}, + + is_absence = #{isAbsence}, + appli_is_absen = #{appliIsAbsen}, + respon_cross_opin = #{responCrossOpin}, + applica_cross_opin = #{applicaCrossOpin}, + + respon_defen_opini = #{responDefenOpini}, + + objection_add_eviden = #{objectionAddEviden}, + open_court_hear = #{openCourtHear}, + respon_isWrit_hear = #{respondentIsWrittenHear}, + hear_date = #{hearDate}, + filearbitra_url = #{filearbitraUrl}, + adjudica_counter_reason = + #{adjudicaCounterReason}, + + + where id = #{id} + + + update case_application set pay_type=#{payType} where id in + + #{caseId} + + + + update case_application set lock_status=#{lockStatus} where id = #{id} + + + update case_application set room_id=#{roomId} where id = #{caseId} + + + + + update case_application set version = #{version} where id = #{id} + + + + delete from case_application where id = #{id} + + + delete from case_application + where id in + + #{item} + ; + delete from case_affiliate + where case_appli_id in + + #{item} + ; + delete from case_attach + where case_appli_id in + + #{item} + ; + delete from column_value + where case_id in + + #{item} + ; + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachLogMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachLogMapper.xml new file mode 100644 index 0000000..fc95fc3 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachLogMapper.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + INSERT INTO case_attach_log (case_appli_log_id, annex_id,annex_name, annex_path , annex_type,note,use_id,use_account,seal_status) + VALUES (#{caseAppliLogId},#{annexId}, #{annexName}, #{annexPath},#{annexType},#{note},#{userId},#{userName},#{sealStatus}) + + + INSERT INTO case_attach_log (case_appli_log_id, annex_id,annex_name, annex_path , annex_type,note,use_id,use_account,seal_status) + VALUES + + (#{item.caseAppliLogId},#{item.annexId}, #{item.annexName}, #{item.annexPath},#{item.annexType},#{item.note},#{item.userId},#{item.userName},#{item.sealStatus}) + + + + delete from case_attach_log + where annex_id in + + #{id} + + + + + + + + + + + + update case_attach_log + set + case_appli_log_id= #{caseAppliLogId} + where annex_id = #{annexId} + + + + update case_attach_log + + annex_name = #{annexName}, + annex_path = #{annexPath} + + + + AND case_appli_log_id = #{caseAppliLogId} + + + AND annex_type = #{annexType} + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml new file mode 100644 index 0000000..af5aa3a --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + INSERT INTO case_attach (case_appli_id, annex_name, annex_path , annex_type,note,use_id,use_account,seal_status,is_batch_upload) + VALUES (#{caseAppliId}, #{annexName}, #{annexPath},#{annexType},#{note},#{userId},#{userName},#{sealStatus},#{isBatchUpload}) + + + INSERT INTO case_attach (case_appli_id, annex_name, annex_path , annex_type,note,use_id,use_account,seal_status,is_batch_upload) + VALUES + + + + (#{item.caseAppliId}, #{item.annexName}, #{item.annexPath},#{item.annexType},#{item.note},#{item.userId},#{item.userName},#{item.sealStatus},#{item.isBatchUpload}) + + + + delete from case_attach + where annex_id in + + #{id} + + + + delete from case_attach + where case_appli_id = #{caseAppliId} + and annex_type = #{annexType} + + AND is_batch_upload = #{isBatchUpload} + + + + + + + + + delete from case_attach + where case_appli_id = #{caseAppliId} + and annex_type = #{annexType} + + + + + + + update case_attach + set + case_appli_id= #{caseAppliId} + where annex_id = #{annexId} + + + + update case_attach + + annex_name = #{annexName}, + annex_path = #{annexPath} + + + + AND case_appli_id = #{caseAppliId} + + + AND annex_type = #{annexType} + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceDirectoryMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceDirectoryMapper.xml new file mode 100644 index 0000000..7f01efb --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceDirectoryMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + insert into case_evidence_directory( + parent_id, + evidence_name, + annex_id, + series, + case_appli_id, + create_by, + create_time + )values( + #{parentId}, + #{evidenceName}, + #{annexId}, + #{series}, + #{caseId}, + #{createBy}, + sysdate() + ) + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml new file mode 100644 index 0000000..445d757 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseLogRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseLogRecordMapper.xml new file mode 100644 index 0000000..817be20 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseLogRecordMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + insert into case_log_record(case_appli_id, case_node,case_node_time,notes,create_by,create_nick_name,create_time,update_by,update_time ) values( + #{caseAppliId},#{caseNode},sysdate(),#{notes},#{createBy},#{createNickName},sysdate(),#{updateBy},sysdate() + ) + + + insert into case_log_record(case_appli_id, case_node,case_node_time,notes,create_by,create_nick_name,create_time,update_by,update_time ) values + + ( + #{item.caseAppliId},#{item.caseNode},sysdate(),#{item.notes},#{item.createBy},#{item.createNickName},sysdate(),#{item.updateBy},sysdate() + ) + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseNumRuleMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseNumRuleMapper.xml new file mode 100644 index 0000000..ff63487 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseNumRuleMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + insert into case_num_rule( + rule_type, + prefixstr, + date_format, + dept_name, + current_num, + dept_name_firchar, + create_by, + create_time + )values( + #{ruleType}, + #{prefixstr}, + #{dateFormat}, + #{deptName}, + #{currentNum}, + #{deptNameFirchar}, + #{createBy}, + sysdate() + ) + + + + update case_num_rule + + rule_type = #{ruleType}, + prefixstr = #{prefixstr}, + date_format = #{dateFormat}, + dept_name = #{deptName}, + current_num = #{currentNum}, + dept_name_firchar = #{deptNameFirchar}, + + + + AND id = #{id} + + + + + delete from case_num_rule where id = #{id} + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml new file mode 100644 index 0000000..b7ca892 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + INSERT INTO case_payment_record (case_id, order_number, payment_status , create_time) + VALUES (#{caseId}, #{orderNumber}, #{paymentStatus},#{createTime}) + + + update case_payment_record + + case_id= #{caseId}, + order_number = #{orderNumber}, + payment_time = #{paymentTime}, + payment_status = #{paymentStatus}, + update_time = #{updateTime}, + pay_type = #{payType}, + + + + AND case_id = #{caseId} + + + AND id = #{id} + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueLogMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueLogMapper.xml new file mode 100644 index 0000000..661195d --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueLogMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + INSERT INTO column_value_log ( `COLUMN`, `NAME`, `VALUE`, case_appli_log_id,is_default ) + values + + + (#{item.column},#{item.name},#{item.value},#{item.caseAppliLogId},#{item.isDefault}) + + + + + + update column_value_log + + + `VALUE` = #{item.value}, + + `id`=#{item.id} + + where `COLUMN`=#{item.column} and `NAME`=#{item.name} and case_appli_log_id=#{item.caseAppliLogId}; + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueMapper.xml new file mode 100644 index 0000000..3ee2dfa --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ColumnValueMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + INSERT INTO column_value ( `COLUMN`, `NAME`, `VALUE`, case_id,is_default ) + values + + + (#{item.column},#{item.name},#{item.value},#{item.caseId},#{item.isDefault}) + + + + + update column_value + + + `VALUE` = #{item.value}, + + + where id=#{item.id}; + + + + + update column_value + + + `VALUE` = #{value}, + + + where id=#{id} + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/DeptIdentifyMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/DeptIdentifyMapper.xml new file mode 100644 index 0000000..3d5e2c0 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/DeptIdentifyMapper.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into dept_identify( + identify_name, + identify_status, + identify_date, + is_use, + org_id, + oper_name, + oper_phone, + identify_type, + auth_flow_id, + credit_code, + legal_per_name, + legal_per_phone, + identify_email, + dept_id, + user_id, + del_flag + )values( + #{identifyName}, + #{identifyStatus}, + #{identifyDate}, + #{isUse}, + #{orgId}, + #{operName}, + #{operPhone}, + #{identifyType}, + #{authFlowId}, + #{creditCode}, + #{legalPerName}, + #{legalPerPhone}, + #{identifyEmail}, + #{deptId}, + #{userId}, + 0 + ) + + + + + + + + + update dept_identify + + identify_date = #{identifyDate}, + identify_name = #{identifyName}, + is_use = #{isUse}, + identify_status = #{identifyStatus}, + org_id = #{orgId}, + del_flag = #{delFlag}, + oper_name = #{operName}, + oper_phone = #{operPhone}, + credit_code = #{creditCode}, + legal_per_name = #{legalPerName}, + legal_per_phone = #{legalPerPhone}, + identify_email = #{identifyEmail}, + user_id = #{userId}, + auth_flow_id = #{authFlowId} + + + + + AND id = #{id} + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/FatchRuleMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/FatchRuleMapper.xml new file mode 100644 index 0000000..4cf1072 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/FatchRuleMapper.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + delete from fatch_rule where id in + + #{item} + + + + + insert into fatch_rule( + file_name, + start_content, + end_content, + `column`, + `column_name`, + is_default, + start_content_repeat_order,end_content_repeat_order,fatch_order + )values( + #{fileName}, + #{startContent}, + #{endContent}, + #{column}, + #{columnName}, + #{isDefault}, + #{startContentRepeatOrder},#{endContentRepeatOrder},#{fatchOrder} + ) + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/IdentityAuthenticationMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/IdentityAuthenticationMapper.xml new file mode 100644 index 0000000..6a6d971 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/IdentityAuthenticationMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + insert into identi_authenti( + user_id, + id_address, + name, + identity_no, + certification_time, + certification_status, + user_name, + create_by, + create_time + )values( + #{userId}, + #{idAddress}, + #{name}, + #{identityNo}, + sysdate(), + #{certificationStatus}, + #{userName}, + #{createBy}, + sysdate() + ) + + + update identi_authenti + + user_id = #{userId}, + user_name = #{userName}, + identity_no = #{identityNo}, + update_by = #{updateBy}, + update_time = sysdate() + + where id = #{id} + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ReservedConferenceMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ReservedConferenceMapper.xml new file mode 100644 index 0000000..ae199f6 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/ReservedConferenceMapper.xml @@ -0,0 +1,37 @@ + + + + + + insert into reserved_conference( + case_id, + room_id, + schedule_start_time, + schedule_end_time, + user_id + )values( + #{caseId}, + #{roomId}, + #{scheduleStartTime}, + #{scheduleEndTime}, + #{userId} + ) + + + delete from reserved_conference where room_id=#{roomId} + + + delete from reserved_conference where id in + + #{item} + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealManageMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealManageMapper.xml new file mode 100644 index 0000000..a801287 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealManageMapper.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + insert into seal_manage( + identify_id, + seal_name, + seal_id, + annex_id, + seal_status, + is_use + )values( + #{identifyId}, + #{sealName}, + #{sealId}, + #{annexId}, + #{sealStatus}, + #{isUse} + ) + + + + update seal_manage + + identify_id = #{identifyId}, + seal_name = #{sealName}, + seal_id = #{sealId}, + annex_id = #{annexId}, + seal_status = #{sealStatus}, + is_use = #{isUse} + + + + AND id = #{id} + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealSignRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealSignRecordMapper.xml new file mode 100644 index 0000000..0469fff --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SealSignRecordMapper.xml @@ -0,0 +1,95 @@ + + + + + + INSERT INTO seal_sign_record (file_id, file_name, sign_flow_id , penson_account + ,penson_name,orgnize_name,orgn_name_psn_acc,orgn_name_psn_name,position_pagepsn + ,position_xpsn,position_ypsn,position_pageorg,position_xorg,position_yorg,case_appli_id + ,sign_flow_status) + VALUES (#{fileid}, #{filename}, #{signFlowid},#{pensonAccount},#{pensonName},#{orgnizeName} + ,#{orgnizeNamePsnAccount},#{orgnizeNamepsnName},#{positionPagepsn},#{positionXpsn},#{positionYpsn} + ,#{positionPageorg},#{positionXorg},#{positionYorg},#{caseAppliId},#{signFlowStatus}) + + + + + + + + + + + + + + + + + + + + + + + + update seal_sign_record + + sign_flow_status = #{signFlowStatus}, + file_download_url = #{fileDownloadUrl} + + where id = #{id} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SendMailRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SendMailRecordMapper.xml new file mode 100644 index 0000000..b93e36d --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SendMailRecordMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + insert into send_mail_record( + mail_name, + mail_content, + mail_address, + send_time, + case_id, + send_status, + create_by, + create_time + )values( + #{mailName}, + #{mailContent}, + #{mailAddress}, + #{sendTime}, + #{caseId}, + #{sendStatus}, + #{createBy}, + sysdate() + ) + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SmsRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SmsRecordMapper.xml new file mode 100644 index 0000000..d2035ce --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/SmsRecordMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + insert into sms_send_record( + case_appli_id, + case_num, + phone, + send_time, + send_content, + create_by, + send_status, + create_time + )values( + #{caseId}, + #{caseNum}, + #{phone}, + #{sendTime}, + #{sendContent}, + #{createBy}, + #{sendStatus}, + sysdate() + ) + + + + insert into sms_send_record( + case_appli_id, + case_num, + phone, + send_time, + send_content, + create_by, + send_status, + create_time + )values + + ( + #{item.caseId}, + #{item.caseNum}, + #{item.phone}, + #{item.sendTime}, + #{item.sendContent}, + #{item.createBy}, + #{item.sendStatus}, + sysdate() + ) + + + + + + diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateFatchRuleMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateFatchRuleMapper.xml new file mode 100644 index 0000000..d243bde --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateFatchRuleMapper.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + delete from template_fatch_rule where template_id=#{id} + + + + insert into template_fatch_rule( + template_id, + fatch_rule_id + )values( + #{templateId}, + #{fatchRuleId} + ) + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManageMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManageMapper.xml new file mode 100644 index 0000000..33af308 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManageMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + insert into template_manage( + identify_id, + tem_name, + tem_type, + tem_format, + tem_orig_path, + tem_revis_path, + create_by, + file_name, + del_flag,create_time + )values( + #{identifyId}, + #{temName}, + #{temType}, + #{temFormat}, + #{temOrigPath}, + #{temRevisPath}, + #{createBy}, + #{fileName}, + 0,sysdate() + ) + + + + update template_manage + + identify_id = #{identifyId}, + tem_name = #{temName}, + tem_type = #{temType}, + tem_format = #{temFormat}, + tem_orig_path = #{temOrigPath}, + del_flag = #{delFlag}, + tem_revis_path = #{temRevisPath}, + update_by = #{updateBy}, + file_name = #{fileName}, + update_time = sysdate() + + + + AND id = #{id} + + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManualMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManualMapper.xml new file mode 100644 index 0000000..1bb2fd0 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/TemplateManualMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + insert into template_manual( + name, + content, + type, + del_flag + )values( + #{name}, + #{content}, + #{type}, + 0 + ) + + + + update template_manual + + name = #{name}, + content = #{content}, + type = #{type}, + del_flag = #{delFlag}, + + + + AND id = #{id} + + + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/WeChatUserMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/WeChatUserMapper.xml new file mode 100644 index 0000000..d15e498 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/WeChatUserMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + insert into identi_authenti( + name, + identity_no, + certification_time, + certification_status, + open_id, + create_by, + phone, + email, + create_time + + )values( + #{name}, + #{identityNo}, + sysdate(), + #{certificationStatus}, + #{openId}, + #{createBy}, + #{phone}, + #{email}, + sysdate() + ) + + + update identi_authenti + + phone = #{phone}, + email = #{email}, + update_by = #{updateBy}, + update_time = sysdate() + + where id = #{id} + + + + + + \ No newline at end of file diff --git a/sql/quartz.sql b/sql/quartz.sql new file mode 100644 index 0000000..6c50ee0 --- /dev/null +++ b/sql/quartz.sql @@ -0,0 +1,176 @@ +DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; +DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; +DROP TABLE IF EXISTS QRTZ_LOCKS; +DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; +DROP TABLE IF EXISTS QRTZ_CALENDARS; + +set names utf8; + +-- ---------------------------- +-- 1、存储每一个已配置的 jobDetail 的详细信息 +-- ---------------------------- +create table QRTZ_JOB_DETAILS ( + sched_name varchar(120) not null comment '调度名称', + job_name varchar(200) not null comment '任务名称', + job_group varchar(200) not null comment '任务组名', + description varchar(250) null comment '相关介绍', + job_class_name varchar(250) not null comment '执行任务类名称', + is_durable varchar(1) not null comment '是否持久化', + is_nonconcurrent varchar(1) not null comment '是否并发', + is_update_data varchar(1) not null comment '是否更新数据', + requests_recovery varchar(1) not null comment '是否接受恢复执行', + job_data blob null comment '存放持久化job对象', + primary key (sched_name, job_name, job_group) +) engine=innodb comment = '任务详细信息表'; + +-- ---------------------------- +-- 2、 存储已配置的 Trigger 的信息 +-- ---------------------------- +create table QRTZ_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment '触发器的名字', + trigger_group varchar(200) not null comment '触发器所属组的名字', + job_name varchar(200) not null comment 'qrtz_job_details表job_name的外键', + job_group varchar(200) not null comment 'qrtz_job_details表job_group的外键', + description varchar(250) null comment '相关介绍', + next_fire_time bigint(13) null comment '上一次触发时间(毫秒)', + prev_fire_time bigint(13) null comment '下一次触发时间(默认为-1表示不触发)', + priority integer null comment '优先级', + trigger_state varchar(16) not null comment '触发器状态', + trigger_type varchar(8) not null comment '触发器的类型', + start_time bigint(13) not null comment '开始时间', + end_time bigint(13) null comment '结束时间', + calendar_name varchar(200) null comment '日程表名称', + misfire_instr smallint(2) null comment '补偿执行的策略', + job_data blob null comment '存放持久化job对象', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, job_name, job_group) references QRTZ_JOB_DETAILS(sched_name, job_name, job_group) +) engine=innodb comment = '触发器详细信息表'; + +-- ---------------------------- +-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 +-- ---------------------------- +create table QRTZ_SIMPLE_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + repeat_count bigint(7) not null comment '重复的次数统计', + repeat_interval bigint(12) not null comment '重复的间隔时间', + times_triggered bigint(10) not null comment '已经触发的次数', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = '简单触发器的信息表'; + +-- ---------------------------- +-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 +-- ---------------------------- +create table QRTZ_CRON_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + cron_expression varchar(200) not null comment 'cron表达式', + time_zone_id varchar(80) comment '时区', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = 'Cron类型的触发器表'; + +-- ---------------------------- +-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) +-- ---------------------------- +create table QRTZ_BLOB_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + blob_data blob null comment '存放持久化Trigger对象', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = 'Blob类型的触发器表'; + +-- ---------------------------- +-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 +-- ---------------------------- +create table QRTZ_CALENDARS ( + sched_name varchar(120) not null comment '调度名称', + calendar_name varchar(200) not null comment '日历名称', + calendar blob not null comment '存放持久化calendar对象', + primary key (sched_name, calendar_name) +) engine=innodb comment = '日历信息表'; + +-- ---------------------------- +-- 7、 存储已暂停的 Trigger 组的信息 +-- ---------------------------- +create table QRTZ_PAUSED_TRIGGER_GRPS ( + sched_name varchar(120) not null comment '调度名称', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + primary key (sched_name, trigger_group) +) engine=innodb comment = '暂停的触发器表'; + +-- ---------------------------- +-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 +-- ---------------------------- +create table QRTZ_FIRED_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + entry_id varchar(95) not null comment '调度器实例id', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + instance_name varchar(200) not null comment '调度器实例名', + fired_time bigint(13) not null comment '触发的时间', + sched_time bigint(13) not null comment '定时器制定的时间', + priority integer not null comment '优先级', + state varchar(16) not null comment '状态', + job_name varchar(200) null comment '任务名称', + job_group varchar(200) null comment '任务组名', + is_nonconcurrent varchar(1) null comment '是否并发', + requests_recovery varchar(1) null comment '是否接受恢复执行', + primary key (sched_name, entry_id) +) engine=innodb comment = '已触发的触发器表'; + +-- ---------------------------- +-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 +-- ---------------------------- +create table QRTZ_SCHEDULER_STATE ( + sched_name varchar(120) not null comment '调度名称', + instance_name varchar(200) not null comment '实例名称', + last_checkin_time bigint(13) not null comment '上次检查时间', + checkin_interval bigint(13) not null comment '检查间隔时间', + primary key (sched_name, instance_name) +) engine=innodb comment = '调度器状态表'; + +-- ---------------------------- +-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) +-- ---------------------------- +create table QRTZ_LOCKS ( + sched_name varchar(120) not null comment '调度名称', + lock_name varchar(40) not null comment '悲观锁名称', + primary key (sched_name, lock_name) +) engine=innodb comment = '存储的悲观锁信息表'; + +-- ---------------------------- +-- 11、 Quartz集群实现同步机制的行锁表 +-- ---------------------------- +create table QRTZ_SIMPROP_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + str_prop_1 varchar(512) null comment 'String类型的trigger的第一个参数', + str_prop_2 varchar(512) null comment 'String类型的trigger的第二个参数', + str_prop_3 varchar(512) null comment 'String类型的trigger的第三个参数', + int_prop_1 int null comment 'int类型的trigger的第一个参数', + int_prop_2 int null comment 'int类型的trigger的第二个参数', + long_prop_1 bigint null comment 'long类型的trigger的第一个参数', + long_prop_2 bigint null comment 'long类型的trigger的第二个参数', + dec_prop_1 numeric(13,4) null comment 'decimal类型的trigger的第一个参数', + dec_prop_2 numeric(13,4) null comment 'decimal类型的trigger的第二个参数', + bool_prop_1 varchar(1) null comment 'Boolean类型的trigger的第一个参数', + bool_prop_2 varchar(1) null comment 'Boolean类型的trigger的第二个参数', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = '同步机制的行锁表'; + +commit; \ No newline at end of file diff --git a/sql/ry_20230706.sql b/sql/ry_20230706.sql new file mode 100644 index 0000000..17eec01 --- /dev/null +++ b/sql/ry_20230706.sql @@ -0,0 +1,699 @@ +-- ---------------------------- +-- 1、部门表 +-- ---------------------------- +drop table if exists sys_dept; +create table sys_dept ( + dept_id bigint(20) not null auto_increment comment '部门id', + parent_id bigint(20) default 0 comment '父部门id', + ancestors varchar(50) default '' comment '祖级列表', + dept_name varchar(30) default '' comment '部门名称', + order_num int(4) default 0 comment '显示顺序', + leader varchar(20) default null comment '负责人', + phone varchar(11) default null comment '联系电话', + email varchar(50) default null comment '邮箱', + status char(1) default '0' comment '部门状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + primary key (dept_id) +) engine=innodb auto_increment=200 comment = '部门表'; + +-- ---------------------------- +-- 初始化-部门表数据 +-- ---------------------------- +insert into sys_dept values(100, 0, '0', '若依科技', 0, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); + + +-- ---------------------------- +-- 2、用户信息表 +-- ---------------------------- +drop table if exists sys_user; +create table sys_user ( + user_id bigint(20) not null auto_increment comment '用户ID', + dept_id bigint(20) default null comment '部门ID', + user_name varchar(30) not null comment '用户账号', + nick_name varchar(30) not null comment '用户昵称', + user_type varchar(2) default '00' comment '用户类型(00系统用户)', + email varchar(50) default '' comment '用户邮箱', + phonenumber varchar(11) default '' comment '手机号码', + sex char(1) default '0' comment '用户性别(0男 1女 2未知)', + avatar varchar(100) default '' comment '头像地址', + password varchar(100) default '' comment '密码', + status char(1) default '0' comment '帐号状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + login_ip varchar(128) default '' comment '最后登录IP', + login_date datetime comment '最后登录时间', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (user_id) +) engine=innodb auto_increment=100 comment = '用户信息表'; + +-- ---------------------------- +-- 初始化-用户信息表数据 +-- ---------------------------- +insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员'); +insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员'); + + +-- ---------------------------- +-- 3、岗位信息表 +-- ---------------------------- +drop table if exists sys_post; +create table sys_post +( + post_id bigint(20) not null auto_increment comment '岗位ID', + post_code varchar(64) not null comment '岗位编码', + post_name varchar(50) not null comment '岗位名称', + post_sort int(4) not null comment '显示顺序', + status char(1) not null comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (post_id) +) engine=innodb comment = '岗位信息表'; + +-- ---------------------------- +-- 初始化-岗位信息表数据 +-- ---------------------------- +insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 4、角色信息表 +-- ---------------------------- +drop table if exists sys_role; +create table sys_role ( + role_id bigint(20) not null auto_increment comment '角色ID', + role_name varchar(30) not null comment '角色名称', + role_key varchar(100) not null comment '角色权限字符串', + role_sort int(4) not null comment '显示顺序', + data_scope char(1) default '1' comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', + dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示', + status char(1) not null comment '角色状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (role_id) +) engine=innodb auto_increment=100 comment = '角色信息表'; + +-- ---------------------------- +-- 初始化-角色信息表数据 +-- ---------------------------- +insert into sys_role values('1', '超级管理员', 'admin', 1, 1, 1, 1, '0', '0', 'admin', sysdate(), '', null, '超级管理员'); +insert into sys_role values('2', '普通角色', 'common', 2, 2, 1, 1, '0', '0', 'admin', sysdate(), '', null, '普通角色'); + + +-- ---------------------------- +-- 5、菜单权限表 +-- ---------------------------- +drop table if exists sys_menu; +create table sys_menu ( + menu_id bigint(20) not null auto_increment comment '菜单ID', + menu_name varchar(50) not null comment '菜单名称', + parent_id bigint(20) default 0 comment '父菜单ID', + order_num int(4) default 0 comment '显示顺序', + path varchar(200) default '' comment '路由地址', + component varchar(255) default null comment '组件路径', + query varchar(255) default null comment '路由参数', + is_frame int(1) default 1 comment '是否为外链(0是 1否)', + is_cache int(1) default 0 comment '是否缓存(0缓存 1不缓存)', + menu_type char(1) default '' comment '菜单类型(M目录 C菜单 F按钮)', + visible char(1) default 0 comment '菜单状态(0显示 1隐藏)', + status char(1) default 0 comment '菜单状态(0正常 1停用)', + perms varchar(100) default null comment '权限标识', + icon varchar(100) default '#' comment '菜单图标', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default '' comment '备注', + primary key (menu_id) +) engine=innodb auto_increment=2000 comment = '菜单权限表'; + +-- ---------------------------- +-- 初始化-菜单信息表数据 +-- ---------------------------- +-- 一级菜单 +insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '系统管理目录'); +insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录'); +insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录'); +insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址'); +-- 二级菜单 +insert into sys_menu values('100', '用户管理', '1', '1', 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', sysdate(), '', null, '用户管理菜单'); +insert into sys_menu values('101', '角色管理', '1', '2', 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', sysdate(), '', null, '角色管理菜单'); +insert into sys_menu values('102', '菜单管理', '1', '3', 'menu', 'system/menu/index', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'tree-table', 'admin', sysdate(), '', null, '菜单管理菜单'); +insert into sys_menu values('103', '部门管理', '1', '4', 'dept', 'system/dept/index', '', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', sysdate(), '', null, '部门管理菜单'); +insert into sys_menu values('104', '岗位管理', '1', '5', 'post', 'system/post/index', '', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', sysdate(), '', null, '岗位管理菜单'); +insert into sys_menu values('105', '字典管理', '1', '6', 'dict', 'system/dict/index', '', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', sysdate(), '', null, '字典管理菜单'); +insert into sys_menu values('106', '参数设置', '1', '7', 'config', 'system/config/index', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', sysdate(), '', null, '参数设置菜单'); +insert into sys_menu values('107', '通知公告', '1', '8', 'notice', 'system/notice/index', '', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', sysdate(), '', null, '通知公告菜单'); +insert into sys_menu values('108', '日志管理', '1', '9', 'log', '', '', 1, 0, 'M', '0', '0', '', 'log', 'admin', sysdate(), '', null, '日志管理菜单'); +insert into sys_menu values('109', '在线用户', '2', '1', 'online', 'monitor/online/index', '', 1, 0, 'C', '0', '0', 'monitor:online:list', 'online', 'admin', sysdate(), '', null, '在线用户菜单'); +insert into sys_menu values('110', '定时任务', '2', '2', 'job', 'monitor/job/index', '', 1, 0, 'C', '0', '0', 'monitor:job:list', 'job', 'admin', sysdate(), '', null, '定时任务菜单'); +insert into sys_menu values('111', '数据监控', '2', '3', 'druid', 'monitor/druid/index', '', 1, 0, 'C', '0', '0', 'monitor:druid:list', 'druid', 'admin', sysdate(), '', null, '数据监控菜单'); +insert into sys_menu values('112', '服务监控', '2', '4', 'server', 'monitor/server/index', '', 1, 0, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', sysdate(), '', null, '服务监控菜单'); +insert into sys_menu values('113', '缓存监控', '2', '5', 'cache', 'monitor/cache/index', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis', 'admin', sysdate(), '', null, '缓存监控菜单'); +insert into sys_menu values('114', '缓存列表', '2', '6', 'cacheList', 'monitor/cache/list', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis-list', 'admin', sysdate(), '', null, '缓存列表菜单'); +insert into sys_menu values('115', '表单构建', '3', '1', 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 'admin', sysdate(), '', null, '表单构建菜单'); +insert into sys_menu values('116', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 'admin', sysdate(), '', null, '代码生成菜单'); +insert into sys_menu values('117', '系统接口', '3', '3', 'swagger', 'tool/swagger/index', '', 1, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', sysdate(), '', null, '系统接口菜单'); +-- 三级菜单 +insert into sys_menu values('500', '操作日志', '108', '1', 'operlog', 'monitor/operlog/index', '', 1, 0, 'C', '0', '0', 'monitor:operlog:list', 'form', 'admin', sysdate(), '', null, '操作日志菜单'); +insert into sys_menu values('501', '登录日志', '108', '2', 'logininfor', 'monitor/logininfor/index', '', 1, 0, 'C', '0', '0', 'monitor:logininfor:list', 'logininfor', 'admin', sysdate(), '', null, '登录日志菜单'); +-- 用户管理按钮 +insert into sys_menu values('1000', '用户查询', '100', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1001', '用户新增', '100', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1002', '用户修改', '100', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1003', '用户删除', '100', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1004', '用户导出', '100', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1005', '用户导入', '100', '6', '', '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1006', '重置密码', '100', '7', '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', sysdate(), '', null, ''); +-- 角色管理按钮 +insert into sys_menu values('1007', '角色查询', '101', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1008', '角色新增', '101', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1009', '角色修改', '101', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1010', '角色删除', '101', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1011', '角色导出', '101', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:role:export', '#', 'admin', sysdate(), '', null, ''); +-- 菜单管理按钮 +insert into sys_menu values('1012', '菜单查询', '102', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1013', '菜单新增', '102', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1014', '菜单修改', '102', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1015', '菜单删除', '102', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', sysdate(), '', null, ''); +-- 部门管理按钮 +insert into sys_menu values('1016', '部门查询', '103', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1017', '部门新增', '103', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1018', '部门修改', '103', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1019', '部门删除', '103', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', sysdate(), '', null, ''); +-- 岗位管理按钮 +insert into sys_menu values('1020', '岗位查询', '104', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1021', '岗位新增', '104', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1022', '岗位修改', '104', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1023', '岗位删除', '104', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1024', '岗位导出', '104', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', sysdate(), '', null, ''); +-- 字典管理按钮 +insert into sys_menu values('1025', '字典查询', '105', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1026', '字典新增', '105', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1027', '字典修改', '105', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1028', '字典删除', '105', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1029', '字典导出', '105', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', sysdate(), '', null, ''); +-- 参数设置按钮 +insert into sys_menu values('1030', '参数查询', '106', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1031', '参数新增', '106', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1032', '参数修改', '106', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1033', '参数删除', '106', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1034', '参数导出', '106', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', sysdate(), '', null, ''); +-- 通知公告按钮 +insert into sys_menu values('1035', '公告查询', '107', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1036', '公告新增', '107', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1037', '公告修改', '107', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1038', '公告删除', '107', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:remove', '#', 'admin', sysdate(), '', null, ''); +-- 操作日志按钮 +insert into sys_menu values('1039', '操作查询', '500', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1040', '操作删除', '500', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1041', '日志导出', '500', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:export', '#', 'admin', sysdate(), '', null, ''); +-- 登录日志按钮 +insert into sys_menu values('1042', '登录查询', '501', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1043', '登录删除', '501', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1044', '日志导出', '501', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:export', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1045', '账户解锁', '501', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock', '#', 'admin', sysdate(), '', null, ''); +-- 在线用户按钮 +insert into sys_menu values('1046', '在线查询', '109', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1047', '批量强退', '109', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:batchLogout', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1048', '单条强退', '109', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:forceLogout', '#', 'admin', sysdate(), '', null, ''); +-- 定时任务按钮 +insert into sys_menu values('1049', '任务查询', '110', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1050', '任务新增', '110', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1051', '任务修改', '110', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1052', '任务删除', '110', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1053', '状态修改', '110', '5', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:changeStatus', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1054', '任务导出', '110', '6', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:export', '#', 'admin', sysdate(), '', null, ''); +-- 代码生成按钮 +insert into sys_menu values('1055', '生成查询', '116', '1', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1056', '生成修改', '116', '2', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1057', '生成删除', '116', '3', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1058', '导入代码', '116', '4', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1059', '预览代码', '116', '5', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1060', '生成代码', '116', '6', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code', '#', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 6、用户和角色关联表 用户N-1角色 +-- ---------------------------- +drop table if exists sys_user_role; +create table sys_user_role ( + user_id bigint(20) not null comment '用户ID', + role_id bigint(20) not null comment '角色ID', + primary key(user_id, role_id) +) engine=innodb comment = '用户和角色关联表'; + +-- ---------------------------- +-- 初始化-用户和角色关联表数据 +-- ---------------------------- +insert into sys_user_role values ('1', '1'); +insert into sys_user_role values ('2', '2'); + + +-- ---------------------------- +-- 7、角色和菜单关联表 角色1-N菜单 +-- ---------------------------- +drop table if exists sys_role_menu; +create table sys_role_menu ( + role_id bigint(20) not null comment '角色ID', + menu_id bigint(20) not null comment '菜单ID', + primary key(role_id, menu_id) +) engine=innodb comment = '角色和菜单关联表'; + +-- ---------------------------- +-- 初始化-角色和菜单关联表数据 +-- ---------------------------- +insert into sys_role_menu values ('2', '1'); +insert into sys_role_menu values ('2', '2'); +insert into sys_role_menu values ('2', '3'); +insert into sys_role_menu values ('2', '4'); +insert into sys_role_menu values ('2', '100'); +insert into sys_role_menu values ('2', '101'); +insert into sys_role_menu values ('2', '102'); +insert into sys_role_menu values ('2', '103'); +insert into sys_role_menu values ('2', '104'); +insert into sys_role_menu values ('2', '105'); +insert into sys_role_menu values ('2', '106'); +insert into sys_role_menu values ('2', '107'); +insert into sys_role_menu values ('2', '108'); +insert into sys_role_menu values ('2', '109'); +insert into sys_role_menu values ('2', '110'); +insert into sys_role_menu values ('2', '111'); +insert into sys_role_menu values ('2', '112'); +insert into sys_role_menu values ('2', '113'); +insert into sys_role_menu values ('2', '114'); +insert into sys_role_menu values ('2', '115'); +insert into sys_role_menu values ('2', '116'); +insert into sys_role_menu values ('2', '117'); +insert into sys_role_menu values ('2', '500'); +insert into sys_role_menu values ('2', '501'); +insert into sys_role_menu values ('2', '1000'); +insert into sys_role_menu values ('2', '1001'); +insert into sys_role_menu values ('2', '1002'); +insert into sys_role_menu values ('2', '1003'); +insert into sys_role_menu values ('2', '1004'); +insert into sys_role_menu values ('2', '1005'); +insert into sys_role_menu values ('2', '1006'); +insert into sys_role_menu values ('2', '1007'); +insert into sys_role_menu values ('2', '1008'); +insert into sys_role_menu values ('2', '1009'); +insert into sys_role_menu values ('2', '1010'); +insert into sys_role_menu values ('2', '1011'); +insert into sys_role_menu values ('2', '1012'); +insert into sys_role_menu values ('2', '1013'); +insert into sys_role_menu values ('2', '1014'); +insert into sys_role_menu values ('2', '1015'); +insert into sys_role_menu values ('2', '1016'); +insert into sys_role_menu values ('2', '1017'); +insert into sys_role_menu values ('2', '1018'); +insert into sys_role_menu values ('2', '1019'); +insert into sys_role_menu values ('2', '1020'); +insert into sys_role_menu values ('2', '1021'); +insert into sys_role_menu values ('2', '1022'); +insert into sys_role_menu values ('2', '1023'); +insert into sys_role_menu values ('2', '1024'); +insert into sys_role_menu values ('2', '1025'); +insert into sys_role_menu values ('2', '1026'); +insert into sys_role_menu values ('2', '1027'); +insert into sys_role_menu values ('2', '1028'); +insert into sys_role_menu values ('2', '1029'); +insert into sys_role_menu values ('2', '1030'); +insert into sys_role_menu values ('2', '1031'); +insert into sys_role_menu values ('2', '1032'); +insert into sys_role_menu values ('2', '1033'); +insert into sys_role_menu values ('2', '1034'); +insert into sys_role_menu values ('2', '1035'); +insert into sys_role_menu values ('2', '1036'); +insert into sys_role_menu values ('2', '1037'); +insert into sys_role_menu values ('2', '1038'); +insert into sys_role_menu values ('2', '1039'); +insert into sys_role_menu values ('2', '1040'); +insert into sys_role_menu values ('2', '1041'); +insert into sys_role_menu values ('2', '1042'); +insert into sys_role_menu values ('2', '1043'); +insert into sys_role_menu values ('2', '1044'); +insert into sys_role_menu values ('2', '1045'); +insert into sys_role_menu values ('2', '1046'); +insert into sys_role_menu values ('2', '1047'); +insert into sys_role_menu values ('2', '1048'); +insert into sys_role_menu values ('2', '1049'); +insert into sys_role_menu values ('2', '1050'); +insert into sys_role_menu values ('2', '1051'); +insert into sys_role_menu values ('2', '1052'); +insert into sys_role_menu values ('2', '1053'); +insert into sys_role_menu values ('2', '1054'); +insert into sys_role_menu values ('2', '1055'); +insert into sys_role_menu values ('2', '1056'); +insert into sys_role_menu values ('2', '1057'); +insert into sys_role_menu values ('2', '1058'); +insert into sys_role_menu values ('2', '1059'); +insert into sys_role_menu values ('2', '1060'); + +-- ---------------------------- +-- 8、角色和部门关联表 角色1-N部门 +-- ---------------------------- +drop table if exists sys_role_dept; +create table sys_role_dept ( + role_id bigint(20) not null comment '角色ID', + dept_id bigint(20) not null comment '部门ID', + primary key(role_id, dept_id) +) engine=innodb comment = '角色和部门关联表'; + +-- ---------------------------- +-- 初始化-角色和部门关联表数据 +-- ---------------------------- +insert into sys_role_dept values ('2', '100'); +insert into sys_role_dept values ('2', '101'); +insert into sys_role_dept values ('2', '105'); + + +-- ---------------------------- +-- 9、用户与岗位关联表 用户1-N岗位 +-- ---------------------------- +drop table if exists sys_user_post; +create table sys_user_post +( + user_id bigint(20) not null comment '用户ID', + post_id bigint(20) not null comment '岗位ID', + primary key (user_id, post_id) +) engine=innodb comment = '用户与岗位关联表'; + +-- ---------------------------- +-- 初始化-用户与岗位关联表数据 +-- ---------------------------- +insert into sys_user_post values ('1', '1'); +insert into sys_user_post values ('2', '2'); + + +-- ---------------------------- +-- 10、操作日志记录 +-- ---------------------------- +drop table if exists sys_oper_log; +create table sys_oper_log ( + oper_id bigint(20) not null auto_increment comment '日志主键', + title varchar(50) default '' comment '模块标题', + business_type int(2) default 0 comment '业务类型(0其它 1新增 2修改 3删除)', + method varchar(100) default '' comment '方法名称', + request_method varchar(10) default '' comment '请求方式', + operator_type int(1) default 0 comment '操作类别(0其它 1后台用户 2手机端用户)', + oper_name varchar(50) default '' comment '操作人员', + dept_name varchar(50) default '' comment '部门名称', + oper_url varchar(255) default '' comment '请求URL', + oper_ip varchar(128) default '' comment '主机地址', + oper_location varchar(255) default '' comment '操作地点', + oper_param varchar(2000) default '' comment '请求参数', + json_result varchar(2000) default '' comment '返回参数', + status int(1) default 0 comment '操作状态(0正常 1异常)', + error_msg varchar(2000) default '' comment '错误消息', + oper_time datetime comment '操作时间', + cost_time bigint(20) default 0 comment '消耗时间', + primary key (oper_id), + key idx_sys_oper_log_bt (business_type), + key idx_sys_oper_log_s (status), + key idx_sys_oper_log_ot (oper_time) +) engine=innodb auto_increment=100 comment = '操作日志记录'; + + +-- ---------------------------- +-- 11、字典类型表 +-- ---------------------------- +drop table if exists sys_dict_type; +create table sys_dict_type +( + dict_id bigint(20) not null auto_increment comment '字典主键', + dict_name varchar(100) default '' comment '字典名称', + dict_type varchar(100) default '' comment '字典类型', + status char(1) default '0' comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (dict_id), + unique (dict_type) +) engine=innodb auto_increment=100 comment = '字典类型表'; + +insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', sysdate(), '', null, '用户性别列表'); +insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', sysdate(), '', null, '菜单状态列表'); +insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', sysdate(), '', null, '系统开关列表'); +insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', sysdate(), '', null, '任务状态列表'); +insert into sys_dict_type values(5, '任务分组', 'sys_job_group', '0', 'admin', sysdate(), '', null, '任务分组列表'); +insert into sys_dict_type values(6, '系统是否', 'sys_yes_no', '0', 'admin', sysdate(), '', null, '系统是否列表'); +insert into sys_dict_type values(7, '通知类型', 'sys_notice_type', '0', 'admin', sysdate(), '', null, '通知类型列表'); +insert into sys_dict_type values(8, '通知状态', 'sys_notice_status', '0', 'admin', sysdate(), '', null, '通知状态列表'); +insert into sys_dict_type values(9, '操作类型', 'sys_oper_type', '0', 'admin', sysdate(), '', null, '操作类型列表'); +insert into sys_dict_type values(10, '系统状态', 'sys_common_status', '0', 'admin', sysdate(), '', null, '登录状态列表'); + + +-- ---------------------------- +-- 12、字典数据表 +-- ---------------------------- +drop table if exists sys_dict_data; +create table sys_dict_data +( + dict_code bigint(20) not null auto_increment comment '字典编码', + dict_sort int(4) default 0 comment '字典排序', + dict_label varchar(100) default '' comment '字典标签', + dict_value varchar(100) default '' comment '字典键值', + dict_type varchar(100) default '' comment '字典类型', + css_class varchar(100) default null comment '样式属性(其他样式扩展)', + list_class varchar(100) default null comment '表格回显样式', + is_default char(1) default 'N' comment '是否默认(Y是 N否)', + status char(1) default '0' comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (dict_code) +) engine=innodb auto_increment=100 comment = '字典数据表'; + +insert into sys_dict_data values(1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', sysdate(), '', null, '性别男'); +insert into sys_dict_data values(2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别女'); +insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别未知'); +insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '显示菜单'); +insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '隐藏菜单'); +insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); +insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); +insert into sys_dict_data values(10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', sysdate(), '', null, '默认分组'); +insert into sys_dict_data values(11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', sysdate(), '', null, '系统分组'); +insert into sys_dict_data values(12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '系统默认是'); +insert into sys_dict_data values(13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '系统默认否'); +insert into sys_dict_data values(14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', sysdate(), '', null, '通知'); +insert into sys_dict_data values(15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '公告'); +insert into sys_dict_data values(16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '关闭状态'); +insert into sys_dict_data values(18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '其他操作'); +insert into sys_dict_data values(19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '新增操作'); +insert into sys_dict_data values(20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '修改操作'); +insert into sys_dict_data values(21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '删除操作'); +insert into sys_dict_data values(22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '授权操作'); +insert into sys_dict_data values(23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导出操作'); +insert into sys_dict_data values(24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导入操作'); +insert into sys_dict_data values(25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '强退操作'); +insert into sys_dict_data values(26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '生成操作'); +insert into sys_dict_data values(27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '清空操作'); +insert into sys_dict_data values(28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); + + +-- ---------------------------- +-- 13、参数配置表 +-- ---------------------------- +drop table if exists sys_config; +create table sys_config ( + config_id int(5) not null auto_increment comment '参数主键', + config_name varchar(100) default '' comment '参数名称', + config_key varchar(100) default '' comment '参数键名', + config_value varchar(500) default '' comment '参数键值', + config_type char(1) default 'N' comment '系统内置(Y是 N否)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (config_id) +) engine=innodb auto_increment=100 comment = '参数配置表'; + +insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow' ); +insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456' ); +insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' ); +insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(true开启,false关闭)'); +insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)'); +insert into sys_config values(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)'); + + +-- ---------------------------- +-- 14、系统访问记录 +-- ---------------------------- +drop table if exists sys_logininfor; +create table sys_logininfor ( + info_id bigint(20) not null auto_increment comment '访问ID', + user_name varchar(50) default '' comment '用户账号', + ipaddr varchar(128) default '' comment '登录IP地址', + login_location varchar(255) default '' comment '登录地点', + browser varchar(50) default '' comment '浏览器类型', + os varchar(50) default '' comment '操作系统', + status char(1) default '0' comment '登录状态(0成功 1失败)', + msg varchar(255) default '' comment '提示消息', + login_time datetime comment '访问时间', + primary key (info_id), + key idx_sys_logininfor_s (status), + key idx_sys_logininfor_lt (login_time) +) engine=innodb auto_increment=100 comment = '系统访问记录'; + + +-- ---------------------------- +-- 15、定时任务调度表 +-- ---------------------------- +drop table if exists sys_job; +create table sys_job ( + job_id bigint(20) not null auto_increment comment '任务ID', + job_name varchar(64) default '' comment '任务名称', + job_group varchar(64) default 'DEFAULT' comment '任务组名', + invoke_target varchar(500) not null comment '调用目标字符串', + cron_expression varchar(255) default '' comment 'cron执行表达式', + misfire_policy varchar(20) default '3' comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)', + concurrent char(1) default '1' comment '是否并发执行(0允许 1禁止)', + status char(1) default '0' comment '状态(0正常 1暂停)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default '' comment '备注信息', + primary key (job_id, job_name, job_group) +) engine=innodb auto_increment=100 comment = '定时任务调度表'; + +insert into sys_job values(1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); +insert into sys_job values(2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); +insert into sys_job values(3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 16、定时任务调度日志表 +-- ---------------------------- +drop table if exists sys_job_log; +create table sys_job_log ( + job_log_id bigint(20) not null auto_increment comment '任务日志ID', + job_name varchar(64) not null comment '任务名称', + job_group varchar(64) not null comment '任务组名', + invoke_target varchar(500) not null comment '调用目标字符串', + job_message varchar(500) comment '日志信息', + status char(1) default '0' comment '执行状态(0正常 1失败)', + exception_info varchar(2000) default '' comment '异常信息', + create_time datetime comment '创建时间', + primary key (job_log_id) +) engine=innodb comment = '定时任务调度日志表'; + + +-- ---------------------------- +-- 17、通知公告表 +-- ---------------------------- +drop table if exists sys_notice; +create table sys_notice ( + notice_id int(4) not null auto_increment comment '公告ID', + notice_title varchar(50) not null comment '公告标题', + notice_type char(1) not null comment '公告类型(1通知 2公告)', + notice_content longblob default null comment '公告内容', + status char(1) default '0' comment '公告状态(0正常 1关闭)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(255) default null comment '备注', + primary key (notice_id) +) engine=innodb auto_increment=10 comment = '通知公告表'; + +-- ---------------------------- +-- 初始化-公告信息表数据 +-- ---------------------------- +insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员'); +insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员'); + + +-- ---------------------------- +-- 18、代码生成业务表 +-- ---------------------------- +drop table if exists gen_table; +create table gen_table ( + table_id bigint(20) not null auto_increment comment '编号', + table_name varchar(200) default '' comment '表名称', + table_comment varchar(500) default '' comment '表描述', + sub_table_name varchar(64) default null comment '关联子表的表名', + sub_table_fk_name varchar(64) default null comment '子表关联的外键名', + class_name varchar(100) default '' comment '实体类名称', + tpl_category varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作)', + package_name varchar(100) comment '生成包路径', + module_name varchar(30) comment '生成模块名', + business_name varchar(30) comment '生成业务名', + function_name varchar(50) comment '生成功能名', + function_author varchar(50) comment '生成功能作者', + gen_type char(1) default '0' comment '生成代码方式(0zip压缩包 1自定义路径)', + gen_path varchar(200) default '/' comment '生成路径(不填默认项目路径)', + options varchar(1000) comment '其它生成选项', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (table_id) +) engine=innodb auto_increment=1 comment = '代码生成业务表'; + + +-- ---------------------------- +-- 19、代码生成业务表字段 +-- ---------------------------- +drop table if exists gen_table_column; +create table gen_table_column ( + column_id bigint(20) not null auto_increment comment '编号', + table_id bigint(20) comment '归属表编号', + column_name varchar(200) comment '列名称', + column_comment varchar(500) comment '列描述', + column_type varchar(100) comment '列类型', + java_type varchar(500) comment 'JAVA类型', + java_field varchar(200) comment 'JAVA字段名', + is_pk char(1) comment '是否主键(1是)', + is_increment char(1) comment '是否自增(1是)', + is_required char(1) comment '是否必填(1是)', + is_insert char(1) comment '是否为插入字段(1是)', + is_edit char(1) comment '是否编辑字段(1是)', + is_list char(1) comment '是否列表字段(1是)', + is_query char(1) comment '是否查询字段(1是)', + query_type varchar(200) default 'EQ' comment '查询方式(等于、不等于、大于、小于、范围)', + html_type varchar(200) comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)', + dict_type varchar(200) default '' comment '字典类型', + sort int comment '排序', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + primary key (column_id) +) engine=innodb auto_increment=1 comment = '代码生成业务表字段'; \ No newline at end of file