From 30fdb672739f620376ace70dd27da18ae0b4a8d9 Mon Sep 17 00:00:00 2001 From: seg_yinzy Date: Fri, 13 May 2022 23:42:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=BE=AE=E4=BF=A1sd?= =?UTF-8?q?k=E5=8C=85=E7=9A=84=E5=BC=95=E7=94=A8=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 45 + .run/test#1.run.xml | 5 + LICENSE | 20 + README.md | 85 + bin/clean.bat | 12 + bin/package.bat | 12 + bin/run.bat | 14 + doc/若依环境使用手册.docx | Bin 0 -> 428430 bytes java_sdk_v3.0.9/README.md | 298 ++++ java_sdk_v3.0.9/pom.xml | 127 ++ .../com/github/wxpay/sdk/IWXPayDomain.java | 42 + .../main/java/com/github/wxpay/sdk/WXPay.java | 689 ++++++++ .../com/github/wxpay/sdk/WXPayConfig.java | 103 ++ .../com/github/wxpay/sdk/WXPayConstants.java | 59 + .../com/github/wxpay/sdk/WXPayReport.java | 265 +++ .../com/github/wxpay/sdk/WXPayRequest.java | 258 +++ .../java/com/github/wxpay/sdk/WXPayUtil.java | 295 ++++ .../com/github/wxpay/sdk/WXPayXmlUtil.java | 30 + libs/wxpay-sdk-0.0.1.jar | Bin 0 -> 63608 bytes pom.xml | 363 ++++ pom.xmlbak | 281 +++ pom1.xml | 320 ++++ ruoyi-admin/pom.xml | 98 ++ .../main/java/com/ruoyi/RuoYiApplication.java | 32 + .../com/ruoyi/RuoYiServletInitializer.java | 18 + .../com/ruoyi/security/SecurityConfig.java | 131 ++ .../filter/JwtAuthenticationTokenFilter.java | 43 + .../handle/AuthenticationEntryPointImpl.java | 33 + .../handle/LogoutSuccessHandlerImpl.java | 51 + .../com/ruoyi/security/web/domain/Server.java | 211 +++ .../ruoyi/security/web/domain/server/Cpu.java | 88 + .../ruoyi/security/web/domain/server/Jvm.java | 107 ++ .../ruoyi/security/web/domain/server/Mem.java | 53 + .../ruoyi/security/web/domain/server/Sys.java | 73 + .../security/web/domain/server/SysFile.java | 99 ++ .../web/exception/GlobalExceptionHandler.java | 105 ++ .../web/service/PermissionService.java | 153 ++ .../security/web/service/SysLoginService.java | 80 + .../web/service/SysPermissionService.java | 58 + .../web/service/UserDetailsServiceImpl.java | 52 + .../controller/common/CaptchaController.java | 96 + .../controller/common/CommonController.java | 334 ++++ .../controller/monitor/CacheController.java | 53 + .../controller/monitor/ServerController.java | 27 + .../monitor/SysLogininforController.java | 67 + .../monitor/SysOperlogController.java | 67 + .../monitor/SysUserOnlineController.java | 92 + .../segchk/SegchkCarouseMgtController.java | 183 ++ .../segchk/SegchkChargeCardController.java | 154 ++ .../segchk/SegchkCommentAccController.java | 145 ++ .../segchk/SegchkDistrictInfoController.java | 105 ++ .../segchk/SegchkKeywordLableController.java | 141 ++ .../segchk/SegchkLableMgtController.java | 165 ++ .../segchk/SegchkLogionDetailController.java | 141 ++ .../segchk/SegchkMsgDetailController.java | 141 ++ .../SegchkPreferenceLableController.java | 141 ++ .../segchk/SegchkProviderMgtController.java | 161 ++ .../SegchkRecommenderStoreController.java | 161 ++ .../segchk/SegchkSalerInfoController.java | 161 ++ .../SegchkSelfServiceChkController.java | 141 ++ .../segchk/SegchkServiceChkController.java | 141 ++ .../SegchkServiceCommentController.java | 141 ++ .../segchk/SegchkSimpleListController.java | 304 ++++ .../segchk/SegchkSmsDetailController.java | 141 ++ .../segchk/SegchkStoreAccountController.java | 142 ++ .../SegchkStoreBasicInfoController.java | 213 +++ .../segchk/SegchkStoreCashController.java | 141 ++ .../segchk/SegchkStoreChargeController.java | 141 ++ .../segchk/SegchkStoreChkMgtController.java | 141 ++ .../segchk/SegchkStoreImageController.java | 141 ++ .../segchk/SegchkStoreLableMgtController.java | 166 ++ .../segchk/SegchkStoreRewardController.java | 145 ++ .../segchk/SegchkStoreSecurityController.java | 145 ++ .../segchk/SegchkStoreSelfMgtController.java | 142 ++ .../segchk/SegchkSystemSettingController.java | 131 ++ .../segchk/SegchkUserAccountController.java | 141 ++ .../segchk/SegchkUserBasicInfoController.java | 141 ++ .../segchk/SegchkUserCashController.java | 141 ++ ...SegchkUserCertificationInfoController.java | 141 ++ .../segchk/SegchkUserChargeController.java | 141 ++ .../segchk/SegchkUserCollectController.java | 141 ++ .../segchk/SegchkUserExtInfoController.java | 141 ++ .../segchk/SegchkUserLikegoController.java | 141 ++ .../segchk/SegchkUserRewardController.java | 141 ++ .../segchk/SegchkUserRewardCtlController.java | 141 ++ .../segchk/SegchkUserSecurityController.java | 141 ++ .../segchk/SegchkUserVipController.java | 141 ++ .../segchk/SegchkUserWechatController.java | 141 ++ .../segchk/SegchkVipSetInfoController.java | 141 ++ .../system/SysConfigController.java | 135 ++ .../controller/system/SysDeptController.java | 162 ++ .../system/SysDictDataController.java | 120 ++ .../system/SysDictTypeController.java | 131 ++ .../controller/system/SysIndexController.java | 29 + .../controller/system/SysLoginController.java | 102 ++ .../controller/system/SysMenuController.java | 142 ++ .../system/SysNoticeController.java | 91 + .../controller/system/SysPostController.java | 129 ++ .../system/SysProfileController.java | 141 ++ .../system/SysRegisterController.java | 38 + .../controller/system/SysRoleController.java | 240 +++ .../controller/system/SysUserController.java | 249 +++ .../controller/tool/SwaggerController.java | 24 + .../web/controller/tool/TestController.java | 181 ++ .../ruoyi/web/core/config/SwaggerConfig.java | 125 ++ .../META-INF/spring-devtools.properties | 1 + .../src/main/resources/application-druid.yml | 119 ++ .../main/resources/application-kaleprod.yml | 118 ++ .../src/main/resources/application-test.yml | 118 ++ .../src/main/resources/application.yml | 98 ++ ruoyi-admin/src/main/resources/banner.txt | 24 + .../main/resources/i18n/messages.properties | 37 + ruoyi-admin/src/main/resources/logback.xml | 93 + .../main/resources/mybatis/mybatis-config.xml | 15 + ruoyi-common/pom.xml | 126 ++ .../ruoyi/common/annotation/DataScope.java | 28 + .../ruoyi/common/annotation/DataSource.java | 28 + .../com/ruoyi/common/annotation/Excel.java | 165 ++ .../com/ruoyi/common/annotation/Excels.java | 18 + .../java/com/ruoyi/common/annotation/Log.java | 41 + .../ruoyi/common/annotation/RateLimiter.java | 40 + .../ruoyi/common/annotation/RepeatSubmit.java | 23 + .../com/ruoyi/common/annotation/UnAuth.java | 14 + .../com/ruoyi/common/config/RuoYiConfig.java | 124 ++ .../com/ruoyi/common/constant/Constants.java | 151 ++ .../ruoyi/common/constant/GenConstants.java | 114 ++ .../com/ruoyi/common/constant/HttpStatus.java | 89 + .../common/constant/ScheduleConstants.java | 50 + .../ruoyi/common/constant/UserConstants.java | 78 + .../core/controller/BaseController.java | 184 ++ .../ruoyi/common/core/domain/AjaxResult.java | 148 ++ .../ruoyi/common/core/domain/BaseEntity.java | 114 ++ .../ruoyi/common/core/domain/TreeEntity.java | 79 + .../ruoyi/common/core/domain/TreeSelect.java | 77 + .../common/core/domain/entity/SysDept.java | 202 +++ .../core/domain/entity/SysDictData.java | 176 ++ .../core/domain/entity/SysDictType.java | 94 + .../common/core/domain/entity/SysMenu.java | 245 +++ .../common/core/domain/entity/SysRole.java | 226 +++ .../common/core/domain/entity/SysUser.java | 365 ++++ .../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 | 84 + .../ruoyi/common/core/page/TableDataInfo.java | 85 + .../ruoyi/common/core/page/TableSupport.java | 49 + .../ruoyi/common/core/redis/RedisCache.java | 234 +++ .../ruoyi/common/core/text/CharsetKit.java | 86 + .../com/ruoyi/common/core/text/Convert.java | 1005 +++++++++++ .../ruoyi/common/core/text/StrFormatter.java | 92 + .../ruoyi/common/enums/BusinessStatus.java | 20 + .../com/ruoyi/common/enums/BusinessType.java | 59 + .../ruoyi/common/enums/DataSourceType.java | 19 + .../com/ruoyi/common/enums/HttpMethod.java | 36 + .../com/ruoyi/common/enums/LimitType.java | 20 + .../com/ruoyi/common/enums/OperatorType.java | 24 + .../com/ruoyi/common/enums/UserStatus.java | 30 + .../common/exception/CustomException.java | 37 + .../common/exception/DemoModeException.java | 15 + .../common/exception/GlobalException.java | 58 + .../common/exception/ServiceException.java | 77 + .../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 + .../file/InvalidExtensionException.java | 81 + .../common/exception/job/TaskException.java | 34 + .../exception/user/CaptchaException.java | 16 + .../user/CaptchaExpireException.java | 16 + .../common/exception/user/UserException.java | 18 + .../user/UserPasswordNotMatchException.java | 16 + .../ruoyi/common/filter/RepeatableFilter.java | 52 + .../filter/RepeatedlyRequestWrapper.java | 75 + .../com/ruoyi/common/filter/XssFilter.java | 74 + .../filter/XssHttpServletRequestWrapper.java | 104 ++ .../java/com/ruoyi/common/utils/Arith.java | 114 ++ .../com/ruoyi/common/utils/DateUtils.java | 155 ++ .../com/ruoyi/common/utils/DictUtils.java | 183 ++ .../com/ruoyi/common/utils/ExceptionUtil.java | 40 + .../java/com/ruoyi/common/utils/LogUtils.java | 18 + .../com/ruoyi/common/utils/MessageUtils.java | 26 + .../com/ruoyi/common/utils/RedisCahceKey.java | 91 + .../com/ruoyi/common/utils/SecurityUtils.java | 120 ++ .../com/ruoyi/common/utils/ServletUtils.java | 136 ++ .../ruoyi/common/utils/SnowflakeIdWorker.java | 171 ++ .../com/ruoyi/common/utils/StringUtils.java | 534 ++++++ .../java/com/ruoyi/common/utils/Threads.java | 99 ++ .../ruoyi/common/utils/VerifyCodeUtils.java | 228 +++ .../ruoyi/common/utils/bean/BeanUtils.java | 110 ++ .../common/utils/file/FileTypeUtils.java | 76 + .../common/utils/file/FileUploadUtils.java | 235 +++ .../ruoyi/common/utils/file/FileUtils.java | 256 +++ .../ruoyi/common/utils/file/ImageUtils.java | 101 ++ .../common/utils/file/MimeTypeUtils.java | 59 + .../ruoyi/common/utils/html/EscapeUtil.java | 155 ++ .../ruoyi/common/utils/html/HTMLFilter.java | 570 ++++++ .../ruoyi/common/utils/http/HttpHelper.java | 55 + .../ruoyi/common/utils/http/HttpUtils.java | 262 +++ .../ruoyi/common/utils/ip/AddressUtils.java | 56 + .../com/ruoyi/common/utils/ip/IpUtils.java | 195 +++ .../com/ruoyi/common/utils/poi/ExcelUtil.java | 1256 ++++++++++++++ .../common/utils/reflect/ReflectUtils.java | 410 +++++ .../com/ruoyi/common/utils/sign/Base64.java | 291 ++++ .../com/ruoyi/common/utils/sign/Md5Utils.java | 66 + .../common/utils/spring/SpringUtils.java | 146 ++ .../com/ruoyi/common/utils/sql/SqlUtil.java | 37 + .../com/ruoyi/common/utils/uuid/IdUtils.java | 49 + .../com/ruoyi/common/utils/uuid/UUID.java | 484 ++++++ ruoyi-framework/pom.xml | 66 + .../framework/aspectj/DataScopeAspect.java | 181 ++ .../framework/aspectj/DataSourceAspect.java | 72 + .../ruoyi/framework/aspectj/LogAspect.java | 243 +++ .../framework/aspectj/RateLimiterAspect.java | 116 ++ .../framework/config/ApplicationConfig.java | 30 + .../ruoyi/framework/config/CaptchaConfig.java | 83 + .../ruoyi/framework/config/DruidConfig.java | 126 ++ .../config/FastJson2JsonRedisSerializer.java | 71 + .../ruoyi/framework/config/FilterConfig.java | 58 + .../framework/config/KaptchaTextCreator.java | 75 + .../ruoyi/framework/config/MyBatisConfig.java | 132 ++ .../ruoyi/framework/config/RedisConfig.java | 79 + .../framework/config/ResourcesConfig.java | 65 + .../ruoyi/framework/config/ServerConfig.java | 32 + .../framework/config/ThreadPoolConfig.java | 62 + .../config/properties/DruidProperties.java | 77 + .../datasource/DynamicDataSource.java | 26 + .../DynamicDataSourceContextHolder.java | 45 + .../interceptor/RepeatSubmitInterceptor.java | 55 + .../impl/SameUrlDataInterceptor.java | 125 ++ .../ruoyi/framework/manager/AsyncManager.java | 55 + .../framework/manager/ShutdownManager.java | 39 + .../manager/factory/AsyncFactory.java | 102 ++ .../web/service/SysRegisterService.java | 115 ++ .../framework/web/service/TokenService.java | 225 +++ ruoyi-generator/pom.xml | 42 + .../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 | 500 ++++++ .../service/IGenTableColumnService.java | 44 + .../generator/service/IGenTableService.java | 121 ++ .../com/ruoyi/generator/util/GenUtils.java | 258 +++ .../generator/util/VelocityInitializer.java | 35 + .../ruoyi/generator/util/VelocityUtils.java | 362 ++++ .../src/main/resources/generator.yml | 10 + .../mapper/generator/GenTableColumnMapper.xml | 127 ++ .../mapper/generator/GenTableMapper.xml | 201 +++ .../main/resources/vm/java/controller.java.vm | 114 ++ .../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 | 166 ++ .../main/resources/vm/java/sub-domain.java.vm | 76 + .../src/main/resources/vm/js/api.js.vm | 53 + .../src/main/resources/vm/sql/sql.vm | 22 + .../main/resources/vm/vue/index-tree.vue.vm | 503 ++++++ .../src/main/resources/vm/vue/index.vue.vm | 607 +++++++ .../src/main/resources/vm/xml/mapper.xml.vm | 135 ++ ruoyi-quartz/pom.xml | 42 + .../ruoyi/quartz/config/ScheduleConfig.java | 57 + .../quartz/controller/SysJobController.java | 167 ++ .../controller/SysJobLogController.java | 90 + .../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 | 254 +++ .../java/com/ruoyi/quartz/task/RyTask.java | 28 + .../com/ruoyi/quartz/task/SegchkTask.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 | 113 ++ .../mapper/quartz/SysJobLogMapper.xml | 93 + .../resources/mapper/quartz/SysJobMapper.xml | 111 ++ ruoyi-segchk-web/pom.xml | 141 ++ ruoyi-segchk-web/src/main/docker/Dockerfile | 4 + .../java/com/ruoyi/AppletsAppApplication.java | 83 + .../ruoyi/appletsutil/AppletsLoginUtils.java | 97 ++ .../com/ruoyi/appletsutil/BaseResponse.java | 56 + .../ruoyi/appletsutil/ErrorController.java | 39 + .../GlobalWebExceptionHandler.java | 59 + .../com/ruoyi/appletsutil/ResultCode.java | 34 + .../appletsutil/UnAuthorizedException.java | 33 + .../java/com/ruoyi/config/SecurityConfig.java | 94 + .../java/com/ruoyi/config/WebConfigurer.java | 26 + .../interceptor/AuthorityInterceptor.java | 170 ++ .../java/com/ruoyi/login/OssController.java | 128 ++ .../ruoyi/login/SegChkLoginController.java | 759 ++++++++ .../segchk/SegchkDefaultIndexController.java | 511 ++++++ .../SegchkDefaultProviderController.java | 207 +++ .../segchk/SegchkDefaultStoreController.java | 589 +++++++ .../segchk/SegchkDefaultUserController.java | 1111 ++++++++++++ .../java/com/ruoyi/util/CommonController.java | 158 ++ .../java/com/ruoyi/util/HtmlController.java | 90 + .../java/com/ruoyi/util/IndexController.java | 33 + .../java/com/ruoyi/util/QrCodeController.java | 118 ++ .../src/main/resources/PwPaX4PqzG.txt | 1 + .../src/main/resources/application-dev.yml | 156 ++ .../src/main/resources/application-prod.yml | 159 ++ .../src/main/resources/application-test.yml | 158 ++ .../src/main/resources/application-uat.yml | 71 + .../src/main/resources/application.yml | 121 ++ .../resources/http-client.private.env.json | 60 + .../src/main/resources/logback-spring.xml | 89 + .../resources/messages/messages.properties | 6 + .../messages/messages_en_US.properties | 5 + .../messages/messages_zh_CN.properties | 5 + .../main/resources/mybatis/mybatis-config.xml | 15 + .../src/main/resources/static/PwPaX4PqzG.txt | 1 + .../resources/static/default/PwPaX4PqzG.txt | 1 + .../static/default/common/PwPaX4PqzG.txt | 1 + .../static/default/index/PwPaX4PqzG.txt | 1 + .../static/default/provider/PwPaX4PqzG.txt | 1 + .../static/default/store/PwPaX4PqzG.txt | 1 + .../static/default/user/PwPaX4PqzG.txt | 1 + .../src/main/resources/static/img/bg.jpg | Bin 0 -> 722686 bytes .../main/resources/static/img/checkret1.png | Bin 0 -> 69452 bytes .../main/resources/static/wxpk/PwPaX4PqzG.txt | 1 + .../main/resources/templates/posters/bg.jpg | Bin 0 -> 722686 bytes .../resources/templates/posters/checkret1.png | Bin 0 -> 69452 bytes ruoyi-segchk-web/src/main/resources/test.http | 998 +++++++++++ ruoyi-segchk/pom.xml | 151 ++ .../com/ruoyi/member/domain/UmsMember.java | 891 ++++++++++ .../ruoyi/member/domain/UmsMemberLevel.java | 206 +++ .../mapper/WeChatCustomerLinkMapper.java | 65 + .../ruoyi/member/service/LoginService.java | 21 + .../ruoyi/member/service/RechargeService.java | 36 + .../ruoyi/member/service/RegisterService.java | 68 + .../member/service/RegisterServiceApi.java | 38 + .../com/ruoyi/member/service/SmsService.java | 71 + .../service/WeChatAppletLoginService.java | 66 + .../service/WeChatCustomerLinkService.java | 86 + .../service/impl/BindNewEmailServiceImpl.java | 0 .../member/service/impl/LoginServiceImpl.java | 223 +++ .../service/impl/RegisterServiceApiImpl.java | 238 +++ .../service/impl/RegisterServiceImpl.java | 221 +++ .../member/service/impl/SendTencentSms.java | 45 + .../member/service/impl/SmsServiceImpl.java | 300 ++++ .../impl/WeChatAppletLoginServiceImpl.java | 179 ++ .../impl/WeChatCustomerLinkServiceImpl.java | 138 ++ .../com/ruoyi/member/vo/AppletLoginInfo.java | 129 ++ .../vo/AppletLoginRedisParamResponse.java | 96 + .../ruoyi/member/vo/BindNewEmailRequest.java | 133 ++ .../ruoyi/member/vo/BindNewMobileRequest.java | 105 ++ .../java/com/ruoyi/member/vo/BindParams.java | 139 ++ .../member/vo/CustomerSearchCondition.java | 178 ++ .../com/ruoyi/member/vo/ForgetPwdRequest.java | 174 ++ .../java/com/ruoyi/member/vo/LoginParams.java | 113 ++ .../com/ruoyi/member/vo/QueryCriteria.java | 125 ++ .../ruoyi/member/vo/UnAuthLoginParams.java | 79 + .../com/ruoyi/member/vo/UpdatePayPwdBean.java | 173 ++ .../com/ruoyi/member/vo/UpdatePwdBean.java | 172 ++ .../ruoyi/order/service/impl/PaySupplier.java | 16 + .../java/com/ruoyi/order/vo/OrderItem.java | 9 + .../ruoyi/segchk/domain/SegchkChargeRet.java | 47 + .../segchk/domain/SegchkChargeReward.java | 207 +++ .../ruoyi/segchk/domain/SegchkMsgWebResp.java | 91 + .../domain/SegchkRecommenderStoreWebResp.java | 182 ++ .../SegchkServiceAndSaleDetailWebResp.java | 90 + .../domain/SegchkServiceAndSaleWebReq.java | 98 ++ .../domain/SegchkServiceAndSaleWebResp.java | 61 + .../domain/SegchkServiceCommentUserReq.java | 89 + .../domain/SegchkServiceCommentWebResp.java | 116 ++ .../domain/SegchkServiceOrderChkResp.java | 138 ++ .../domain/SegchkServiceOrderWebReq.java | 136 ++ .../domain/SegchkStoreBasicInfoWebResp.java | 325 ++++ .../domain/SegchkStoreIndexWebResp.java | 209 +++ .../ruoyi/segchk/domain/SegchkStoreVrReq.java | 118 ++ .../segchk/domain/SegchkStoreWebReq.java | 179 ++ .../segchk/domain/SegchkUserAccountCheck.java | 76 + .../segchk/domain/SegchkUserCashOpsResp.java | 49 + .../segchk/domain/SegchkUserCashWebResp.java | 66 + .../segchk/domain/SegchkUserChargeCard.java | 153 ++ .../domain/SegchkUserChargeWebResp.java | 78 + .../domain/SegchkUserCollectWebResp.java | 185 ++ .../domain/SegchkUserLikeGoWebResp.java | 263 +++ .../segchk/domain/SegchkUserSetInfoReq.java | 104 ++ .../segchk/domain/SegchkUserWebCardResp.java | 185 ++ .../ruoyi/segchk/domain/SegchkUserWebReq.java | 112 ++ .../segchk/domain/SegchkUserWebResp.java | 307 ++++ .../ruoyi/segchk/domain/StoreSelfCard.java | 94 + .../segchk/domain/WeChatCustomerLink.java | 128 ++ .../mapper/SegchkProviderIndexMapper.java | 66 + .../segchk/mapper/SegchkStoreIndexMapper.java | 154 ++ .../segchk/mapper/SegchkUserIndexMapper.java | 136 ++ .../service/ISegchkProviderIndexService.java | 49 + .../service/ISegchkStoreIndexService.java | 191 ++ .../service/ISegchkUserCashService.java | 63 + .../service/ISegchkUserCollectService.java | 70 + .../service/ISegchkUserIndexService.java | 295 ++++ .../service/ISegchkUserLikegoService.java | 62 + .../service/ISegchkUserWechatService.java | 62 + .../impl/ISegchkStoreIndexServiceImpl.java | 393 +++++ .../impl/SegchkProviderIndexServiceImpl.java | 78 + .../impl/SegchkUserCashServiceImpl.java | 100 ++ .../impl/SegchkUserCollectServiceImpl.java | 107 ++ .../impl/SegchkUserIndexServiceImpl.java | 1380 +++++++++++++++ .../impl/SegchkUserLikegoServiceImpl.java | 96 + .../impl/SegchkUserWechatServiceImpl.java | 94 + .../com/ruoyi/setting/bean/AliPaySet.java | 83 + .../com/ruoyi/setting/bean/OssSetting.java | 136 ++ .../java/com/ruoyi/setting/bean/PaySet.java | 75 + .../com/ruoyi/setting/bean/PaySetCommon.java | 232 +++ .../com/ruoyi/setting/bean/PrePaySet.java | 33 + .../com/ruoyi/setting/bean/UnionPaySet.java | 68 + .../com/ruoyi/setting/bean/UploadData.java | 91 + .../com/ruoyi/setting/bean/WechatPaySet.java | 126 ++ .../com/ruoyi/setting/domain/KsdSmsReq.java | 5 + .../java/com/ruoyi/setting/domain/LsCity.java | 158 ++ .../com/ruoyi/setting/domain/LsDistrict.java | 131 ++ .../ruoyi/setting/domain/LsEmailSetting.java | 126 ++ .../com/ruoyi/setting/domain/LsProvince.java | 141 ++ .../ruoyi/setting/domain/LsSmsSetting.java | 197 +++ .../ruoyi/setting/domain/LsStationLetter.java | 111 ++ .../com/ruoyi/setting/domain/LsSystemSeo.java | 96 + .../setting/domain/LsWxCustomerLink.java | 96 + .../setting/domain/SCommunityBuySetting.java | 111 ++ .../setting/domain/SegchkPaySetting.java | 81 + .../com/ruoyi/setting/mapper/AreaMapper.java | 160 ++ .../setting/mapper/BaseInfoSetMapper.java | 55 + .../ruoyi/setting/mapper/LsCityMapper.java | 61 + .../setting/mapper/LsDistrictMapper.java | 61 + .../setting/mapper/LsEmailSettingMapper.java | 61 + .../setting/mapper/LsProvinceMapper.java | 61 + .../setting/mapper/LsSmsSettingMapper.java | 61 + .../setting/mapper/LsStationLetterMapper.java | 116 ++ .../setting/mapper/LsSystemSeoMapper.java | 61 + .../mapper/LsWxCustomerLinkMapper.java | 61 + .../com/ruoyi/setting/mapper/OssMapper.java | 30 + .../mapper/SCommunityBuySettingMapper.java | 61 + .../mapper/SegchkPaySettingMapper.java | 82 + .../ruoyi/setting/service/AreaService.java | 155 ++ .../setting/service/BaseInfoSetService.java | 49 + .../ruoyi/setting/service/ILsCityService.java | 61 + .../setting/service/ILsDistrictService.java | 61 + .../service/ILsEmailSettingService.java | 61 + .../setting/service/ILsPaySettingService.java | 76 + .../setting/service/ILsProvinceService.java | 61 + .../setting/service/ILsSmsSettingService.java | 61 + .../service/ILsStationLetterService.java | 105 ++ .../setting/service/ILsSystemSeoService.java | 61 + .../service/ILsWxCustomerLinkService.java | 61 + .../service/ISCommunityBuySettingService.java | 61 + .../com/ruoyi/setting/service/OssService.java | 61 + .../setting/service/impl/AreaServiceImpl.java | 270 +++ .../service/impl/BaseInfoSetServiceImpl.java | 117 ++ .../service/impl/LsCityServiceImpl.java | 92 + .../service/impl/LsDistrictServiceImpl.java | 92 + .../impl/LsEmailSettingServiceImpl.java | 90 + .../service/impl/LsPaySettingServiceImpl.java | 174 ++ .../service/impl/LsProvinceServiceImpl.java | 92 + .../service/impl/LsSmsSettingServiceImpl.java | 90 + .../impl/LsStationLetterServiceImpl.java | 147 ++ .../service/impl/LsSystemSeoServiceImpl.java | 90 + .../impl/LsWxCustomerLinkServiceImpl.java | 90 + .../setting/service/impl/OssServiceImpl.java | 89 + .../impl/SCommunityBuySettingServiceImpl.java | 90 + .../java/com/ruoyi/setting/vo/AreaItem.java | 9 + .../java/com/ruoyi/setting/vo/Locality.java | 89 + .../main/java/com/ruoyi/util/AesUtils.java | 82 + .../java/com/ruoyi/util/BaseResponse.java | 89 + .../src/main/java/com/ruoyi/util/Claims.java | 132 ++ .../java/com/ruoyi/util/CommonConstant.java | 310 ++++ .../java/com/ruoyi/util/CommonResponse.java | 73 + .../java/com/ruoyi/util/CustomHttpUtils.java | 349 ++++ .../java/com/ruoyi/util/Express100Utils.java | 47 + .../java/com/ruoyi/util/Graphics2DUtils.java | 110 ++ .../main/java/com/ruoyi/util/JaxbUtil.java | 130 ++ .../com/ruoyi/util/MarketingConstant.java | 76 + .../main/java/com/ruoyi/util/PageHelper.java | 132 ++ .../main/java/com/ruoyi/util/PosterUtils.java | 358 ++++ .../main/java/com/ruoyi/util/QRCodeUtils.java | 192 ++ .../java/com/ruoyi/util/QRPostersUtil.java | 362 ++++ .../main/java/com/ruoyi/util/QqOssClient.java | 366 ++++ .../java/com/ruoyi/util/RandomMathLetter.java | 37 + .../ruoyi/util/RedisCacheErrorHandler.java | 44 + .../com/ruoyi/util/SegchkWXPayConfigImpl.java | 126 ++ .../java/com/ruoyi/util/ShareCodeUtils.java | 64 + .../src/main/java/com/ruoyi/util/SmsUtil.java | 124 ++ .../com/ruoyi/util/SnowflakeIdWorker.java | 171 ++ .../main/java/com/ruoyi/util/ThreadTask.java | 33 + .../java/com/ruoyi/util/UnionPayUtils.java | 0 .../java/com/ruoyi/util/VerifyCodeUtils.java | 202 +++ .../com/ruoyi/util/WXPayDomainSimpleImpl.java | 120 ++ .../ruoyi/util/WeChatAppletLoginResponse.java | 132 ++ .../com/ruoyi/util/WeChatAppletUserInfo.java | 101 ++ .../com/ruoyi/util/WeChatAppletUtils.java | 311 ++++ .../java/com/ruoyi/util/WechatSetting.java | 297 ++++ .../main/java/com/ruoyi/util/WechatUtils.java | 715 ++++++++ .../java/com/ruoyi/util/YunUploadUtils.java | 219 +++ .../ruoyi/util/bean/AccessTokenResult.java | 164 ++ .../com/ruoyi/util/bean/AliPaySetting.java | 106 ++ .../java/com/ruoyi/util/bean/BeanUtils.java | 104 ++ .../com/ruoyi/util/bean/CommonWebResult.java | 87 + .../java/com/ruoyi/util/bean/EmailConf.java | 58 + .../com/ruoyi/util/bean/EmailContent.java | 50 + .../java/com/ruoyi/util/bean/LineColor.java | 55 + .../ruoyi/util/bean/MonYunSmsResponse.java | 44 + .../ruoyi/util/bean/OrderInfoAfterPay.java | 70 + .../com/ruoyi/util/bean/OrderInfoForPay.java | 86 + .../java/com/ruoyi/util/bean/OssYunConf.java | 114 ++ .../com/ruoyi/util/bean/PrepayResult.java | 307 ++++ .../com/ruoyi/util/bean/RequestParam.java | 147 ++ .../com/ruoyi/util/bean/SegUserProfile.java | 107 ++ .../com/ruoyi/util/bean/UnionPaySetting.java | 44 + .../com/ruoyi/util/bean/UserConstants.java | 89 + .../com/ruoyi/util/bean/UserInfoProfile.java | 120 ++ .../com/ruoyi/util/bean/UserInfoResult.java | 179 ++ .../util/bean/WeChatAppletCodeRequest.java | 104 ++ .../util/bean/WechatApletPrepayResult.java | 121 ++ .../ruoyi/util/bean/WechatNotifyResult.java | 225 +++ .../ruoyi/util/bean/WechatPayResponse.java | 69 + .../bean/WechatPayResponseForRecharge.java | 62 + .../com/ruoyi/util/bean/WithdrawRequest.java | 73 + .../com/ruoyi/util/bean/WithdrawResponse.java | 77 + .../com/ruoyi/util/bean/WxTransferResult.java | 352 ++++ .../src/main/java/com/ruoyi/util/md5/MD5.java | 59 + .../java/com/ruoyi/util/md5/MD5Utils.java | 121 ++ .../com/ruoyi/util/md5/MessageSourceUtil.java | 38 + .../member/WeChatCustomerLinkMapper.xml | 72 + .../segchk/SegchkProviderIndexMapper.xml | 200 +++ .../mapper/segchk/SegchkStoreIndexMapper.xml | 801 +++++++++ .../mapper/segchk/SegchkUserIndexMapper.xml | 858 +++++++++ .../resources/mapper/setting/AreaMapper.xml | 272 +++ .../mapper/setting/BaseInfoSetMapper.xml | 62 + .../resources/mapper/setting/LsCityMapper.xml | 85 + .../mapper/setting/LsDistrictMapper.xml | 85 + .../mapper/setting/LsEmailSettingMapper.xml | 83 + .../mapper/setting/LsProvinceMapper.xml | 80 + .../mapper/setting/LsSmsSettingMapper.xml | 116 ++ .../mapper/setting/LsStationLetterMapper.xml | 120 ++ .../mapper/setting/LsSystemSeoMapper.xml | 72 + .../mapper/setting/LsWxCustomerLinkMapper.xml | 72 + .../resources/mapper/setting/OssMapper.xml | 48 + .../setting/SCommunityBuySettingMapper.xml | 81 + .../mapper/setting/SegchkPaySettingMapper.xml | 88 + .../main/resources/templates/posters/bg.jpg | Bin 0 -> 192993 bytes .../resources/templates/posters/bigtitle.jpg | Bin 0 -> 397991 bytes .../resources/templates/posters/checkret1.png | Bin 0 -> 69452 bytes ruoyi-system/pom.xml | 30 + .../com/ruoyi/segchk/domain/BaseInfoSet.java | 354 ++++ .../segchk/domain/SegchkBaseInfoSet.java | 328 ++++ .../ruoyi/segchk/domain/SegchkCarouseMgt.java | 125 ++ .../ruoyi/segchk/domain/SegchkChargeCard.java | 123 ++ .../ruoyi/segchk/domain/SegchkChargeRet.java | 47 + .../ruoyi/segchk/domain/SegchkCommentAcc.java | 124 ++ .../segchk/domain/SegchkDistrictInfo.java | 80 + .../segchk/domain/SegchkKeywordLable.java | 97 ++ .../ruoyi/segchk/domain/SegchkLableMgt.java | 148 ++ .../segchk/domain/SegchkLogionDetail.java | 97 ++ .../ruoyi/segchk/domain/SegchkMsgDetail.java | 181 ++ .../ruoyi/segchk/domain/SegchkMsgWebResp.java | 91 + .../segchk/domain/SegchkPreferenceLable.java | 97 ++ .../segchk/domain/SegchkProviderMgt.java | 181 ++ .../segchk/domain/SegchkRecommenderStore.java | 111 ++ .../SegchkRecommenderStoreLableWeb.java | 87 + .../domain/SegchkRecommenderStoreWebReq.java | 89 + .../domain/SegchkRecommenderStoreWebResp.java | 182 ++ .../ruoyi/segchk/domain/SegchkSalerInfo.java | 125 ++ .../segchk/domain/SegchkSelfServiceChk.java | 111 ++ .../SegchkServiceAndSaleDetailWebResp.java | 90 + .../domain/SegchkServiceAndSaleWebReq.java | 98 ++ .../domain/SegchkServiceAndSaleWebResp.java | 61 + .../ruoyi/segchk/domain/SegchkServiceChk.java | 139 ++ .../segchk/domain/SegchkServiceComment.java | 111 ++ .../domain/SegchkServiceCommentUserReq.java | 89 + .../domain/SegchkServiceCommentWebResp.java | 116 ++ .../domain/SegchkServiceOrderChkResp.java | 138 ++ .../domain/SegchkServiceOrderChkTestResp.java | 222 +++ .../domain/SegchkServiceOrderWebReq.java | 112 ++ .../ruoyi/segchk/domain/SegchkSmsDetail.java | 95 + .../segchk/domain/SegchkStoreAccount.java | 154 ++ .../segchk/domain/SegchkStoreBasicInfo.java | 414 +++++ .../ruoyi/segchk/domain/SegchkStoreCash.java | 139 ++ .../segchk/domain/SegchkStoreCharge.java | 126 ++ .../segchk/domain/SegchkStoreChkMgt.java | 137 ++ .../ruoyi/segchk/domain/SegchkStoreImage.java | 265 +++ .../domain/SegchkStoreIndexWebResp.java | 209 +++ .../segchk/domain/SegchkStoreLableMgt.java | 139 ++ .../segchk/domain/SegchkStoreReward.java | 140 ++ .../segchk/domain/SegchkStoreSecurity.java | 97 ++ .../segchk/domain/SegchkStoreSelfMgt.java | 209 +++ .../segchk/domain/SegchkSystemSetting.java | 357 ++++ .../segchk/domain/SegchkUserAccount.java | 137 ++ .../segchk/domain/SegchkUserAccountCheck.java | 76 + .../segchk/domain/SegchkUserBasicInfo.java | 123 ++ .../ruoyi/segchk/domain/SegchkUserCash.java | 139 ++ .../segchk/domain/SegchkUserCashOpsReq.java | 124 ++ .../segchk/domain/SegchkUserCashOpsResp.java | 49 + .../segchk/domain/SegchkUserCashWebResp.java | 66 + .../domain/SegchkUserCertificationInfo.java | 139 ++ .../ruoyi/segchk/domain/SegchkUserCharge.java | 182 ++ .../segchk/domain/SegchkUserChargeCard.java | 153 ++ .../domain/SegchkUserChargeWebResp.java | 78 + .../segchk/domain/SegchkUserCollect.java | 131 ++ .../domain/SegchkUserCollectWebResp.java | 185 ++ .../segchk/domain/SegchkUserExtInfo.java | 97 ++ .../segchk/domain/SegchkUserLevelInfo.java | 77 + .../domain/SegchkUserLikeGoWebResp.java | 237 +++ .../ruoyi/segchk/domain/SegchkUserLikego.java | 153 ++ .../ruoyi/segchk/domain/SegchkUserReward.java | 140 ++ .../segchk/domain/SegchkUserRewardCtl.java | 112 ++ .../segchk/domain/SegchkUserSecurity.java | 97 ++ .../segchk/domain/SegchkUserSetInfoReq.java | 104 ++ .../ruoyi/segchk/domain/SegchkUserVip.java | 154 ++ .../segchk/domain/SegchkUserWebSCResp.java | 184 ++ .../ruoyi/segchk/domain/SegchkUserWechat.java | 124 ++ .../ruoyi/segchk/domain/SegchkVipSetInfo.java | 140 ++ .../segchk/mapper/SegchkCarouseMgtMapper.java | 66 + .../segchk/mapper/SegchkChargeCardMapper.java | 61 + .../segchk/mapper/SegchkCommentAccMapper.java | 61 + .../mapper/SegchkDistrictInfoMapper.java | 61 + .../mapper/SegchkIndexCarouseMapper.java | 62 + .../mapper/SegchkIndexStoreAccountMapper.java | 79 + .../mapper/SegchkIndexUserAccountMapper.java | 112 ++ .../mapper/SegchkIndexUserVipMapper.java | 39 + .../mapper/SegchkKeywordLableMapper.java | 61 + .../segchk/mapper/SegchkLableMgtMapper.java | 65 + .../mapper/SegchkLogionDetailMapper.java | 61 + .../segchk/mapper/SegchkMsgDetailMapper.java | 61 + .../mapper/SegchkPreferenceLableMapper.java | 61 + .../mapper/SegchkProviderMgtMapper.java | 92 + .../mapper/SegchkRecommenderIndexMapper.java | 66 + .../mapper/SegchkRecommenderStoreMapper.java | 63 + .../segchk/mapper/SegchkSalerInfoMapper.java | 61 + .../mapper/SegchkSelfServiceChkMapper.java | 61 + .../segchk/mapper/SegchkServiceChkMapper.java | 61 + .../mapper/SegchkServiceCommentMapper.java | 71 + .../segchk/mapper/SegchkSmsDetailMapper.java | 61 + .../mapper/SegchkStoreAccountMapper.java | 61 + .../mapper/SegchkStoreBasicInfoMapper.java | 168 ++ .../segchk/mapper/SegchkStoreCashMapper.java | 61 + .../mapper/SegchkStoreChargeMapper.java | 61 + .../mapper/SegchkStoreChkMgtMapper.java | 61 + .../segchk/mapper/SegchkStoreImageMapper.java | 61 + .../mapper/SegchkStoreLableMgtMapper.java | 65 + .../mapper/SegchkStoreRewardMapper.java | 61 + .../mapper/SegchkStoreSecurityMapper.java | 61 + .../mapper/SegchkStoreSelfMgtMapper.java | 69 + .../mapper/SegchkSystemSettingMapper.java | 108 ++ .../mapper/SegchkUserAccountMapper.java | 63 + .../mapper/SegchkUserBasicInfoMapper.java | 87 + .../segchk/mapper/SegchkUserCashMapper.java | 61 + .../SegchkUserCertificationInfoMapper.java | 61 + .../segchk/mapper/SegchkUserChargeMapper.java | 71 + .../mapper/SegchkUserCollectMapper.java | 61 + .../mapper/SegchkUserExtInfoMapper.java | 61 + .../segchk/mapper/SegchkUserLikegoMapper.java | 61 + .../mapper/SegchkUserRewardCtlMapper.java | 61 + .../segchk/mapper/SegchkUserRewardMapper.java | 61 + .../mapper/SegchkUserSecurityMapper.java | 61 + .../segchk/mapper/SegchkUserVipMapper.java | 61 + .../segchk/mapper/SegchkUserWechatMapper.java | 61 + .../segchk/mapper/SegchkVipSetInfoMapper.java | 61 + .../service/ISegchkCarouseMgtService.java | 65 + .../service/ISegchkChargeCardService.java | 61 + .../service/ISegchkCommentAccService.java | 61 + .../service/ISegchkDistrictInfoService.java | 61 + .../service/ISegchkKeywordLableService.java | 61 + .../service/ISegchkLableMgtService.java | 65 + .../service/ISegchkLogionDetailService.java | 61 + .../service/ISegchkMsgDetailService.java | 61 + .../ISegchkPreferenceLableService.java | 61 + .../service/ISegchkProviderMgtService.java | 66 + .../ISegchkRecommenderIndexService.java | 65 + .../ISegchkRecommenderStoreService.java | 63 + .../service/ISegchkSalerInfoService.java | 61 + .../service/ISegchkSelfServiceChkService.java | 61 + .../service/ISegchkServiceChkService.java | 61 + .../service/ISegchkServiceCommentService.java | 61 + .../service/ISegchkSmsDetailService.java | 61 + .../service/ISegchkStoreAccountService.java | 61 + .../service/ISegchkStoreBasicInfoService.java | 73 + .../service/ISegchkStoreCashService.java | 61 + .../service/ISegchkStoreChargeService.java | 61 + .../service/ISegchkStoreChkMgtService.java | 61 + .../service/ISegchkStoreImageService.java | 61 + .../service/ISegchkStoreLableMgtService.java | 65 + .../service/ISegchkStoreRewardService.java | 61 + .../service/ISegchkStoreSecurityService.java | 61 + .../service/ISegchkStoreSelfMgtService.java | 61 + .../service/ISegchkSystemSettingService.java | 103 ++ .../service/ISegchkUserAccountService.java | 63 + .../service/ISegchkUserBasicInfoService.java | 61 + .../service/ISegchkUserCashService.java | 61 + .../ISegchkUserCertificationInfoService.java | 61 + .../service/ISegchkUserChargeService.java | 61 + .../service/ISegchkUserCollectService.java | 69 + .../service/ISegchkUserExtInfoService.java | 61 + .../service/ISegchkUserLikegoService.java | 61 + .../service/ISegchkUserRewardCtlService.java | 61 + .../service/ISegchkUserRewardService.java | 61 + .../service/ISegchkUserSecurityService.java | 61 + .../segchk/service/ISegchkUserVipService.java | 61 + .../service/ISegchkUserWechatService.java | 61 + .../service/ISegchkVipSetInfoService.java | 61 + .../impl/SegchkCarouseMgtServiceImpl.java | 116 ++ .../impl/SegchkChargeCardServiceImpl.java | 125 ++ .../impl/SegchkCommentAccServiceImpl.java | 93 + .../impl/SegchkDistrictInfoServiceImpl.java | 93 + .../impl/SegchkKeywordLableServiceImpl.java | 111 ++ .../impl/SegchkLableMgtServiceImpl.java | 106 ++ .../impl/SegchkLogionDetailServiceImpl.java | 93 + .../impl/SegchkMsgDetailServiceImpl.java | 93 + .../SegchkPreferenceLableServiceImpl.java | 110 ++ .../impl/SegchkProviderMgtServiceImpl.java | 145 ++ .../SegchkRecommenderIndexServiceImpl.java | 99 ++ .../SegchkRecommenderStoreServiceImpl.java | 98 ++ .../impl/SegchkSalerInfoServiceImpl.java | 93 + .../impl/SegchkSelfServiceChkServiceImpl.java | 93 + .../impl/SegchkServiceChkServiceImpl.java | 93 + .../impl/SegchkServiceCommentServiceImpl.java | 93 + .../impl/SegchkSmsDetailServiceImpl.java | 95 + .../impl/SegchkStoreAccountServiceImpl.java | 93 + .../impl/SegchkStoreBasicInfoServiceImpl.java | 259 +++ .../impl/SegchkStoreCashServiceImpl.java | 93 + .../impl/SegchkStoreChargeServiceImpl.java | 93 + .../impl/SegchkStoreChkMgtServiceImpl.java | 93 + .../impl/SegchkStoreImageServiceImpl.java | 93 + .../impl/SegchkStoreLableMgtServiceImpl.java | 105 ++ .../impl/SegchkStoreRewardServiceImpl.java | 93 + .../impl/SegchkStoreSecurityServiceImpl.java | 93 + .../impl/SegchkStoreSelfMgtServiceImpl.java | 93 + .../impl/SegchkSystemSettingServiceImpl.java | 189 ++ .../impl/SegchkUserAccountServiceImpl.java | 99 ++ .../impl/SegchkUserBasicInfoServiceImpl.java | 130 ++ .../impl/SegchkUserCashServiceImpl.java | 93 + ...egchkUserCertificationInfoServiceImpl.java | 93 + .../impl/SegchkUserChargeServiceImpl.java | 97 ++ .../impl/SegchkUserCollectServiceImpl.java | 108 ++ .../impl/SegchkUserExtInfoServiceImpl.java | 93 + .../impl/SegchkUserLikegoServiceImpl.java | 95 + .../impl/SegchkUserRewardCtlServiceImpl.java | 93 + .../impl/SegchkUserRewardServiceImpl.java | 93 + .../impl/SegchkUserSecurityServiceImpl.java | 93 + .../impl/SegchkUserVipServiceImpl.java | 93 + .../impl/SegchkUserWechatServiceImpl.java | 93 + .../impl/SegchkVipSetInfoServiceImpl.java | 93 + .../com/ruoyi/system/domain/SysConfig.java | 111 ++ .../ruoyi/system/domain/SysLogininfor.java | 144 ++ .../com/ruoyi/system/domain/SysNotice.java | 100 ++ .../com/ruoyi/system/domain/SysOperLog.java | 255 +++ .../java/com/ruoyi/system/domain/SysPost.java | 123 ++ .../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 | 133 ++ .../ruoyi/system/mapper/SysConfigMapper.java | 68 + .../ruoyi/system/mapper/SysDeptMapper.java | 118 ++ .../system/mapper/SysDictDataMapper.java | 95 + .../system/mapper/SysDictTypeMapper.java | 85 + .../system/mapper/SysLogininforMapper.java | 42 + .../ruoyi/system/mapper/SysMenuMapper.java | 117 ++ .../ruoyi/system/mapper/SysNoticeMapper.java | 60 + .../ruoyi/system/mapper/SysOperLogMapper.java | 48 + .../ruoyi/system/mapper/SysPostMapper.java | 99 ++ .../system/mapper/SysRoleDeptMapper.java | 44 + .../ruoyi/system/mapper/SysRoleMapper.java | 107 ++ .../system/mapper/SysRoleMenuMapper.java | 44 + .../ruoyi/system/mapper/SysUserMapper.java | 127 ++ .../system/mapper/SysUserPostMapper.java | 44 + .../system/mapper/SysUserRoleMapper.java | 62 + .../system/service/ISysConfigService.java | 90 + .../ruoyi/system/service/ISysDeptService.java | 109 ++ .../system/service/ISysDictDataService.java | 61 + .../system/service/ISysDictTypeService.java | 99 ++ .../system/service/ISysLogininforService.java | 40 + .../ruoyi/system/service/ISysMenuService.java | 136 ++ .../system/service/ISysNoticeService.java | 60 + .../system/service/ISysOperLogService.java | 48 + .../ruoyi/system/service/ISysPostService.java | 100 ++ .../ruoyi/system/service/ISysRoleService.java | 166 ++ .../system/service/ISysUserOnlineService.java | 48 + .../ruoyi/system/service/ISysUserService.java | 199 +++ .../service/impl/SysConfigServiceImpl.java | 227 +++ .../service/impl/SysDeptServiceImpl.java | 307 ++++ .../service/impl/SysDictDataServiceImpl.java | 112 ++ .../service/impl/SysDictTypeServiceImpl.java | 220 +++ .../impl/SysLogininforServiceImpl.java | 65 + .../service/impl/SysMenuServiceImpl.java | 501 ++++++ .../service/impl/SysNoticeServiceImpl.java | 92 + .../service/impl/SysOperLogServiceImpl.java | 76 + .../service/impl/SysPostServiceImpl.java | 179 ++ .../service/impl/SysRoleServiceImpl.java | 401 +++++ .../impl/SysUserOnlineServiceImpl.java | 96 + .../service/impl/SysUserServiceImpl.java | 597 +++++++ .../mapper/segchk/SegchkCarouseMgtMapper.xml | 99 ++ .../mapper/segchk/SegchkChargeCardMapper.xml | 84 + .../mapper/segchk/SegchkCommentAccMapper.xml | 83 + .../segchk/SegchkDistrictInfoMapper.xml | 69 + .../segchk/SegchkIndexStoreAccountMapper.xml | 114 ++ .../segchk/SegchkIndexUserAccountMapper.xml | 139 ++ .../segchk/SegchkIndexUserVipMapper.xml | 43 + .../segchk/SegchkKeywordLableMapper.xml | 73 + .../mapper/segchk/SegchkLableMgtMapper.xml | 98 ++ .../segchk/SegchkLogionDetailMapper.xml | 72 + .../mapper/segchk/SegchkMsgDetailMapper.xml | 101 ++ .../segchk/SegchkPreferenceLableMapper.xml | 73 + .../mapper/segchk/SegchkProviderMgtMapper.xml | 149 ++ .../segchk/SegchkRecommenderIndexMapper.xml | 78 + .../segchk/SegchkRecommenderStoreMapper.xml | 83 + .../mapper/segchk/SegchkSalerInfoMapper.xml | 82 + .../segchk/SegchkSelfServiceChkMapper.xml | 77 + .../mapper/segchk/SegchkServiceChkMapper.xml | 93 + .../segchk/SegchkServiceCommentMapper.xml | 97 ++ .../mapper/segchk/SegchkSmsDetailMapper.xml | 77 + .../segchk/SegchkStoreAccountMapper.xml | 98 ++ .../segchk/SegchkStoreBasicInfoMapper.xml | 379 ++++ .../mapper/segchk/SegchkStoreCashMapper.xml | 82 + .../mapper/segchk/SegchkStoreChargeMapper.xml | 82 + .../mapper/segchk/SegchkStoreChkMgtMapper.xml | 87 + .../mapper/segchk/SegchkStoreImageMapper.xml | 141 ++ .../segchk/SegchkStoreLableMgtMapper.xml | 100 ++ .../mapper/segchk/SegchkStoreRewardMapper.xml | 93 + .../segchk/SegchkStoreSecurityMapper.xml | 72 + .../segchk/SegchkStoreSelfMgtMapper.xml | 120 ++ .../segchk/SegchkSystemSettingMapper.xml | 228 +++ .../mapper/segchk/SegchkUserAccountMapper.xml | 116 ++ .../segchk/SegchkUserBasicInfoMapper.xml | 113 ++ .../mapper/segchk/SegchkUserCashMapper.xml | 82 + .../SegchkUserCertificationInfoMapper.xml | 87 + .../mapper/segchk/SegchkUserChargeMapper.xml | 157 ++ .../mapper/segchk/SegchkUserCollectMapper.xml | 85 + .../mapper/segchk/SegchkUserExtInfoMapper.xml | 79 + .../mapper/segchk/SegchkUserLikegoMapper.xml | 92 + .../segchk/SegchkUserRewardCtlMapper.xml | 84 + .../mapper/segchk/SegchkUserRewardMapper.xml | 87 + .../segchk/SegchkUserSecurityMapper.xml | 72 + .../mapper/segchk/SegchkUserVipMapper.xml | 92 + .../mapper/segchk/SegchkUserWechatMapper.xml | 85 + .../mapper/segchk/SegchkVipSetInfoMapper.xml | 87 + .../mapper/system/SysConfigMapper.xml | 112 ++ .../resources/mapper/system/SysDeptMapper.xml | 154 ++ .../mapper/system/SysDictDataMapper.xml | 124 ++ .../mapper/system/SysDictTypeMapper.xml | 105 ++ .../mapper/system/SysLogininforMapper.xml | 57 + .../resources/mapper/system/SysMenuMapper.xml | 191 ++ .../mapper/system/SysNoticeMapper.xml | 89 + .../mapper/system/SysOperLogMapper.xml | 83 + .../resources/mapper/system/SysPostMapper.xml | 122 ++ .../mapper/system/SysRoleDeptMapper.xml | 34 + .../resources/mapper/system/SysRoleMapper.xml | 149 ++ .../mapper/system/SysRoleMenuMapper.xml | 34 + .../resources/mapper/system/SysUserMapper.xml | 217 +++ .../mapper/system/SysUserPostMapper.xml | 34 + .../mapper/system/SysUserRoleMapper.xml | 44 + ruoyi-ui/.editorconfig | 22 + ruoyi-ui/.env.development | 14 + ruoyi-ui/.env.production | 11 + ruoyi-ui/.env.staging | 10 + ruoyi-ui/.eslintignore | 10 + ruoyi-ui/.eslintrc.js | 199 +++ ruoyi-ui/.gitignore | 23 + ruoyi-ui/README.md | 30 + ruoyi-ui/alais-config.js | 14 + ruoyi-ui/babel.config.js | 13 + ruoyi-ui/bin/build.bat | 12 + ruoyi-ui/bin/package.bat | 12 + ruoyi-ui/bin/run-web.bat | 12 + ruoyi-ui/build/index.js | 36 + ruoyi-ui/package.json | 88 + ruoyi-ui/public/favicon.ico | Bin 0 -> 5663 bytes ruoyi-ui/public/html/ie.html | 46 + ruoyi-ui/public/index.html | 208 +++ ruoyi-ui/public/robots.txt | 2 + ruoyi-ui/src/App.vue | 19 + ruoyi-ui/src/api/login.js | 52 + ruoyi-ui/src/api/menu.js | 9 + ruoyi-ui/src/api/monitor/cache.js | 9 + ruoyi-ui/src/api/monitor/job.js | 80 + ruoyi-ui/src/api/monitor/jobLog.js | 35 + ruoyi-ui/src/api/monitor/logininfor.js | 35 + ruoyi-ui/src/api/monitor/online.js | 18 + ruoyi-ui/src/api/monitor/operlog.js | 35 + ruoyi-ui/src/api/monitor/server.js | 9 + ruoyi-ui/src/api/segchk/basicinfo.js | 43 + ruoyi-ui/src/api/segchk/segchk_carouse_mgt.js | 76 + ruoyi-ui/src/api/segchk/segchk_charge_card.js | 53 + ruoyi-ui/src/api/segchk/segchk_comment_acc.js | 53 + .../src/api/segchk/segchk_district_info.js | 53 + .../src/api/segchk/segchk_get_simple_list.js | 66 + .../src/api/segchk/segchk_keyword_lable.js | 53 + ruoyi-ui/src/api/segchk/segchk_lable_mgt.js | 68 + .../src/api/segchk/segchk_logion_detail.js | 53 + ruoyi-ui/src/api/segchk/segchk_msg_detail.js | 53 + .../src/api/segchk/segchk_preference_lable.js | 53 + .../src/api/segchk/segchk_provider_mgt.js | 65 + .../api/segchk/segchk_recommender_store.js | 67 + ruoyi-ui/src/api/segchk/segchk_saler_info.js | 67 + .../src/api/segchk/segchk_self_service_chk.js | 53 + ruoyi-ui/src/api/segchk/segchk_service_chk.js | 53 + .../src/api/segchk/segchk_service_comment.js | 53 + ruoyi-ui/src/api/segchk/segchk_sms_detail.js | 53 + .../src/api/segchk/segchk_store_account.js | 53 + .../src/api/segchk/segchk_store_basic_info.js | 77 + ruoyi-ui/src/api/segchk/segchk_store_cash.js | 53 + .../src/api/segchk/segchk_store_charge.js | 53 + .../src/api/segchk/segchk_store_chk_mgt.js | 53 + ruoyi-ui/src/api/segchk/segchk_store_image.js | 53 + .../src/api/segchk/segchk_store_lable_mgt.js | 66 + .../src/api/segchk/segchk_store_reward.js | 53 + .../src/api/segchk/segchk_store_security.js | 53 + .../src/api/segchk/segchk_store_self_mgt.js | 53 + .../src/api/segchk/segchk_system_setting.js | 53 + .../src/api/segchk/segchk_user_account.js | 53 + .../src/api/segchk/segchk_user_basic_info.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_cash.js | 53 + .../segchk/segchk_user_certification_info.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_charge.js | 53 + .../src/api/segchk/segchk_user_collect.js | 53 + .../src/api/segchk/segchk_user_ext_info.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_likego.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_reward.js | 53 + .../src/api/segchk/segchk_user_reward_ctl.js | 53 + .../src/api/segchk/segchk_user_security.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_vip.js | 53 + ruoyi-ui/src/api/segchk/segchk_user_wechat.js | 53 + .../src/api/segchk/segchk_vip_set_info.js | 53 + ruoyi-ui/src/api/system/config.js | 69 + ruoyi-ui/src/api/system/dept.js | 68 + ruoyi-ui/src/api/system/dict/data.js | 61 + ruoyi-ui/src/api/system/dict/type.js | 69 + ruoyi-ui/src/api/system/menu.js | 60 + ruoyi-ui/src/api/system/notice.js | 44 + ruoyi-ui/src/api/system/post.js | 53 + ruoyi-ui/src/api/system/role.js | 120 ++ ruoyi-ui/src/api/system/user.js | 144 ++ ruoyi-ui/src/api/tool/gen.js | 76 + ruoyi-ui/src/assets/401_images/401.gif | Bin 0 -> 164227 bytes ruoyi-ui/src/assets/404_images/404.png | Bin 0 -> 98071 bytes ruoyi-ui/src/assets/404_images/404_cloud.png | Bin 0 -> 4766 bytes ruoyi-ui/src/assets/icons/index.js | 9 + ruoyi-ui/src/assets/icons/svg/404.svg | 1 + ruoyi-ui/src/assets/icons/svg/bug.svg | 1 + ruoyi-ui/src/assets/icons/svg/build.svg | 1 + ruoyi-ui/src/assets/icons/svg/button.svg | 1 + ruoyi-ui/src/assets/icons/svg/cascader.svg | 1 + ruoyi-ui/src/assets/icons/svg/chart.svg | 1 + ruoyi-ui/src/assets/icons/svg/checkbox.svg | 1 + ruoyi-ui/src/assets/icons/svg/clipboard.svg | 1 + ruoyi-ui/src/assets/icons/svg/code.svg | 1 + ruoyi-ui/src/assets/icons/svg/color.svg | 1 + ruoyi-ui/src/assets/icons/svg/component.svg | 1 + ruoyi-ui/src/assets/icons/svg/dashboard.svg | 1 + ruoyi-ui/src/assets/icons/svg/date-range.svg | 1 + ruoyi-ui/src/assets/icons/svg/date.svg | 1 + ruoyi-ui/src/assets/icons/svg/dict.svg | 1 + .../src/assets/icons/svg/documentation.svg | 1 + ruoyi-ui/src/assets/icons/svg/download.svg | 1 + ruoyi-ui/src/assets/icons/svg/drag.svg | 1 + ruoyi-ui/src/assets/icons/svg/druid.svg | 1 + ruoyi-ui/src/assets/icons/svg/edit.svg | 1 + ruoyi-ui/src/assets/icons/svg/education.svg | 1 + ruoyi-ui/src/assets/icons/svg/email.svg | 1 + ruoyi-ui/src/assets/icons/svg/example.svg | 1 + ruoyi-ui/src/assets/icons/svg/excel.svg | 1 + .../src/assets/icons/svg/exit-fullscreen.svg | 1 + ruoyi-ui/src/assets/icons/svg/eye-open.svg | 1 + ruoyi-ui/src/assets/icons/svg/eye.svg | 1 + ruoyi-ui/src/assets/icons/svg/form.svg | 1 + ruoyi-ui/src/assets/icons/svg/fullscreen.svg | 1 + ruoyi-ui/src/assets/icons/svg/github.svg | 1 + ruoyi-ui/src/assets/icons/svg/guide.svg | 1 + ruoyi-ui/src/assets/icons/svg/icon.svg | 1 + ruoyi-ui/src/assets/icons/svg/input.svg | 1 + .../src/assets/icons/svg/international.svg | 1 + ruoyi-ui/src/assets/icons/svg/job.svg | 1 + ruoyi-ui/src/assets/icons/svg/language.svg | 1 + ruoyi-ui/src/assets/icons/svg/link.svg | 1 + ruoyi-ui/src/assets/icons/svg/list.svg | 1 + ruoyi-ui/src/assets/icons/svg/lock.svg | 1 + ruoyi-ui/src/assets/icons/svg/log.svg | 1 + ruoyi-ui/src/assets/icons/svg/logininfor.svg | 1 + ruoyi-ui/src/assets/icons/svg/message.svg | 1 + ruoyi-ui/src/assets/icons/svg/money.svg | 1 + ruoyi-ui/src/assets/icons/svg/monitor.svg | 2 + ruoyi-ui/src/assets/icons/svg/nested.svg | 1 + ruoyi-ui/src/assets/icons/svg/number.svg | 1 + ruoyi-ui/src/assets/icons/svg/online.svg | 1 + ruoyi-ui/src/assets/icons/svg/password.svg | 1 + ruoyi-ui/src/assets/icons/svg/pdf.svg | 1 + ruoyi-ui/src/assets/icons/svg/people.svg | 1 + ruoyi-ui/src/assets/icons/svg/peoples.svg | 1 + ruoyi-ui/src/assets/icons/svg/phone.svg | 1 + ruoyi-ui/src/assets/icons/svg/post.svg | 1 + ruoyi-ui/src/assets/icons/svg/qq.svg | 1 + ruoyi-ui/src/assets/icons/svg/question.svg | 1 + ruoyi-ui/src/assets/icons/svg/radio.svg | 1 + ruoyi-ui/src/assets/icons/svg/rate.svg | 1 + ruoyi-ui/src/assets/icons/svg/redis.svg | 1 + ruoyi-ui/src/assets/icons/svg/row.svg | 1 + ruoyi-ui/src/assets/icons/svg/search.svg | 1 + ruoyi-ui/src/assets/icons/svg/select.svg | 1 + ruoyi-ui/src/assets/icons/svg/server.svg | 1 + ruoyi-ui/src/assets/icons/svg/shopping.svg | 1 + ruoyi-ui/src/assets/icons/svg/size.svg | 1 + ruoyi-ui/src/assets/icons/svg/skill.svg | 1 + ruoyi-ui/src/assets/icons/svg/slider.svg | 1 + ruoyi-ui/src/assets/icons/svg/star.svg | 1 + ruoyi-ui/src/assets/icons/svg/swagger.svg | 1 + ruoyi-ui/src/assets/icons/svg/switch.svg | 1 + ruoyi-ui/src/assets/icons/svg/system.svg | 2 + ruoyi-ui/src/assets/icons/svg/tab.svg | 1 + ruoyi-ui/src/assets/icons/svg/table.svg | 1 + ruoyi-ui/src/assets/icons/svg/textarea.svg | 1 + ruoyi-ui/src/assets/icons/svg/theme.svg | 1 + ruoyi-ui/src/assets/icons/svg/time-range.svg | 1 + ruoyi-ui/src/assets/icons/svg/time.svg | 1 + ruoyi-ui/src/assets/icons/svg/tool.svg | 1 + ruoyi-ui/src/assets/icons/svg/tree-table.svg | 1 + ruoyi-ui/src/assets/icons/svg/tree.svg | 1 + ruoyi-ui/src/assets/icons/svg/upload.svg | 1 + ruoyi-ui/src/assets/icons/svg/user.svg | 1 + ruoyi-ui/src/assets/icons/svg/validCode.svg | 1 + ruoyi-ui/src/assets/icons/svg/wechat.svg | 1 + ruoyi-ui/src/assets/icons/svg/zip.svg | 1 + ruoyi-ui/src/assets/icons/svgo.yml | 22 + ruoyi-ui/src/assets/images/dark.svg | 39 + ruoyi-ui/src/assets/images/light.svg | 39 + .../src/assets/images/login-background.jpg | Bin 0 -> 521275 bytes ruoyi-ui/src/assets/images/profile.jpg | Bin 0 -> 81131 bytes ruoyi-ui/src/assets/logo/logo.png | Bin 0 -> 5663 bytes ruoyi-ui/src/assets/styles/btn.scss | 99 ++ ruoyi-ui/src/assets/styles/element-ui.scss | 92 + .../src/assets/styles/element-variables.scss | 31 + ruoyi-ui/src/assets/styles/index.scss | 191 ++ ruoyi-ui/src/assets/styles/mixin.scss | 66 + ruoyi-ui/src/assets/styles/ruoyi.scss | 266 +++ ruoyi-ui/src/assets/styles/sidebar.scss | 223 +++ ruoyi-ui/src/assets/styles/transition.scss | 48 + ruoyi-ui/src/assets/styles/variables.scss | 44 + ruoyi-ui/src/components/Breadcrumb/index.vue | 74 + ruoyi-ui/src/components/DictTag/index.vue | 51 + ruoyi-ui/src/components/Editor/index.vue | 277 +++ ruoyi-ui/src/components/FileUpload/index.vue | 198 +++ ruoyi-ui/src/components/Hamburger/index.vue | 44 + .../src/components/HeaderSearch/index.vue | 190 ++ ruoyi-ui/src/components/IconSelect/index.vue | 68 + .../src/components/IconSelect/requireIcons.js | 11 + ruoyi-ui/src/components/ImageUpload/index.vue | 213 +++ ruoyi-ui/src/components/Pagination/index.vue | 107 ++ ruoyi-ui/src/components/PanThumb/index.vue | 142 ++ ruoyi-ui/src/components/ParentView/index.vue | 3 + ruoyi-ui/src/components/RightPanel/index.vue | 149 ++ .../src/components/RightToolbar/index.vue | 87 + ruoyi-ui/src/components/RuoYi/Doc/index.vue | 21 + ruoyi-ui/src/components/RuoYi/Git/index.vue | 21 + ruoyi-ui/src/components/Screenfull/index.vue | 57 + ruoyi-ui/src/components/SizeSelect/index.vue | 57 + ruoyi-ui/src/components/SvgIcon/index.vue | 61 + ruoyi-ui/src/components/ThemePicker/index.vue | 174 ++ .../Tinymce/components/EditorImage.vue | 115 ++ .../components/Tinymce/dynamicLoadScript.js | 60 + ruoyi-ui/src/components/Tinymce/index.vue | 204 +++ ruoyi-ui/src/components/Tinymce/plugins.js | 7 + ruoyi-ui/src/components/Tinymce/toolbar.js | 6 + ruoyi-ui/src/components/TopNav/index.vue | 195 +++ .../src/components/Upload/multiUpload.vue | 96 + .../src/components/Upload/singleUpload.vue | 103 ++ ruoyi-ui/src/components/iFrame/index.vue | 36 + ruoyi-ui/src/directive/dialog/drag.js | 64 + ruoyi-ui/src/directive/index.js | 18 + ruoyi-ui/src/directive/permission/hasPermi.js | 28 + ruoyi-ui/src/directive/permission/hasRole.js | 28 + ruoyi-ui/src/layout/components/AppMain.vue | 57 + .../src/layout/components/InnerLink/index.vue | 27 + ruoyi-ui/src/layout/components/Navbar.vue | 200 +++ .../src/layout/components/Settings/index.vue | 268 +++ .../layout/components/Sidebar/FixiOSBug.js | 25 + .../src/layout/components/Sidebar/Item.vue | 29 + .../src/layout/components/Sidebar/Link.vue | 43 + .../src/layout/components/Sidebar/Logo.vue | 96 + .../layout/components/Sidebar/SidebarItem.vue | 96 + .../src/layout/components/Sidebar/index.vue | 57 + .../layout/components/TagsView/ScrollPane.vue | 94 + .../src/layout/components/TagsView/index.vue | 318 ++++ ruoyi-ui/src/layout/components/index.js | 5 + ruoyi-ui/src/layout/index.vue | 107 ++ ruoyi-ui/src/layout/mixin/ResizeHandler.js | 45 + ruoyi-ui/src/main.js | 88 + ruoyi-ui/src/permission.js | 53 + ruoyi-ui/src/router/index.js | 159 ++ ruoyi-ui/src/settings.js | 44 + ruoyi-ui/src/store/getters.js | 21 + ruoyi-ui/src/store/index.js | 27 + ruoyi-ui/src/store/modules/app.js | 56 + ruoyi-ui/src/store/modules/baseinfoset.js | 36 + ruoyi-ui/src/store/modules/permission.js | 113 ++ ruoyi-ui/src/store/modules/settings.js | 43 + ruoyi-ui/src/store/modules/tagsView.js | 183 ++ ruoyi-ui/src/store/modules/user.js | 110 ++ ruoyi-ui/src/utils/auth.js | 15 + ruoyi-ui/src/utils/errorCode.js | 6 + ruoyi-ui/src/utils/generator/config.js | 438 +++++ ruoyi-ui/src/utils/generator/css.js | 18 + .../src/utils/generator/drawingDefalut.js | 29 + ruoyi-ui/src/utils/generator/html.js | 359 ++++ ruoyi-ui/src/utils/generator/icon.json | 1 + ruoyi-ui/src/utils/generator/js.js | 236 +++ ruoyi-ui/src/utils/generator/render.js | 126 ++ ruoyi-ui/src/utils/index.js | 390 +++++ ruoyi-ui/src/utils/jsencrypt.js | 30 + ruoyi-ui/src/utils/permission.js | 51 + ruoyi-ui/src/utils/request.js | 106 ++ ruoyi-ui/src/utils/ruoyi.js | 174 ++ ruoyi-ui/src/utils/scroll-to.js | 58 + ruoyi-ui/src/utils/validate.js | 83 + ruoyi-ui/src/utils/zipdownload.js | 42 + .../views/components/icons/element-icons.js | 3 + ruoyi-ui/src/views/components/icons/index.vue | 87 + .../src/views/components/icons/svg-icons.js | 10 + ruoyi-ui/src/views/dashboard/BarChart.vue | 102 ++ ruoyi-ui/src/views/dashboard/LineChart.vue | 135 ++ ruoyi-ui/src/views/dashboard/PanelGroup.vue | 181 ++ ruoyi-ui/src/views/dashboard/PieChart.vue | 79 + ruoyi-ui/src/views/dashboard/RaddarChart.vue | 116 ++ ruoyi-ui/src/views/dashboard/mixins/resize.js | 56 + ruoyi-ui/src/views/error/401.vue | 88 + ruoyi-ui/src/views/error/404.vue | 233 +++ ruoyi-ui/src/views/index.vue | 683 ++++++++ ruoyi-ui/src/views/index_v1.vue | 98 ++ ruoyi-ui/src/views/login.vue | 217 +++ ruoyi-ui/src/views/monitor/cache/index.vue | 153 ++ ruoyi-ui/src/views/monitor/druid/index.vue | 15 + ruoyi-ui/src/views/monitor/job/index.vue | 523 ++++++ ruoyi-ui/src/views/monitor/job/log.vue | 328 ++++ .../src/views/monitor/logininfor/index.vue | 247 +++ ruoyi-ui/src/views/monitor/online/index.vue | 128 ++ ruoyi-ui/src/views/monitor/operlog/index.vue | 335 ++++ ruoyi-ui/src/views/monitor/server/index.vue | 210 +++ ruoyi-ui/src/views/redirect.vue | 12 + ruoyi-ui/src/views/register.vue | 208 +++ .../views/segchk/segchk_carouse_mgt/index.vue | 657 +++++++ .../views/segchk/segchk_charge_card/index.vue | 500 ++++++ .../views/segchk/segchk_comment_acc/index.vue | 422 +++++ .../segchk/segchk_district_info/index.vue | 311 ++++ .../segchk/segchk_keyword_lable/index.vue | 472 +++++ .../views/segchk/segchk_lable_mgt/index.vue | 708 ++++++++ .../segchk/segchk_logion_detail/index.vue | 346 ++++ .../views/segchk/segchk_msg_detail/index.vue | 451 +++++ .../segchk/segchk_preference_lable/index.vue | 481 ++++++ .../segchk/segchk_provider_mgt/index.vue | 663 +++++++ .../segchk/segchk_recommender_store/index.vue | 513 ++++++ .../views/segchk/segchk_saler_info/index.vue | 513 ++++++ .../segchk/segchk_self_service_chk/index.vue | 367 ++++ .../views/segchk/segchk_service_chk/index.vue | 403 +++++ .../segchk/segchk_service_comment/index.vue | 358 ++++ .../views/segchk/segchk_sms_detail/index.vue | 359 ++++ .../segchk/segchk_store_account/index.vue | 462 +++++ .../segchk/segchk_store_basic_info/index.vue | 1538 +++++++++++++++++ .../views/segchk/segchk_store_cash/index.vue | 470 +++++ .../segchk/segchk_store_charge/index.vue | 383 ++++ .../segchk/segchk_store_chk_mgt/index.vue | 491 ++++++ .../views/segchk/segchk_store_image/index.vue | 523 ++++++ .../segchk/segchk_store_lable_mgt/index.vue | 645 +++++++ .../segchk/segchk_store_reward/index.vue | 542 ++++++ .../segchk/segchk_store_security/index.vue | 349 ++++ .../segchk/segchk_store_self_mgt/index.vue | 484 ++++++ .../segchk_system_setting/basicSetting.vue | 200 +++ .../segchk_system_setting/basicinfo.vue | 223 +++ .../segchk/segchk_system_setting/index.vue | 256 +++ .../segchk/segchk_system_setting/index_1.vue | 511 ++++++ .../segchk/segchk_user_account/index.vue | 383 ++++ .../segchk/segchk_user_basic_info/index.vue | 448 +++++ .../views/segchk/segchk_user_cash/index.vue | 382 ++++ .../segchk_user_certification_info/index.vue | 393 +++++ .../views/segchk/segchk_user_charge/index.vue | 455 +++++ .../segchk/segchk_user_collect/index.vue | 385 +++++ .../segchk/segchk_user_ext_info/index.vue | 349 ++++ .../views/segchk/segchk_user_likego/index.vue | 413 +++++ .../views/segchk/segchk_user_reward/index.vue | 403 +++++ .../segchk/segchk_user_reward_ctl/index.vue | 547 ++++++ .../segchk/segchk_user_security/index.vue | 346 ++++ .../views/segchk/segchk_user_vip/index.vue | 440 +++++ .../views/segchk/segchk_user_wechat/index.vue | 377 ++++ .../segchk/segchk_vip_set_info/index.vue | 403 +++++ ruoyi-ui/src/views/system/config/index.vue | 366 ++++ ruoyi-ui/src/views/system/dept/index.vue | 317 ++++ ruoyi-ui/src/views/system/dict/data.vue | 406 +++++ ruoyi-ui/src/views/system/dict/index.vue | 370 ++++ ruoyi-ui/src/views/system/menu/index.vue | 442 +++++ ruoyi-ui/src/views/system/notice/index.vue | 339 ++++ ruoyi-ui/src/views/system/post/index.vue | 331 ++++ ruoyi-ui/src/views/system/role/authUser.vue | 213 +++ ruoyi-ui/src/views/system/role/index.vue | 643 +++++++ ruoyi-ui/src/views/system/role/selectUser.vue | 142 ++ ruoyi-ui/src/views/system/user/authRole.vue | 117 ++ ruoyi-ui/src/views/system/user/index.vue | 721 ++++++++ .../src/views/system/user/profile/index.vue | 91 + .../views/system/user/profile/resetPwd.vue | 72 + .../views/system/user/profile/userAvatar.vue | 172 ++ .../views/system/user/profile/userInfo.vue | 76 + .../src/views/tool/build/CodeTypeDialog.vue | 106 ++ .../src/views/tool/build/DraggableItem.vue | 100 ++ ruoyi-ui/src/views/tool/build/IconsDialog.vue | 123 ++ ruoyi-ui/src/views/tool/build/RightPanel.vue | 946 ++++++++++ .../src/views/tool/build/TreeNodeDialog.vue | 149 ++ ruoyi-ui/src/views/tool/build/index.vue | 794 +++++++++ ruoyi-ui/src/views/tool/gen/basicInfoForm.vue | 61 + ruoyi-ui/src/views/tool/gen/editTable.vue | 232 +++ ruoyi-ui/src/views/tool/gen/genInfoForm.vue | 300 ++++ ruoyi-ui/src/views/tool/gen/importTable.vue | 117 ++ ruoyi-ui/src/views/tool/gen/index.vue | 340 ++++ ruoyi-ui/src/views/tool/swagger/index.vue | 15 + ruoyi-ui/vue.config.js | 118 ++ ry.bat | 67 + ry.sh | 90 + sql/quartz.sql | 174 ++ sql/ry_20210731.sql | 687 ++++++++ wxpay-sdk/.gitignore | 23 + wxpay-sdk/LICENSE | 29 + wxpay-sdk/README.md | 220 +++ wxpay-sdk/pom.xml | 160 ++ .../src/main/java/com/weixin/pay/WXPay.java | 1355 +++++++++++++++ .../main/java/com/weixin/pay/WXPayConfig.java | 104 ++ .../java/com/weixin/pay/WXPayConfigImpl.java | 95 + .../main/java/com/weixin/pay/WXPayDomain.java | 45 + .../com/weixin/pay/WXPayDomainSimpleImpl.java | 117 ++ .../main/java/com/weixin/pay/WXPayReport.java | 267 +++ .../java/com/weixin/pay/WXPayRequest.java | 266 +++ .../com/weixin/pay/XxxWXPayConfigImpl.java | 95 + .../com/weixin/pay/card/CardBgColorEnum.java | 91 + .../com/weixin/pay/constants/WXConstants.java | 52 + .../weixin/pay/constants/WXPayCodeEnum.java | 39 + .../weixin/pay/constants/WXPayConstants.java | 248 +++ .../java/com/weixin/pay/constants/WXURL.java | 113 ++ .../com/weixin/pay/redis/RedisKeyEnum.java | 84 + .../com/weixin/pay/redis/RedisKeyUtil.java | 122 ++ .../java/com/weixin/pay/util/AESUtil.java | 121 ++ .../com/weixin/pay/util/DateTimeUtil.java | 159 ++ .../java/com/weixin/pay/util/WXPayUtil.java | 385 +++++ .../com/weixin/pay/util/WXPayXmlUtil.java | 43 + .../com/weixin/pay/util/WXSignatureUtil.java | 226 +++ .../java/com/weixin/pay/util/WXUserUtil.java | 41 + .../java/com/weixin/pay/util/WXUtils.java | 622 +++++++ .../src/main/test/controller/TestWXPay.java | 389 +++++ .../test/controller/WXAuthController.java | 107 ++ .../main/test/controller/WXPayController.java | 302 ++++ 1252 files changed, 157662 insertions(+) create mode 100644 .gitignore create mode 100644 .run/test#1.run.xml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bin/clean.bat create mode 100644 bin/package.bat create mode 100644 bin/run.bat create mode 100644 doc/若依环境使用手册.docx create mode 100644 java_sdk_v3.0.9/README.md create mode 100644 java_sdk_v3.0.9/pom.xml create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/IWXPayDomain.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPay.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConfig.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConstants.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayReport.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayRequest.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayUtil.java create mode 100644 java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayXmlUtil.java create mode 100644 libs/wxpay-sdk-0.0.1.jar create mode 100644 pom.xml create mode 100644 pom.xmlbak create mode 100644 pom1.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/security/SecurityConfig.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/filter/JwtAuthenticationTokenFilter.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/handle/AuthenticationEntryPointImpl.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/handle/LogoutSuccessHandlerImpl.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/Server.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Cpu.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Jvm.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Mem.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Sys.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/SysFile.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/exception/GlobalExceptionHandler.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/service/PermissionService.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysLoginService.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysPermissionService.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/security/web/service/UserDetailsServiceImpl.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/segchk/SegchkCarouseMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkChargeCardController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCommentAccController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkDistrictInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkKeywordLableController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLableMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLogionDetailController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkMsgDetailController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkPreferenceLableController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkProviderMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkRecommenderStoreController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSalerInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSelfServiceChkController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceChkController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceCommentController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSimpleListController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSmsDetailController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreAccountController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreBasicInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreCashController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChargeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChkMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreImageController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreLableMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreRewardController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSecurityController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSelfMgtController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSystemSettingController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserAccountController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserBasicInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCashController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCertificationInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserChargeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCollectController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserExtInfoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserLikegoController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardCtlController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserSecurityController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserVipController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserWechatController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkVipSetInfoController.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/SwaggerController.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/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/application-druid.yml create mode 100644 ruoyi-admin/src/main/resources/application-kaleprod.yml create mode 100644 ruoyi-admin/src/main/resources/application-test.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-common/pom.xml 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/UnAuth.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/Constants.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/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/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/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/UserStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.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/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/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/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/UserPasswordNotMatchException.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/ExceptionUtil.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/RedisCahceKey.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/SnowflakeIdWorker.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/VerifyCodeUtils.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/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/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/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/uuid/IdUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.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/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/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/web/service/SysRegisterService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.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/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/task/SegchkTask.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-segchk-web/pom.xml create mode 100644 ruoyi-segchk-web/src/main/docker/Dockerfile create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/AppletsAppApplication.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/AppletsLoginUtils.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/BaseResponse.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ErrorController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/GlobalWebExceptionHandler.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ResultCode.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/UnAuthorizedException.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/config/SecurityConfig.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/config/WebConfigurer.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/interceptor/AuthorityInterceptor.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/login/OssController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/login/SegChkLoginController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultIndexController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultProviderController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultStoreController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultUserController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/util/CommonController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/util/HtmlController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/util/IndexController.java create mode 100644 ruoyi-segchk-web/src/main/java/com/ruoyi/util/QrCodeController.java create mode 100644 ruoyi-segchk-web/src/main/resources/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/application-dev.yml create mode 100644 ruoyi-segchk-web/src/main/resources/application-prod.yml create mode 100644 ruoyi-segchk-web/src/main/resources/application-test.yml create mode 100644 ruoyi-segchk-web/src/main/resources/application-uat.yml create mode 100644 ruoyi-segchk-web/src/main/resources/application.yml create mode 100644 ruoyi-segchk-web/src/main/resources/http-client.private.env.json create mode 100644 ruoyi-segchk-web/src/main/resources/logback-spring.xml create mode 100644 ruoyi-segchk-web/src/main/resources/messages/messages.properties create mode 100644 ruoyi-segchk-web/src/main/resources/messages/messages_en_US.properties create mode 100644 ruoyi-segchk-web/src/main/resources/messages/messages_zh_CN.properties create mode 100644 ruoyi-segchk-web/src/main/resources/mybatis/mybatis-config.xml create mode 100644 ruoyi-segchk-web/src/main/resources/static/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/common/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/index/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/provider/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/store/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/default/user/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/static/img/bg.jpg create mode 100644 ruoyi-segchk-web/src/main/resources/static/img/checkret1.png create mode 100644 ruoyi-segchk-web/src/main/resources/static/wxpk/PwPaX4PqzG.txt create mode 100644 ruoyi-segchk-web/src/main/resources/templates/posters/bg.jpg create mode 100644 ruoyi-segchk-web/src/main/resources/templates/posters/checkret1.png create mode 100644 ruoyi-segchk-web/src/main/resources/test.http create mode 100644 ruoyi-segchk/pom.xml create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMember.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMemberLevel.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/mapper/WeChatCustomerLinkMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/LoginService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/RechargeService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterServiceApi.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/SmsService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatAppletLoginService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatCustomerLinkService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/BindNewEmailServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/LoginServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceApiImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SendTencentSms.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SmsServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatAppletLoginServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatCustomerLinkServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginInfo.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginRedisParamResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewEmailRequest.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewMobileRequest.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindParams.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/CustomerSearchCondition.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/ForgetPwdRequest.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/LoginParams.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/QueryCriteria.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UnAuthLoginParams.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePayPwdBean.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePwdBean.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/order/service/impl/PaySupplier.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/order/vo/OrderItem.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeRet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeReward.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkMsgWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleDetailWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentUserReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderWebReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreBasicInfoWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreIndexWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreVrReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreWebReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccountCheck.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeCard.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollectWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikeGoWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserSetInfoReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebCardResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebResp.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/StoreSelfCard.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/WeChatCustomerLink.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkProviderIndexMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreIndexMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkUserIndexMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkProviderIndexService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkStoreIndexService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCashService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCollectService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserIndexService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserLikegoService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserWechatService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/ISegchkStoreIndexServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkProviderIndexServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCashServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCollectServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserIndexServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserLikegoServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserWechatServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/AliPaySet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/OssSetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySetCommon.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PrePaySet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UnionPaySet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UploadData.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/WechatPaySet.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/KsdSmsReq.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsCity.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsDistrict.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsEmailSetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsProvince.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSmsSetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsStationLetter.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSystemSeo.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsWxCustomerLink.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SCommunityBuySetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SegchkPaySetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/AreaMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/BaseInfoSetMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsCityMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsDistrictMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsEmailSettingMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsProvinceMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSmsSettingMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsStationLetterMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSystemSeoMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsWxCustomerLinkMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/OssMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SCommunityBuySettingMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SegchkPaySettingMapper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/AreaService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/BaseInfoSetService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsCityService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsDistrictService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsEmailSettingService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsPaySettingService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsProvinceService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSmsSettingService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsStationLetterService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSystemSeoService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsWxCustomerLinkService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ISCommunityBuySettingService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/OssService.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/AreaServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/BaseInfoSetServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsCityServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsDistrictServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsEmailSettingServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsPaySettingServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsProvinceServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSmsSettingServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsStationLetterServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSystemSeoServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsWxCustomerLinkServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/OssServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/SCommunityBuySettingServiceImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/AreaItem.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/Locality.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/AesUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/BaseResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/Claims.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/CommonConstant.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/CommonResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/CustomHttpUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/Express100Utils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/Graphics2DUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/JaxbUtil.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/MarketingConstant.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/PageHelper.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/PosterUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/QRCodeUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/QRPostersUtil.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/QqOssClient.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/RandomMathLetter.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/RedisCacheErrorHandler.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/SegchkWXPayConfigImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/ShareCodeUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/SmsUtil.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/SnowflakeIdWorker.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/ThreadTask.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/UnionPayUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/VerifyCodeUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WXPayDomainSimpleImpl.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletLoginResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUserInfo.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WechatSetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/WechatUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/YunUploadUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AccessTokenResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AliPaySetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/BeanUtils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/CommonWebResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailConf.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailContent.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/LineColor.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/MonYunSmsResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoAfterPay.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoForPay.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OssYunConf.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/PrepayResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/RequestParam.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/SegUserProfile.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UnionPaySetting.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserConstants.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoProfile.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WeChatAppletCodeRequest.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatApletPrepayResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatNotifyResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponseForRecharge.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawRequest.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawResponse.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WxTransferResult.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5Utils.java create mode 100644 ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MessageSourceUtil.java create mode 100644 ruoyi-segchk/src/main/resources/mapper/member/WeChatCustomerLinkMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/segchk/SegchkProviderIndexMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/segchk/SegchkStoreIndexMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/segchk/SegchkUserIndexMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/AreaMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/BaseInfoSetMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsCityMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsDistrictMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsEmailSettingMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsProvinceMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsSmsSettingMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsStationLetterMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsSystemSeoMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/LsWxCustomerLinkMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/OssMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/SCommunityBuySettingMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/mapper/setting/SegchkPaySettingMapper.xml create mode 100644 ruoyi-segchk/src/main/resources/templates/posters/bg.jpg create mode 100644 ruoyi-segchk/src/main/resources/templates/posters/bigtitle.jpg create mode 100644 ruoyi-segchk/src/main/resources/templates/posters/checkret1.png create mode 100644 ruoyi-system/pom.xml create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/BaseInfoSet.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkBaseInfoSet.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkCarouseMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkChargeCard.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkChargeRet.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkCommentAcc.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkDistrictInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkKeywordLable.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkLableMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkLogionDetail.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkMsgDetail.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkMsgWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkPreferenceLable.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkProviderMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStore.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreLableWeb.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkSalerInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkSelfServiceChk.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleDetailWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceChk.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceComment.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentUserReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkTestResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderWebReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkSmsDetail.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreAccount.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreBasicInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreCash.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreCharge.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreChkMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreImage.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreIndexWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreLableMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreReward.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreSecurity.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkStoreSelfMgt.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkSystemSetting.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccount.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccountCheck.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserBasicInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCash.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCertificationInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCharge.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeCard.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollect.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollectWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserExtInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserLevelInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikeGoWebResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikego.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserReward.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserRewardCtl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserSecurity.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserSetInfoReq.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserVip.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebSCResp.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkUserWechat.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/domain/SegchkVipSetInfo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkCarouseMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkChargeCardMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkCommentAccMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkDistrictInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkIndexCarouseMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkIndexStoreAccountMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkIndexUserAccountMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkIndexUserVipMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkKeywordLableMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkLableMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkLogionDetailMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkMsgDetailMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkPreferenceLableMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkProviderMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkRecommenderIndexMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkRecommenderStoreMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkSalerInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkSelfServiceChkMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkServiceChkMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkServiceCommentMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkSmsDetailMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreAccountMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreBasicInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreCashMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreChargeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreChkMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreImageMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreLableMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreRewardMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreSecurityMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreSelfMgtMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkSystemSettingMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserAccountMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserBasicInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserCashMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserCertificationInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserChargeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserCollectMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserExtInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserLikegoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserRewardCtlMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserRewardMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserSecurityMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserVipMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkUserWechatMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/mapper/SegchkVipSetInfoMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkCarouseMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkChargeCardService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkCommentAccService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkDistrictInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkKeywordLableService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkLableMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkLogionDetailService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkMsgDetailService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkPreferenceLableService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkProviderMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkRecommenderIndexService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkRecommenderStoreService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkSalerInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkSelfServiceChkService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkServiceChkService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkServiceCommentService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkSmsDetailService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreAccountService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreBasicInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreCashService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreChargeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreChkMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreImageService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreLableMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreRewardService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreSecurityService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkStoreSelfMgtService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkSystemSettingService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserAccountService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserBasicInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserCashService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserCertificationInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserChargeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserCollectService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserExtInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserLikegoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserRewardCtlService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserRewardService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserSecurityService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserVipService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkUserWechatService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/ISegchkVipSetInfoService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkCarouseMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkChargeCardServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkCommentAccServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkDistrictInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkKeywordLableServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkLableMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkLogionDetailServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkMsgDetailServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkPreferenceLableServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkProviderMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkRecommenderIndexServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkRecommenderStoreServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkSalerInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkSelfServiceChkServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkServiceChkServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkServiceCommentServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkSmsDetailServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreAccountServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreBasicInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreCashServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreChargeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreChkMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreImageServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreLableMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreRewardServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreSecurityServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkStoreSelfMgtServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkSystemSettingServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserAccountServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserBasicInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCashServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCertificationInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserChargeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCollectServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserExtInfoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserLikegoServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserRewardCtlServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserRewardServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserSecurityServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserVipServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserWechatServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/segchk/service/impl/SegchkVipSetInfoServiceImpl.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/resources/mapper/segchk/SegchkCarouseMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkChargeCardMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkCommentAccMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkDistrictInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkIndexStoreAccountMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkIndexUserAccountMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkIndexUserVipMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkKeywordLableMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkLableMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkLogionDetailMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkMsgDetailMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkPreferenceLableMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkProviderMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkRecommenderIndexMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkRecommenderStoreMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkSalerInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkSelfServiceChkMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkServiceChkMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkServiceCommentMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkSmsDetailMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreAccountMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreBasicInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreCashMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreChargeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreChkMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreImageMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreLableMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreRewardMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreSecurityMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkStoreSelfMgtMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkSystemSettingMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserAccountMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserBasicInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserCashMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserCertificationInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserChargeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserCollectMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserExtInfoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserLikegoMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserRewardCtlMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserRewardMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserSecurityMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserVipMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkUserWechatMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/segchk/SegchkVipSetInfoMapper.xml 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-ui/.editorconfig create mode 100644 ruoyi-ui/.env.development create mode 100644 ruoyi-ui/.env.production create mode 100644 ruoyi-ui/.env.staging create mode 100644 ruoyi-ui/.eslintignore create mode 100644 ruoyi-ui/.eslintrc.js create mode 100644 ruoyi-ui/.gitignore create mode 100644 ruoyi-ui/README.md create mode 100644 ruoyi-ui/alais-config.js create mode 100644 ruoyi-ui/babel.config.js create mode 100644 ruoyi-ui/bin/build.bat create mode 100644 ruoyi-ui/bin/package.bat create mode 100644 ruoyi-ui/bin/run-web.bat create mode 100644 ruoyi-ui/build/index.js create mode 100644 ruoyi-ui/package.json create mode 100644 ruoyi-ui/public/favicon.ico create mode 100644 ruoyi-ui/public/html/ie.html create mode 100644 ruoyi-ui/public/index.html create mode 100644 ruoyi-ui/public/robots.txt create mode 100644 ruoyi-ui/src/App.vue create mode 100644 ruoyi-ui/src/api/login.js create mode 100644 ruoyi-ui/src/api/menu.js create mode 100644 ruoyi-ui/src/api/monitor/cache.js create mode 100644 ruoyi-ui/src/api/monitor/job.js create mode 100644 ruoyi-ui/src/api/monitor/jobLog.js create mode 100644 ruoyi-ui/src/api/monitor/logininfor.js create mode 100644 ruoyi-ui/src/api/monitor/online.js create mode 100644 ruoyi-ui/src/api/monitor/operlog.js create mode 100644 ruoyi-ui/src/api/monitor/server.js create mode 100644 ruoyi-ui/src/api/segchk/basicinfo.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_carouse_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_charge_card.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_comment_acc.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_district_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_get_simple_list.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_keyword_lable.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_lable_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_logion_detail.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_msg_detail.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_preference_lable.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_provider_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_recommender_store.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_saler_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_self_service_chk.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_service_chk.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_service_comment.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_sms_detail.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_account.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_basic_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_cash.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_charge.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_chk_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_image.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_lable_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_reward.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_security.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_store_self_mgt.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_system_setting.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_account.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_basic_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_cash.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_certification_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_charge.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_collect.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_ext_info.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_likego.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_reward.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_reward_ctl.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_security.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_vip.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_user_wechat.js create mode 100644 ruoyi-ui/src/api/segchk/segchk_vip_set_info.js create mode 100644 ruoyi-ui/src/api/system/config.js create mode 100644 ruoyi-ui/src/api/system/dept.js create mode 100644 ruoyi-ui/src/api/system/dict/data.js create mode 100644 ruoyi-ui/src/api/system/dict/type.js create mode 100644 ruoyi-ui/src/api/system/menu.js create mode 100644 ruoyi-ui/src/api/system/notice.js create mode 100644 ruoyi-ui/src/api/system/post.js create mode 100644 ruoyi-ui/src/api/system/role.js create mode 100644 ruoyi-ui/src/api/system/user.js create mode 100644 ruoyi-ui/src/api/tool/gen.js create mode 100644 ruoyi-ui/src/assets/401_images/401.gif create mode 100644 ruoyi-ui/src/assets/404_images/404.png create mode 100644 ruoyi-ui/src/assets/404_images/404_cloud.png create mode 100644 ruoyi-ui/src/assets/icons/index.js create mode 100644 ruoyi-ui/src/assets/icons/svg/404.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/bug.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/build.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/button.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/cascader.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/chart.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/checkbox.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/clipboard.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/code.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/color.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/component.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/dashboard.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/date-range.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/date.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/dict.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/documentation.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/download.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/drag.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/druid.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/edit.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/education.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/email.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/example.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/excel.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/exit-fullscreen.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/eye-open.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/eye.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/form.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/fullscreen.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/github.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/guide.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/icon.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/input.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/international.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/job.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/language.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/link.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/list.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/lock.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/log.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/logininfor.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/message.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/money.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/monitor.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/nested.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/number.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/online.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/password.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/pdf.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/people.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/peoples.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/phone.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/post.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/qq.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/question.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/radio.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/rate.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/redis.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/row.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/search.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/select.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/server.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/shopping.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/size.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/skill.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/slider.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/star.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/swagger.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/switch.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/system.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/tab.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/table.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/textarea.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/theme.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/time-range.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/time.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/tool.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/tree-table.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/tree.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/upload.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/user.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/validCode.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/wechat.svg create mode 100644 ruoyi-ui/src/assets/icons/svg/zip.svg create mode 100644 ruoyi-ui/src/assets/icons/svgo.yml create mode 100644 ruoyi-ui/src/assets/images/dark.svg create mode 100644 ruoyi-ui/src/assets/images/light.svg create mode 100644 ruoyi-ui/src/assets/images/login-background.jpg create mode 100644 ruoyi-ui/src/assets/images/profile.jpg create mode 100644 ruoyi-ui/src/assets/logo/logo.png create mode 100644 ruoyi-ui/src/assets/styles/btn.scss create mode 100644 ruoyi-ui/src/assets/styles/element-ui.scss create mode 100644 ruoyi-ui/src/assets/styles/element-variables.scss create mode 100644 ruoyi-ui/src/assets/styles/index.scss create mode 100644 ruoyi-ui/src/assets/styles/mixin.scss create mode 100644 ruoyi-ui/src/assets/styles/ruoyi.scss create mode 100644 ruoyi-ui/src/assets/styles/sidebar.scss create mode 100644 ruoyi-ui/src/assets/styles/transition.scss create mode 100644 ruoyi-ui/src/assets/styles/variables.scss create mode 100644 ruoyi-ui/src/components/Breadcrumb/index.vue create mode 100644 ruoyi-ui/src/components/DictTag/index.vue create mode 100644 ruoyi-ui/src/components/Editor/index.vue create mode 100644 ruoyi-ui/src/components/FileUpload/index.vue create mode 100644 ruoyi-ui/src/components/Hamburger/index.vue create mode 100644 ruoyi-ui/src/components/HeaderSearch/index.vue create mode 100644 ruoyi-ui/src/components/IconSelect/index.vue create mode 100644 ruoyi-ui/src/components/IconSelect/requireIcons.js create mode 100644 ruoyi-ui/src/components/ImageUpload/index.vue create mode 100644 ruoyi-ui/src/components/Pagination/index.vue create mode 100644 ruoyi-ui/src/components/PanThumb/index.vue create mode 100644 ruoyi-ui/src/components/ParentView/index.vue create mode 100644 ruoyi-ui/src/components/RightPanel/index.vue create mode 100644 ruoyi-ui/src/components/RightToolbar/index.vue create mode 100644 ruoyi-ui/src/components/RuoYi/Doc/index.vue create mode 100644 ruoyi-ui/src/components/RuoYi/Git/index.vue create mode 100644 ruoyi-ui/src/components/Screenfull/index.vue create mode 100644 ruoyi-ui/src/components/SizeSelect/index.vue create mode 100644 ruoyi-ui/src/components/SvgIcon/index.vue create mode 100644 ruoyi-ui/src/components/ThemePicker/index.vue create mode 100644 ruoyi-ui/src/components/Tinymce/components/EditorImage.vue create mode 100644 ruoyi-ui/src/components/Tinymce/dynamicLoadScript.js create mode 100644 ruoyi-ui/src/components/Tinymce/index.vue create mode 100644 ruoyi-ui/src/components/Tinymce/plugins.js create mode 100644 ruoyi-ui/src/components/Tinymce/toolbar.js create mode 100644 ruoyi-ui/src/components/TopNav/index.vue create mode 100644 ruoyi-ui/src/components/Upload/multiUpload.vue create mode 100644 ruoyi-ui/src/components/Upload/singleUpload.vue create mode 100644 ruoyi-ui/src/components/iFrame/index.vue create mode 100644 ruoyi-ui/src/directive/dialog/drag.js create mode 100644 ruoyi-ui/src/directive/index.js create mode 100644 ruoyi-ui/src/directive/permission/hasPermi.js create mode 100644 ruoyi-ui/src/directive/permission/hasRole.js create mode 100644 ruoyi-ui/src/layout/components/AppMain.vue create mode 100644 ruoyi-ui/src/layout/components/InnerLink/index.vue create mode 100644 ruoyi-ui/src/layout/components/Navbar.vue create mode 100644 ruoyi-ui/src/layout/components/Settings/index.vue create mode 100644 ruoyi-ui/src/layout/components/Sidebar/FixiOSBug.js create mode 100644 ruoyi-ui/src/layout/components/Sidebar/Item.vue create mode 100644 ruoyi-ui/src/layout/components/Sidebar/Link.vue create mode 100644 ruoyi-ui/src/layout/components/Sidebar/Logo.vue create mode 100644 ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue create mode 100644 ruoyi-ui/src/layout/components/Sidebar/index.vue create mode 100644 ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue create mode 100644 ruoyi-ui/src/layout/components/TagsView/index.vue create mode 100644 ruoyi-ui/src/layout/components/index.js create mode 100644 ruoyi-ui/src/layout/index.vue create mode 100644 ruoyi-ui/src/layout/mixin/ResizeHandler.js create mode 100644 ruoyi-ui/src/main.js create mode 100644 ruoyi-ui/src/permission.js create mode 100644 ruoyi-ui/src/router/index.js create mode 100644 ruoyi-ui/src/settings.js create mode 100644 ruoyi-ui/src/store/getters.js create mode 100644 ruoyi-ui/src/store/index.js create mode 100644 ruoyi-ui/src/store/modules/app.js create mode 100644 ruoyi-ui/src/store/modules/baseinfoset.js create mode 100644 ruoyi-ui/src/store/modules/permission.js create mode 100644 ruoyi-ui/src/store/modules/settings.js create mode 100644 ruoyi-ui/src/store/modules/tagsView.js create mode 100644 ruoyi-ui/src/store/modules/user.js create mode 100644 ruoyi-ui/src/utils/auth.js create mode 100644 ruoyi-ui/src/utils/errorCode.js create mode 100644 ruoyi-ui/src/utils/generator/config.js create mode 100644 ruoyi-ui/src/utils/generator/css.js create mode 100644 ruoyi-ui/src/utils/generator/drawingDefalut.js create mode 100644 ruoyi-ui/src/utils/generator/html.js create mode 100644 ruoyi-ui/src/utils/generator/icon.json create mode 100644 ruoyi-ui/src/utils/generator/js.js create mode 100644 ruoyi-ui/src/utils/generator/render.js create mode 100644 ruoyi-ui/src/utils/index.js create mode 100644 ruoyi-ui/src/utils/jsencrypt.js create mode 100644 ruoyi-ui/src/utils/permission.js create mode 100644 ruoyi-ui/src/utils/request.js create mode 100644 ruoyi-ui/src/utils/ruoyi.js create mode 100644 ruoyi-ui/src/utils/scroll-to.js create mode 100644 ruoyi-ui/src/utils/validate.js create mode 100644 ruoyi-ui/src/utils/zipdownload.js create mode 100644 ruoyi-ui/src/views/components/icons/element-icons.js create mode 100644 ruoyi-ui/src/views/components/icons/index.vue create mode 100644 ruoyi-ui/src/views/components/icons/svg-icons.js create mode 100644 ruoyi-ui/src/views/dashboard/BarChart.vue create mode 100644 ruoyi-ui/src/views/dashboard/LineChart.vue create mode 100644 ruoyi-ui/src/views/dashboard/PanelGroup.vue create mode 100644 ruoyi-ui/src/views/dashboard/PieChart.vue create mode 100644 ruoyi-ui/src/views/dashboard/RaddarChart.vue create mode 100644 ruoyi-ui/src/views/dashboard/mixins/resize.js create mode 100644 ruoyi-ui/src/views/error/401.vue create mode 100644 ruoyi-ui/src/views/error/404.vue create mode 100644 ruoyi-ui/src/views/index.vue create mode 100644 ruoyi-ui/src/views/index_v1.vue create mode 100644 ruoyi-ui/src/views/login.vue create mode 100644 ruoyi-ui/src/views/monitor/cache/index.vue create mode 100644 ruoyi-ui/src/views/monitor/druid/index.vue create mode 100644 ruoyi-ui/src/views/monitor/job/index.vue create mode 100644 ruoyi-ui/src/views/monitor/job/log.vue create mode 100644 ruoyi-ui/src/views/monitor/logininfor/index.vue create mode 100644 ruoyi-ui/src/views/monitor/online/index.vue create mode 100644 ruoyi-ui/src/views/monitor/operlog/index.vue create mode 100644 ruoyi-ui/src/views/monitor/server/index.vue create mode 100644 ruoyi-ui/src/views/redirect.vue create mode 100644 ruoyi-ui/src/views/register.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_carouse_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_charge_card/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_comment_acc/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_district_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_keyword_lable/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_lable_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_logion_detail/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_msg_detail/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_preference_lable/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_provider_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_recommender_store/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_saler_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_self_service_chk/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_service_chk/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_service_comment/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_sms_detail/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_account/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_basic_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_cash/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_charge/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_chk_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_image/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_lable_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_reward/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_security/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_store_self_mgt/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_system_setting/basicSetting.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_system_setting/basicinfo.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_system_setting/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_system_setting/index_1.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_account/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_basic_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_cash/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_certification_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_charge/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_collect/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_ext_info/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_likego/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_reward/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_reward_ctl/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_security/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_vip/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_user_wechat/index.vue create mode 100644 ruoyi-ui/src/views/segchk/segchk_vip_set_info/index.vue create mode 100644 ruoyi-ui/src/views/system/config/index.vue create mode 100644 ruoyi-ui/src/views/system/dept/index.vue create mode 100644 ruoyi-ui/src/views/system/dict/data.vue create mode 100644 ruoyi-ui/src/views/system/dict/index.vue create mode 100644 ruoyi-ui/src/views/system/menu/index.vue create mode 100644 ruoyi-ui/src/views/system/notice/index.vue create mode 100644 ruoyi-ui/src/views/system/post/index.vue create mode 100644 ruoyi-ui/src/views/system/role/authUser.vue create mode 100644 ruoyi-ui/src/views/system/role/index.vue create mode 100644 ruoyi-ui/src/views/system/role/selectUser.vue create mode 100644 ruoyi-ui/src/views/system/user/authRole.vue create mode 100644 ruoyi-ui/src/views/system/user/index.vue create mode 100644 ruoyi-ui/src/views/system/user/profile/index.vue create mode 100644 ruoyi-ui/src/views/system/user/profile/resetPwd.vue create mode 100644 ruoyi-ui/src/views/system/user/profile/userAvatar.vue create mode 100644 ruoyi-ui/src/views/system/user/profile/userInfo.vue create mode 100644 ruoyi-ui/src/views/tool/build/CodeTypeDialog.vue create mode 100644 ruoyi-ui/src/views/tool/build/DraggableItem.vue create mode 100644 ruoyi-ui/src/views/tool/build/IconsDialog.vue create mode 100644 ruoyi-ui/src/views/tool/build/RightPanel.vue create mode 100644 ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue create mode 100644 ruoyi-ui/src/views/tool/build/index.vue create mode 100644 ruoyi-ui/src/views/tool/gen/basicInfoForm.vue create mode 100644 ruoyi-ui/src/views/tool/gen/editTable.vue create mode 100644 ruoyi-ui/src/views/tool/gen/genInfoForm.vue create mode 100644 ruoyi-ui/src/views/tool/gen/importTable.vue create mode 100644 ruoyi-ui/src/views/tool/gen/index.vue create mode 100644 ruoyi-ui/src/views/tool/swagger/index.vue create mode 100644 ruoyi-ui/vue.config.js create mode 100644 ry.bat create mode 100644 ry.sh create mode 100644 sql/quartz.sql create mode 100644 sql/ry_20210731.sql create mode 100644 wxpay-sdk/.gitignore create mode 100644 wxpay-sdk/LICENSE create mode 100644 wxpay-sdk/README.md create mode 100644 wxpay-sdk/pom.xml create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPay.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayConfig.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayConfigImpl.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayDomain.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayDomainSimpleImpl.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayReport.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/WXPayRequest.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/XxxWXPayConfigImpl.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/card/CardBgColorEnum.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/constants/WXConstants.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/constants/WXPayCodeEnum.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/constants/WXPayConstants.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/constants/WXURL.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/redis/RedisKeyEnum.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/redis/RedisKeyUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/AESUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/DateTimeUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/WXPayUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/WXPayXmlUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/WXSignatureUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/WXUserUtil.java create mode 100644 wxpay-sdk/src/main/java/com/weixin/pay/util/WXUtils.java create mode 100644 wxpay-sdk/src/main/test/controller/TestWXPay.java create mode 100644 wxpay-sdk/src/main/test/controller/WXAuthController.java create mode 100644 wxpay-sdk/src/main/test/controller/WXPayController.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..095aa77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +###################################################################### +# 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 + +### NetBeans ### +nbproject/private/ +build/* +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +###################################################################### +# Others +*.log +*.xml.versionsBackup +*.swp + +!*/build/*.java +!*/build/*.html +!*/build/*.xml +/logs/ diff --git a/.run/test#1.run.xml b/.run/test#1.run.xml new file mode 100644 index 0000000..67e0c24 --- /dev/null +++ b/.run/test#1.run.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file 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/README.md b/README.md new file mode 100644 index 0000000..f1ec311 --- /dev/null +++ b/README.md @@ -0,0 +1,85 @@ +## 平台简介 + +若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 + +* 前端采用Vue、Element UI。 +* 后端采用Spring Boot、Spring Security、Redis & Jwt。 +* 权限认证使用Jwt,支持多终端认证系统。 +* 支持加载动态权限菜单,多方式轻松权限控制。 +* 高效率开发,使用代码生成器可以一键生成前后端代码。 +* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。 +* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) +* 特别鸣谢:[element](https://github.com/ElemeFE/element),[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://github.com/elunez/eladmin-web)。 +* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)   +* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)   + +## 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 通知公告:系统通知公告信息发布维护。 +9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +10. 登录日志:系统登录日志记录查询包含登录异常。 +11. 在线用户:当前系统中活跃用户状态监控。 +12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 +13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 +14. 系统接口:根据业务代码自动生成相关的api接口文档。 +15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 +16. 缓存监控:对系统的缓存信息查询,命令统计等。 +17. 在线构建器:拖动表单元素生成相应的HTML代码。 +18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 + +## 在线体验 + +- admin/admin123 +- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。 + +演示地址:http://vue.ruoyi.vip +文档地址:http://doc.ruoyi.vip + +## 演示图 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +## 若依前后端分离交流群 + +QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) 点击按钮入群。 \ No newline at end of file diff --git a/bin/clean.bat b/bin/clean.bat new file mode 100644 index 0000000..24c0974 --- /dev/null +++ b/bin/clean.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] target· +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean + +pause \ No newline at end of file diff --git a/bin/package.bat b/bin/package.bat new file mode 100644 index 0000000..c693ec0 --- /dev/null +++ b/bin/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] Weḅwar/jarļ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean package -Dmaven.test.skip=true + +pause \ No newline at end of file diff --git a/bin/run.bat b/bin/run.bat new file mode 100644 index 0000000..41efbd0 --- /dev/null +++ b/bin/run.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarWeb̡ +echo. + +cd %~dp0 +cd ../ruoyi-admin/target + +set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -jar %JAVA_OPTS% ruoyi-admin.jar + +cd bin +pause \ No newline at end of file diff --git a/doc/若依环境使用手册.docx b/doc/若依环境使用手册.docx new file mode 100644 index 0000000000000000000000000000000000000000..9e4daef4d9be2e445419109a02eaf321cd4d537e GIT binary patch literal 428430 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 +HtCx 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 Rli)_iWGz7fMupr%QDEgRC> z`GMjf4QA8>dNe?Fon+;^v5|)<{`$*+r4CjI&L~yC{C+=ED$DHFe-xzC2jv zHJ54IsMFeeI8;)niO+*v3z?@I;VX0}`AQboc*+Cd!+FQj`t!*zR!B!2_aE z9mr{pOJoKKCc8uale@S_qRo)7W#n5_RBg0BCq*>W{*^A=xot*0qvbn)bybr5co05R zOdqP@-e|f6~N@%O6UY@@R{rF$? zkdHkb&Ob#~@;?A^Wbm(#NDv-?2!bjiblbl+jYF1!vjjsrz0%-_N+JAT$rJA%CoGKY z4_trhTL@ru>JDE%uPsQ%gYaO)`tzsV{rjK$v(Jz?i0fi6j>?mY4GzZnhT`x*>$yX= z%*E-u2W{Z+nP9P!%6u2O)f;WyneV&u8z*1%x-Y@jHC=TL8Mk2F`z;7Jg<3rBc zxdpb|l05%F#xIb=k8@ZoovqT|Gb2jwZ|WjY{1BLwKZQDuSb9C)X&myS_w|hQ9#*N7 z6|e?=FHvVah}c=JZ%5Zci{p9tsqbE2K&M&=B0edRYW(vmn|@m^R|NJ<;w!iDq+hZl zag(9Iry#Gj7?wvo#CBIECkd^`a%QF#8S572p;wlh6^ajcPGYhM+3@&w7Z4oMczA*M z^fa}rjj1G}Hl5<$SqTSk5}KgB(8v;)?n)}tA!|>t?f)n7oC+zEJ+FjYdyj&;@ea#< zukAeeWM%yInp_pc&M*_Q#t@qX7{xXk>t9b;YCl1of8J}*s6B5tcJUCSCjuXeTpI+IX@Ci#h}Eieu=l>*L}W2To58g`)=Wym|?_mdn6*czq4e=K9vidP9;|EkY7Py0GEzTF6H8jdv9C==3!%l) zW?XU%%fqG=QKd+eZN{o|YlR_4#rv4&a#sZyQ2Q=F`8)`zeRSsXsaLADR}yzi^4ou} zWRjLbdax{8Ol9(x)4puEMpCIjorixI^{9Zz!@!T-mL=rdF;69nb9*4!K(Hn6@3t62 zBGv&W{~fD;cPr^8wmF)Bvt#=IAnYx};%b^LPzDI@1Pks#f@^?4LV~*v?h@Qx28ZCT zL4vylcMtCF?iSqd<~{bEbMLw52M;{#-aUJESFc)CwYnScVLU7+VJi4!0<3}6V#J9|B+!+EgIh%$4IFYzy6m_~$xT!wuI-Jg3}!lT zrbgeH8bj$~+fm^+S$9l@%&dB2J`Ouhj^^&%i-bxaF7QsmI5HgkHs8aGvUc3)RI`)O zC@GkwH|EWp`ylhXp5Wor!?LRK+P^2Xio^ajokifoH?Z@qylqo4<0O=ai2Huh+QxruPVRDoEgKaRcD3x#kGUWFfbEC{a zCqlo5(i9Y#X3FB2ja?~Ji-PFilX-SRR_Ui5$q05yt$EVMt}J)9U&m*n_M$_;o^M*nGcy^u+} z9o`;H6s)_q=U#SE948kIc>Tb3LQp_q%zI0zN70wv$heIcg{eGm6BCourqfoPmxEbg zhv)Mh!I6I)z^~Wz*yP#*s}uHSv1fGAf5wH;;P(=nLlT$ zgu>c}kwre0nxdy_SLOz2(p?(rgn{+e5-6>rDKI}TVm0j>skzSUc>QHA4BOoGPyd_$ zeL<dimmKa_9PS=7giuE7LRm^}NaU2iwqv%;-Eex1b zn5i3_6Gx9W{=8USERLF4F7*ksvBh?%OmhUM!@(2UD)zVUX1aT6qOAjEvMuO+^u@W? zJN`m5Do;u?T%xfe1~jvU$i~O)HdNj5x-FMG_JI#(s5$M~AqD+@CBO7_#W?&M2u7Va z3A_1CBaa@D#oYfkJZt4hirCmn)6E(e^gn3G52yTXFO6*YP?;Lpylkb3OdgJ^-|=0j zi%#N|4|cN{zF|CDNMt%533X%061@GE6m0Bf@0 zu^_M+gklO@P9Tt^kNr)dd7v8mTb>L^7~u$D17SM8`v+daCW*=@S{a6*O~v94sdTLO zDwVq9nhHt+G~(+T!Z9ks0VIXuT<^h6wVI^LsS_s-oLL&0*qM9$HgocK3J3ym%#IF2 zw5o zf7I-aDc%E0Fw%I5@4C4_H7BT4BN$&MdV*F|4QYO;GA6MK+tVRPQwSIf6G0;3-N$JUN6)RlBI*`~{OC@VT9Y=fdEo?6GT`}s?4A^o=(TqKTV*e+9 z-?C(*VH4-R&hCI4Hu4T4PSyu0+otcUlhg3pf_)=D1?V=ozN4Pb_iphQl2=fsnI6~t zIJzB2sE~(+{h`GOw$^u4?{Lf63BmlNzvK2@GcIY+>44HS)ZfHnD}mQaq5p^vEB2}O zTBcmT+w009z$aBCHvzV;p|d-!AdHPZHiu@Q$Jcc$&z3845ncI%PCr_+*WMM3LXEpbx1FDkhs{f^}CmqM9gG1Tfz{!E1}byW3qR)hqEye;^IISuWVmJ*yJ zj@H1(ge)?kEY+6OCa>3ysF<0xSFjpMs%)G2DmrK1+l1V0`WB zTe^Xins6M%iB(n-_qUYSO5VU%^O|D91JQ^l$t7={{6jape+V7N|MAEun+a+^yzzJY z-ji8-;tq2tZQDW`IrH>XO4!g@;Zj=MJ*f((rAo6fJm{()9vd1BMXmhZD20pJgb^!` z&q{rfcIV)_3im@U{cM^ov39ccc4Y*f;r+Z)+#q}?B9}cuCi`>}5a95@km_5bw1G3HH+3sdDSkYCe&+5&@g;MVRhJVbzC95HB&H$ z>t=p^Yi7IfdpqK1l?*e_h^<@c0MRakhe|)X_ib0X)qH1$a%YAj)`ehYcFxx7_2a{A z+p}YjqrWT0`}ffQmSTDT-i#reZkF$0(!4JxshJPQ^>l=u$X2JxX}Icov=Mhq>X#hB zsUzeK#(Ns*1jJhZX(z?Jq$JnU;@XJR)st?^1y)zW&(``#<8JTzCYu{_Y`UM0sz)2o zkMDLfoE1@wUV$76mI@T$Lm2!D#Za(H7;;JU^6N|%uRIzGC@W;61HT|b>6k#ewHnUv zACe4d5C8O!R?<}j%7<_C9m>f+t)aQ^|G8<40Pqw1<}CI9$SDw(_F!I_b(9J0GwFfE zyIA;qhQt3|uv%>EKx!im1@-!a12l8Cwlie5G&20I$Nb$=&%}uLf6=Qt1B+!V5ukxP zaIy7XyZ=9z&PwC_hh7y~Q_1N0C4&GXG!?_#SUmyNFgV#sgPb{89`ZD$^4aMIuko%+ zC-2LZ{jt7t5oc9qXj4T>v=u_l4{jUr3*7oA%wYv5`-0!n>^O)xaf3sTZKJ&GUF~Vf zyzKTT7XszgM+l>?OsA*p8R@&cyB;Jzd-Ta$Nf=&KqFFh4`5C9uJNkE!UsQiv4#z5b z4r7%ILyHN0hFw@(R4rA%8WTqMkxP;?#(o?{5gcy&{oBFOi8ZJ&I~ykE>JU%9>E?o9 z(&X}VmGqrlO^cU{2md0Lzzf{+fifcI&IGzz9!G7>rtON zyk^sWe7;$aWmFoT-rrG~H}BNZZhg3Y-X2|Ud)#dCe+0jfTqFyuGMHbt>Tz(V#9x`N z2#nTwG&3ik;>=v%Pkn4P()~!aHXVj&^W?OFaClS9@bh6aou&b=0vnc01E_`u)B! zk6=fKua@v+B>2QLzU7_GUGqKMpEQ}VJ>4AgjGra($Hrd=+_D_uOh`+|)RJm63vdkC zc0)77H`O2BmN%)?ddzj8UAU*ccb!INsU(Fhp@+e$wps7Qq}=oWGi`g47C_vfY1VSv zS(NF0C=z~uN`Q^`j5~7LStjw$Xzsk%`(?9cRphJAd8F2iwSHvDp5gj;g%K}hi&f>a z&L4_u%YP`SPiT3`SPO%Y!fNku#A_HZhf>6>yw(%!6e`~Li1J?^N)+GIi?61zT2&ls zu1P-VU*zB%U7D>(RZXun-VX8g7d0+(h8tcV&!oDQRo$J05>q8>d!c{0In&}OepB6F zs{pqhdBvC9rjE^WDU+yd-Sq5royh#*okTBH+wYAL(9qXYc{z@P>4T&?wbt?34{ zdA&6mglmZ$s3c-SNYF|~M_4ec7TiYZ)|1g?GohB2vZY9oQuUtg;epq+OxG6X#|zJ% zyL~Sw;B(hWjXS;se%AhPpZu&nn)Wz z_@Zo`QF4p9qR5_^Uoj*EQ4?=+WK^PsqOgCCITM1Oz#O}X!!H=`8CeT0O(c0ZY)|qZhbberDXfVVh;cKLZ%Ah&?6iD!DSN9PbWG(iT>u`2)mV^rm= z_g>g8s!rPgtE${>dY#KDVGqG;JaH`E~Ny<#SLq zdnqL`eWF#6K{`FeTNK(0V{CSM+7S>xt+utL^BNDQY}0egCBNJajwPjvpy4mQD45UY zBF|K34|?n`P1`VOHU~b9>2cW`ercn3xYi?FcQ0`qP5rhthG{HNXDjLY!JTeT%+f01 zi2&b?yMHx6yX<3lgXhFpFY$Hi{Lz{($BTL5RU!FUbcU+(BA(nki8it?%$MoUS^Zp^ z2TV5(Y68Tp9cLIc604k7Zg4?`%0DfC-!Au^tv1-R|XemvERC8O1`5!u;Z5%iD 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

K#u)l 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

)q;tSdIrAwYxlSM|Hl};Y` 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 literal 0 HcmV?d00001 diff --git a/java_sdk_v3.0.9/README.md b/java_sdk_v3.0.9/README.md new file mode 100644 index 0000000..38d4c0f --- /dev/null +++ b/java_sdk_v3.0.9/README.md @@ -0,0 +1,298 @@ +微信支付 Java SDK +------ + +对[微信支付开发者文档](https://pay.weixin.qq.com/wiki/doc/api/index.html)中给出的API进行了封装。 + +com.github.wxpay.sdk.WXPay类下提供了对应的方法: + +|方法名 | 说明 | +|--------|--------| +|microPay| 刷卡支付 | +|unifiedOrder | 统一下单| +|orderQuery | 查询订单 | +|reverse | 撤销订单 | +|closeOrder|关闭订单| +|refund|申请退款| +|refundQuery|查询退款| +|downloadBill|下载对账单| +|report|交易保障| +|shortUrl|转换短链接| +|authCodeToOpenid|授权码查询openid| + +* 注意: +* 证书文件不能放在web服务器虚拟目录,应放在有访问权限控制的目录中,防止被他人下载 +* 建议将证书文件名改为复杂且不容易猜测的文件名 +* 商户服务器要做好病毒和木马防护工作,不被非法侵入者窃取证书文件 +* 请妥善保管商户支付密钥、公众帐号SECRET,避免密钥泄露 +* 参数为`Map`对象,返回类型也是`Map` +* 方法内部会将参数会转换成含有`appid`、`mch_id`、`nonce_str`、`sign\_type`和`sign`的XML +* 可选HMAC-SHA256算法和MD5算法签名 +* 通过HTTPS请求得到返回数据后会对其做必要的处理(例如验证签名,签名错误则抛出异常) +* 对于downloadBill,无论是否成功都返回Map,且都含有`return_code`和`return_msg`,若成功,其中`return_code`为`SUCCESS`,另外`data`对应对账单数据 + + +## 示例 +配置类MyConfig: +```java +import com.github.wxpay.sdk.WXPayConfig; +import java.io.*; + +public class MyConfig implements WXPayConfig{ + + private byte[] certData; + + public MyConfig() throws Exception { + String certPath = "/path/to/apiclient_cert.p12"; + File file = new File(certPath); + InputStream certStream = new FileInputStream(file); + this.certData = new byte[(int) file.length()]; + certStream.read(this.certData); + certStream.close(); + } + + public String getAppID() { + return "wx8888888888888888"; + } + + public String getMchID() { + return "12888888"; + } + + public String getKey() { + return "88888888888888888888888888888888"; + } + + public InputStream getCertStream() { + ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData); + return certBis; + } + + public int getHttpConnectTimeoutMs() { + return 8000; + } + + public int getHttpReadTimeoutMs() { + return 10000; + } +} +``` + +统一下单: + +```java +import com.github.wxpay.sdk.WXPay; + +import java.util.HashMap; +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map data = new HashMap(); + data.put("body", "腾讯充值中心-QQ会员充值"); + data.put("out_trade_no", "2016090910595900000012"); + data.put("device_info", ""); + data.put("fee_type", "CNY"); + data.put("total_fee", "1"); + data.put("spbill_create_ip", "123.12.12.123"); + data.put("notify_url", "http://www.example.com/wxpay/notify"); + data.put("trade_type", "NATIVE"); // 此处指定为扫码支付 + data.put("product_id", "12"); + + try { + Map resp = wxpay.unifiedOrder(data); + System.out.println(resp); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +订单查询: +```java +import com.github.wxpay.sdk.WXPay; + +import java.util.HashMap; +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map data = new HashMap(); + data.put("out_trade_no", "2016090910595900000012"); + + try { + Map resp = wxpay.orderQuery(data); + System.out.println(resp); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +退款查询: + +```java +import com.github.wxpay.sdk.WXPay; + +import java.util.HashMap; +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map data = new HashMap(); + data.put("out_trade_no", "2016090910595900000012"); + + try { + Map resp = wxpay.refundQuery(data); + System.out.println(resp); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +下载对账单: + +```java +import com.github.wxpay.sdk.WXPay; + +import java.util.HashMap; +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map data = new HashMap(); + data.put("bill_date", "20140603"); + data.put("bill_type", "ALL"); + + try { + Map resp = wxpay.downloadBill(data); + System.out.println(resp); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +其他API的使用和上面类似。 + +暂时不支持下载压缩格式的对账单,但可以使用该SDK生成请求用的XML数据: +```java +import com.github.wxpay.sdk.WXPay; +import com.github.wxpay.sdk.WXPayUtil; + +import java.util.HashMap; +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map data = new HashMap(); + data.put("bill_date", "20140603"); + data.put("bill_type", "ALL"); + data.put("tar_type", "GZIP"); + + try { + data = wxpay.fillRequestData(data); + System.out.println(WXPayUtil.mapToXml(data)); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +收到支付结果通知时,需要验证签名,可以这样做: +```java + +import com.github.wxpay.sdk.WXPay; +import com.github.wxpay.sdk.WXPayUtil; + +import java.util.Map; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + + String notifyData = "...."; // 支付结果通知的xml格式数据 + + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config); + + Map notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map + + if (wxpay.isPayResultNotifySignatureValid(notifyMap)) { + // 签名正确 + // 进行处理。 + // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功 + } + else { + // 签名错误,如果数据里没有sign字段,也认为是签名错误 + } + } + +} +``` + +HTTPS请求可选HMAC-SHA256算法和MD5算法签名: +``` +import com.github.wxpay.sdk.WXPay; +import com.github.wxpay.sdk.WXPayConstants; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config, WXPayConstants.SignType.HMACSHA256); + // ...... + } +} +``` + +若需要使用sandbox环境: +``` +import com.github.wxpay.sdk.WXPay; +import com.github.wxpay.sdk.WXPayConstants; + +public class WXPayExample { + + public static void main(String[] args) throws Exception { + MyConfig config = new MyConfig(); + WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, true); + // ...... + } + +} +``` \ No newline at end of file diff --git a/java_sdk_v3.0.9/pom.xml b/java_sdk_v3.0.9/pom.xml new file mode 100644 index 0000000..0c1c352 --- /dev/null +++ b/java_sdk_v3.0.9/pom.xml @@ -0,0 +1,127 @@ + + + + 4.0.0 + + com.github.wxpay + wxpay-sdk + 3.0.9 + wxpay-sdk + wxpay sdk + + + + utf-8 + utf-8 + + + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + org.slf4j + slf4j-api + 1.7.21 + + + + org.slf4j + slf4j-simple + 1.7.21 + + + + + + + + + release + + + oss + https://oss.sonatype.org/content/repositories/snapshots/ + + + oss + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + package + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + + + \ No newline at end of file diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/IWXPayDomain.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/IWXPayDomain.java new file mode 100644 index 0000000..b693aad --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/IWXPayDomain.java @@ -0,0 +1,42 @@ +package com.github.wxpay.sdk; + +/** + * 域名管理,实现主备域名自动切换 + */ +public abstract interface IWXPayDomain { + /** + * 上报域名网络状况 + * @param domain 域名。 比如:api.mch.weixin.qq.com + * @param elapsedTimeMillis 耗时 + * @param ex 网络请求中出现的异常。 + * null表示没有异常 + * ConnectTimeoutException,表示建立网络连接异常 + * UnknownHostException, 表示dns解析异常 + */ + abstract void report(final String domain, long elapsedTimeMillis, final Exception ex); + + /** + * 获取域名 + * @param config 配置 + * @return 域名 + */ + abstract DomainInfo getDomain(final WXPayConfig config); + + static class DomainInfo{ + public String domain; //域名 + public boolean primaryDomain; //该域名是否为主域名。例如:api.mch.weixin.qq.com为主域名 + public DomainInfo(String domain, boolean primaryDomain) { + this.domain = domain; + this.primaryDomain = primaryDomain; + } + + @Override + public String toString() { + return "DomainInfo{" + + "domain='" + domain + '\'' + + ", primaryDomain=" + primaryDomain + + '}'; + } + } + +} \ No newline at end of file diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPay.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPay.java new file mode 100644 index 0000000..5c9e3fa --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPay.java @@ -0,0 +1,689 @@ +package com.github.wxpay.sdk; + +import com.github.wxpay.sdk.WXPayConstants.SignType; + +import java.util.HashMap; +import java.util.Map; + +public class WXPay { + + private WXPayConfig config; + private SignType signType; + private boolean autoReport; + private boolean useSandbox; + private String notifyUrl; + private WXPayRequest wxPayRequest; + + public WXPay(final WXPayConfig config) throws Exception { + this(config, null, true, false); + } + + public WXPay(final WXPayConfig config, final boolean autoReport) throws Exception { + this(config, null, autoReport, false); + } + + + public WXPay(final WXPayConfig config, final boolean autoReport, final boolean useSandbox) throws Exception{ + this(config, null, autoReport, useSandbox); + } + + public WXPay(final WXPayConfig config, final String notifyUrl) throws Exception { + this(config, notifyUrl, true, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport) throws Exception { + this(config, notifyUrl, autoReport, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception { + this.config = config; + this.notifyUrl = notifyUrl; + this.autoReport = autoReport; + this.useSandbox = useSandbox; + if (useSandbox) { + this.signType = SignType.MD5; // 沙箱环境 + } + else { + this.signType = SignType.HMACSHA256; + } + this.wxPayRequest = new WXPayRequest(config); + } + + private void checkWXPayConfig() throws Exception { + if (this.config == null) { + throw new Exception("config is null"); + } + if (this.config.getAppID() == null || this.config.getAppID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getMchID() == null || this.config.getMchID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getCertStream() == null) { + throw new Exception("cert stream in config is empty"); + } + if (this.config.getWXPayDomain() == null){ + throw new Exception("config.getWXPayDomain() is null"); + } + + if (this.config.getHttpConnectTimeoutMs() < 10) { + throw new Exception("http connect timeout is too small"); + } + if (this.config.getHttpReadTimeoutMs() < 10) { + throw new Exception("http read timeout is too small"); + } + + } + + /** + * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign
+ * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 + * + * @param reqData + * @return + * @throws Exception + */ + public Map fillRequestData(Map reqData) throws Exception { + reqData.put("appid", config.getAppID()); + reqData.put("mch_id", config.getMchID()); + reqData.put("nonce_str", WXPayUtil.generateNonceStr()); + if (SignType.MD5.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.MD5); + } + else if (SignType.HMACSHA256.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.HMACSHA256); + } + reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType)); + return reqData; + } + + /** + * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isResponseSignatureValid(Map reqData) throws Exception { + // 返回数据的签名方式和请求中给定的签名方式是一致的 + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), this.signType); + } + + /** + * 判断支付结果通知中的sign是否有效 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isPayResultNotifySignatureValid(Map reqData) throws Exception { + String signTypeInData = reqData.get(WXPayConstants.FIELD_SIGN_TYPE); + SignType signType; + if (signTypeInData == null) { + signType = SignType.MD5; + } + else { + signTypeInData = signTypeInData.trim(); + if (signTypeInData.length() == 0) { + signType = SignType.MD5; + } + else if (WXPayConstants.MD5.equals(signTypeInData)) { + signType = SignType.MD5; + } + else if (WXPayConstants.HMACSHA256.equals(signTypeInData)) { + signType = SignType.HMACSHA256; + } + else { + throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData)); + } + } + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), signType); + } + + + /** + * 不需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithoutCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID = reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithoutCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, autoReport); + return resp; + } + + + /** + * 需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 Map + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID= reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, this.autoReport); + return resp; + } + + /** + * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。 + * @param xmlStr API返回的XML格式数据 + * @return Map类型数据 + * @throws Exception + */ + public Map processResponseXml(String xmlStr) throws Exception { + String RETURN_CODE = "return_code"; + String return_code; + Map respData = WXPayUtil.xmlToMap(xmlStr); + if (respData.containsKey(RETURN_CODE)) { + return_code = respData.get(RETURN_CODE); + } + else { + throw new Exception(String.format("No `return_code` in XML: %s", xmlStr)); + } + + if (return_code.equals(WXPayConstants.FAIL)) { + return respData; + } + else if (return_code.equals(WXPayConstants.SUCCESS)) { + if (this.isResponseSignatureValid(respData)) { + return respData; + } + else { + throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr)); + } + } + else { + throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr)); + } + } + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData) throws Exception { + return this.microPay(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_MICROPAY_URL_SUFFIX; + } + else { + url = WXPayConstants.MICROPAY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData) throws Exception { + return this.microPayWithPos(reqData, this.config.getHttpConnectTimeoutMs()); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @param connectTimeoutMs + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData, int connectTimeoutMs) throws Exception { + int remainingTimeMs = 60*1000; + long startTimestampMs = 0; + Map lastResult = null; + Exception lastException = null; + + while (true) { + startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + int readTimeoutMs = remainingTimeMs - connectTimeoutMs; + if (readTimeoutMs > 1000) { + try { + lastResult = this.microPay(reqData, connectTimeoutMs, readTimeoutMs); + String returnCode = lastResult.get("return_code"); + if (returnCode.equals("SUCCESS")) { + String resultCode = lastResult.get("result_code"); + String errCode = lastResult.get("err_code"); + if (resultCode.equals("SUCCESS")) { + break; + } + else { + // 看错误码,若支付结果未知,则重试提交刷卡支付 + if (errCode.equals("SYSTEMERROR") || errCode.equals("BANKERROR") || errCode.equals("USERPAYING")) { + remainingTimeMs = remainingTimeMs - (int)(WXPayUtil.getCurrentTimestampMs() - startTimestampMs); + if (remainingTimeMs <= 100) { + break; + } + else { + WXPayUtil.getLogger().info("microPayWithPos: try micropay again"); + if (remainingTimeMs > 5*1000) { + Thread.sleep(5*1000); + } + else { + Thread.sleep(1*1000); + } + continue; + } + } + else { + break; + } + } + } + else { + break; + } + } + catch (Exception ex) { + lastResult = null; + lastException = ex; + } + } + else { + break; + } + } + + if (lastResult == null) { + throw lastException; + } + else { + return lastResult; + } + } + + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData) throws Exception { + return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.UNIFIEDORDER_URL_SUFFIX; + } + if(this.notifyUrl != null) { + reqData.put("notify_url", this.notifyUrl); + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData) throws Exception { + return this.orderQuery(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 int + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_ORDERQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.ORDERQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData) throws Exception { + return this.reverse(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REVERSE_URL_SUFFIX; + } + else { + url = WXPayConstants.REVERSE_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData) throws Exception { + return this.closeOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_CLOSEORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.CLOSEORDER_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData) throws Exception { + return this.refund(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUND_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUND_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData) throws Exception { + return this.refundQuery(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUNDQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUNDQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:对账单下载(成功时返回对账单数据,失败时返回XML格式数据)
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData) throws Exception { + return this.downloadBill(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:对账单下载
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:无论是否成功都返回Map。若成功,返回的Map中含有return_code、return_msg、data, + * 其中return_code为`SUCCESS`,data为对账单数据。 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return 经过封装的API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_DOWNLOADBILL_URL_SUFFIX; + } + else { + url = WXPayConstants.DOWNLOADBILL_URL_SUFFIX; + } + String respStr = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs).trim(); + Map ret; + // 出现错误,返回XML数据 + if (respStr.indexOf("<") == 0) { + ret = WXPayUtil.xmlToMap(respStr); + } + else { + // 正常返回csv数据 + ret = new HashMap(); + ret.put("return_code", WXPayConstants.SUCCESS); + ret.put("return_msg", "ok"); + ret.put("data", respStr); + } + return ret; + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData) throws Exception { + return this.report(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REPORT_URL_SUFFIX; + } + else { + url = WXPayConstants.REPORT_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return WXPayUtil.xmlToMap(respXml); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData) throws Exception { + return this.shortUrl(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_SHORTURL_URL_SUFFIX; + } + else { + url = WXPayConstants.SHORTURL_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData) throws Exception { + return this.authCodeToOpenid(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_AUTHCODETOOPENID_URL_SUFFIX; + } + else { + url = WXPayConstants.AUTHCODETOOPENID_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + +} // end class diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConfig.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConfig.java new file mode 100644 index 0000000..ed1acf2 --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConfig.java @@ -0,0 +1,103 @@ +package com.github.wxpay.sdk; + +import java.io.InputStream; + +public abstract class WXPayConfig { + + + + /** + * 获取 App ID + * + * @return App ID + */ + abstract String getAppID(); + + + /** + * 获取 Mch ID + * + * @return Mch ID + */ + abstract String getMchID(); + + + /** + * 获取 API 密钥 + * + * @return API密钥 + */ + abstract String getKey(); + + + /** + * 获取商户证书内容 + * + * @return 商户证书内容 + */ + abstract InputStream getCertStream(); + + /** + * HTTP(S) 连接超时时间,单位毫秒 + * + * @return + */ + public int getHttpConnectTimeoutMs() { + return 6*1000; + } + + /** + * HTTP(S) 读数据超时时间,单位毫秒 + * + * @return + */ + public int getHttpReadTimeoutMs() { + return 8*1000; + } + + /** + * 获取WXPayDomain, 用于多域名容灾自动切换 + * @return + */ + abstract IWXPayDomain getWXPayDomain(); + + /** + * 是否自动上报。 + * 若要关闭自动上报,子类中实现该函数返回 false 即可。 + * + * @return + */ + public boolean shouldAutoReport() { + return true; + } + + /** + * 进行健康上报的线程的数量 + * + * @return + */ + public int getReportWorkerNum() { + return 6; + } + + + /** + * 健康上报缓存消息的最大数量。会有线程去独立上报 + * 粗略计算:加入一条消息200B,10000消息占用空间 2000 KB,约为2MB,可以接受 + * + * @return + */ + public int getReportQueueMaxSize() { + return 10000; + } + + /** + * 批量上报,一次最多上报多个数据 + * + * @return + */ + public int getReportBatchSize() { + return 10; + } + +} diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConstants.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConstants.java new file mode 100644 index 0000000..8419859 --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayConstants.java @@ -0,0 +1,59 @@ +package com.github.wxpay.sdk; + +import org.apache.http.client.HttpClient; + +/** + * 常量 + */ +public class WXPayConstants { + + public enum SignType { + MD5, HMACSHA256 + } + + public static final String DOMAIN_API = "api.mch.weixin.qq.com"; + public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com"; + public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com"; + public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com"; + + + public static final String FAIL = "FAIL"; + public static final String SUCCESS = "SUCCESS"; + public static final String HMACSHA256 = "HMAC-SHA256"; + public static final String MD5 = "MD5"; + + public static final String FIELD_SIGN = "sign"; + public static final String FIELD_SIGN_TYPE = "sign_type"; + + public static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9"; + public static final String USER_AGENT = WXPAYSDK_VERSION + + " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") + + ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion(); + + public static final String MICROPAY_URL_SUFFIX = "/pay/micropay"; + public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder"; + public static final String ORDERQUERY_URL_SUFFIX = "/pay/orderquery"; + public static final String REVERSE_URL_SUFFIX = "/secapi/pay/reverse"; + public static final String CLOSEORDER_URL_SUFFIX = "/pay/closeorder"; + public static final String REFUND_URL_SUFFIX = "/secapi/pay/refund"; + public static final String REFUNDQUERY_URL_SUFFIX = "/pay/refundquery"; + public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill"; + public static final String REPORT_URL_SUFFIX = "/payitil/report"; + public static final String SHORTURL_URL_SUFFIX = "/tools/shorturl"; + public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid"; + + // sandbox + public static final String SANDBOX_MICROPAY_URL_SUFFIX = "/sandboxnew/pay/micropay"; + public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder"; + public static final String SANDBOX_ORDERQUERY_URL_SUFFIX = "/sandboxnew/pay/orderquery"; + public static final String SANDBOX_REVERSE_URL_SUFFIX = "/sandboxnew/secapi/pay/reverse"; + public static final String SANDBOX_CLOSEORDER_URL_SUFFIX = "/sandboxnew/pay/closeorder"; + public static final String SANDBOX_REFUND_URL_SUFFIX = "/sandboxnew/secapi/pay/refund"; + public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX = "/sandboxnew/pay/refundquery"; + public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill"; + public static final String SANDBOX_REPORT_URL_SUFFIX = "/sandboxnew/payitil/report"; + public static final String SANDBOX_SHORTURL_URL_SUFFIX = "/sandboxnew/tools/shorturl"; + public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid"; + +} + diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayReport.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayReport.java new file mode 100644 index 0000000..a6a2e22 --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayReport.java @@ -0,0 +1,265 @@ +package com.github.wxpay.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; + +/** + * 交易保障 + */ +public class WXPayReport { + + public static class ReportInfo { + + /** + * 布尔变量使用int。0为false, 1为true。 + */ + + // 基本信息 + private String version = "v1"; + private String sdk = WXPayConstants.WXPAYSDK_VERSION; + private String uuid; // 交易的标识 + private long timestamp; // 上报时的时间戳,单位秒 + private long elapsedTimeMillis; // 耗时,单位 毫秒 + + // 针对主域名 + private String firstDomain; // 第1次请求的域名 + private boolean primaryDomain; //是否主域名 + private int firstConnectTimeoutMillis; // 第1次请求设置的连接超时时间,单位 毫秒 + private int firstReadTimeoutMillis; // 第1次请求设置的读写超时时间,单位 毫秒 + private int firstHasDnsError; // 第1次请求是否出现dns问题 + private int firstHasConnectTimeout; // 第1次请求是否出现连接超时 + private int firstHasReadTimeout; // 第1次请求是否出现连接超时 + + public ReportInfo(String uuid, long timestamp, long elapsedTimeMillis, String firstDomain, boolean primaryDomain, int firstConnectTimeoutMillis, int firstReadTimeoutMillis, boolean firstHasDnsError, boolean firstHasConnectTimeout, boolean firstHasReadTimeout) { + this.uuid = uuid; + this.timestamp = timestamp; + this.elapsedTimeMillis = elapsedTimeMillis; + this.firstDomain = firstDomain; + this.primaryDomain = primaryDomain; + this.firstConnectTimeoutMillis = firstConnectTimeoutMillis; + this.firstReadTimeoutMillis = firstReadTimeoutMillis; + this.firstHasDnsError = firstHasDnsError?1:0; + this.firstHasConnectTimeout = firstHasConnectTimeout?1:0; + this.firstHasReadTimeout = firstHasReadTimeout?1:0; + } + + @Override + public String toString() { + return "ReportInfo{" + + "version='" + version + '\'' + + ", sdk='" + sdk + '\'' + + ", uuid='" + uuid + '\'' + + ", timestamp=" + timestamp + + ", elapsedTimeMillis=" + elapsedTimeMillis + + ", firstDomain='" + firstDomain + '\'' + + ", primaryDomain=" + primaryDomain + + ", firstConnectTimeoutMillis=" + firstConnectTimeoutMillis + + ", firstReadTimeoutMillis=" + firstReadTimeoutMillis + + ", firstHasDnsError=" + firstHasDnsError + + ", firstHasConnectTimeout=" + firstHasConnectTimeout + + ", firstHasReadTimeout=" + firstHasReadTimeout + + '}'; + } + + /** + * 转换成 csv 格式 + * + * @return + */ + public String toLineString(String key) { + String separator = ","; + Object[] objects = new Object[] { + version, sdk, uuid, timestamp, elapsedTimeMillis, + firstDomain, primaryDomain, firstConnectTimeoutMillis, firstReadTimeoutMillis, + firstHasDnsError, firstHasConnectTimeout, firstHasReadTimeout + }; + StringBuffer sb = new StringBuffer(); + for(Object obj: objects) { + sb.append(obj).append(separator); + } + try { + String sign = WXPayUtil.HMACSHA256(sb.toString(), key); + sb.append(sign); + return sb.toString(); + } + catch (Exception ex) { + return null; + } + + } + + } + + private static final String REPORT_URL = "http://report.mch.weixin.qq.com/wxpay/report/default"; + // private static final String REPORT_URL = "http://127.0.0.1:5000/test"; + + + private static final int DEFAULT_CONNECT_TIMEOUT_MS = 6*1000; + private static final int DEFAULT_READ_TIMEOUT_MS = 8*1000; + + private LinkedBlockingQueue reportMsgQueue = null; + private WXPayConfig config; + private ExecutorService executorService; + + private volatile static WXPayReport INSTANCE; + + private WXPayReport(final WXPayConfig config) { + this.config = config; + reportMsgQueue = new LinkedBlockingQueue(config.getReportQueueMaxSize()); + + // 添加处理线程 + executorService = Executors.newFixedThreadPool(config.getReportWorkerNum(), new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setDaemon(true); + return t; + } + }); + + if (config.shouldAutoReport()) { + WXPayUtil.getLogger().info("report worker num: {}", config.getReportWorkerNum()); + for (int i = 0; i < config.getReportWorkerNum(); ++i) { + executorService.execute(new Runnable() { + public void run() { + while (true) { + // 先用 take 获取数据 + try { + StringBuffer sb = new StringBuffer(); + String firstMsg = reportMsgQueue.take(); + WXPayUtil.getLogger().info("get first report msg: {}", firstMsg); + String msg = null; + sb.append(firstMsg); //会阻塞至有消息 + int remainNum = config.getReportBatchSize() - 1; + for (int j=0; jcreate() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + HttpPost httpPost = new HttpPost(REPORT_URL); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + } + +} diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayRequest.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayRequest.java new file mode 100644 index 0000000..83dd05a --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayRequest.java @@ -0,0 +1,258 @@ +package com.github.wxpay.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +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.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.InputStream; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.security.KeyStore; +import java.security.SecureRandom; + +import static com.github.wxpay.sdk.WXPayConstants.USER_AGENT; + +public class WXPayRequest { + private WXPayConfig config; + public WXPayRequest(WXPayConfig config) throws Exception{ + + this.config = config; + } + + /** + * 请求,只请求一次,不做重试 + * @param domain + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @param useCert 是否使用证书,针对退款、撤销等操作 + * @return + * @throws Exception + */ + private String requestOnce(final String domain, String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception { + BasicHttpClientConnectionManager connManager; + if (useCert) { + // 证书 + char[] password = config.getMchID().toCharArray(); + InputStream certStream = config.getCertStream(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(certStream, password); + + // 实例化密钥库 & 初始化密钥工厂 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password); + + // 创建 SSLContext + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, new SecureRandom()); + + SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( + sslContext, + new String[]{"TLSv1"}, + null, + new DefaultHostnameVerifier()); + + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", sslConnectionSocketFactory) + .build(), + null, + null, + null + ); + } + else { + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + } + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + String url = "https://" + domain + urlSuffix; + HttpPost httpPost = new HttpPost(url); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", USER_AGENT + " " + config.getMchID()); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + + } + + + private String request(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert, boolean autoReport) throws Exception { + Exception exception = null; + long elapsedTimeMillis = 0; + long startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + boolean firstHasDnsErr = false; + boolean firstHasConnectTimeout = false; + boolean firstHasReadTimeout = false; + IWXPayDomain.DomainInfo domainInfo = config.getWXPayDomain().getDomain(config); + if(domainInfo == null){ + throw new Exception("WXPayConfig.getWXPayDomain().getDomain() is empty or null"); + } + try { + String result = requestOnce(domainInfo.domain, urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, useCert); + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, null); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + return result; + } + catch (UnknownHostException ex) { // dns 解析错误,或域名不存在 + exception = ex; + firstHasDnsErr = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("UnknownHostException for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (ConnectTimeoutException ex) { + exception = ex; + firstHasConnectTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("connect timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (SocketTimeoutException ex) { + exception = ex; + firstHasReadTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + catch (Exception ex) { + exception = ex; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, exception); + throw exception; + } + + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), false, autoReport); + } + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, false, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), true, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, true, autoReport); + } +} diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayUtil.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayUtil.java new file mode 100644 index 0000000..8f6948a --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayUtil.java @@ -0,0 +1,295 @@ +package com.github.wxpay.sdk; + +import com.github.wxpay.sdk.WXPayConstants.SignType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.*; + + +public class WXPayUtil { + + private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + private static final Random RANDOM = new SecureRandom(); + + /** + * XML格式字符串转换为Map + * + * @param strXML XML字符串 + * @return XML数据转换后的Map + * @throws Exception + */ + public static Map xmlToMap(String strXML) throws Exception { + try { + Map data = new HashMap(); + DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder(); + InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); + org.w3c.dom.Document doc = documentBuilder.parse(stream); + doc.getDocumentElement().normalize(); + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + for (int idx = 0; idx < nodeList.getLength(); ++idx) { + Node node = nodeList.item(idx); + if (node.getNodeType() == Node.ELEMENT_NODE) { + org.w3c.dom.Element element = (org.w3c.dom.Element) node; + data.put(element.getNodeName(), element.getTextContent()); + } + } + try { + stream.close(); + } catch (Exception ex) { + // do nothing + } + return data; + } catch (Exception ex) { + WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML); + throw ex; + } + + } + + /** + * 将Map转换为XML格式的字符串 + * + * @param data Map类型数据 + * @return XML格式的字符串 + * @throws Exception + */ + public static String mapToXml(Map data) throws Exception { + org.w3c.dom.Document document = WXPayXmlUtil.newDocument(); + org.w3c.dom.Element root = document.createElement("xml"); + document.appendChild(root); + for (String key: data.keySet()) { + String value = data.get(key); + if (value == null) { + value = ""; + } + value = value.trim(); + org.w3c.dom.Element filed = document.createElement(key); + filed.appendChild(document.createTextNode(value)); + root.appendChild(filed); + } + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + DOMSource source = new DOMSource(document); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); + try { + writer.close(); + } + catch (Exception ex) { + } + return output; + } + + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key) throws Exception { + return generateSignedXml(data, key, SignType.MD5); + } + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名类型 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key, SignType signType) throws Exception { + String sign = generateSignature(data, key, signType); + data.put(WXPayConstants.FIELD_SIGN, sign); + return mapToXml(data); + } + + + /** + * 判断签名是否正确 + * + * @param xmlStr XML格式数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(String xmlStr, String key) throws Exception { + Map data = xmlToMap(xmlStr); + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key).equals(sign); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key) throws Exception { + return isSignatureValid(data, key, SignType.MD5); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key, SignType signType) throws Exception { + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key, signType).equals(sign); + } + + /** + * 生成签名 + * + * @param data 待签名数据 + * @param key API密钥 + * @return 签名 + */ + public static String generateSignature(final Map data, String key) throws Exception { + return generateSignature(data, key, SignType.MD5); + } + + /** + * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 + * + * @param data 待签名数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名 + */ + public static String generateSignature(final Map data, String key, SignType signType) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k).trim()).append("&"); + } + sb.append("key=").append(key); + if (SignType.MD5.equals(signType)) { + return MD5(sb.toString()).toUpperCase(); + } + else if (SignType.HMACSHA256.equals(signType)) { + return HMACSHA256(sb.toString(), key); + } + else { + throw new Exception(String.format("Invalid sign_type: %s", signType)); + } + } + + + /** + * 获取随机字符串 Nonce Str + * + * @return String 随机字符串 + */ + public static String generateNonceStr() { + char[] nonceChars = new char[32]; + for (int index = 0; index < nonceChars.length; ++index) { + nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + return new String(nonceChars); + } + + + /** + * 生成 MD5 + * + * @param data 待处理数据 + * @return MD5结果 + */ + public static String MD5(String data) throws Exception { + java.security.MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] array = md.digest(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 生成 HMACSHA256 + * @param data 待处理数据 + * @param key 密钥 + * @return 加密结果 + * @throws Exception + */ + public static String HMACSHA256(String data, String key) throws Exception { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 日志 + * @return + */ + public static Logger getLogger() { + Logger logger = LoggerFactory.getLogger("wxpay java sdk"); + return logger; + } + + /** + * 获取当前时间戳,单位秒 + * @return + */ + public static long getCurrentTimestamp() { + return System.currentTimeMillis()/1000; + } + + /** + * 获取当前时间戳,单位毫秒 + * @return + */ + public static long getCurrentTimestampMs() { + return System.currentTimeMillis(); + } + +} diff --git a/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayXmlUtil.java b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayXmlUtil.java new file mode 100644 index 0000000..5988840 --- /dev/null +++ b/java_sdk_v3.0.9/src/main/java/com/github/wxpay/sdk/WXPayXmlUtil.java @@ -0,0 +1,30 @@ +package com.github.wxpay.sdk; + +import org.w3c.dom.Document; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * 2018/7/3 + */ +public final class WXPayXmlUtil { + public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + documentBuilderFactory.setXIncludeAware(false); + documentBuilderFactory.setExpandEntityReferences(false); + + return documentBuilderFactory.newDocumentBuilder(); + } + + public static Document newDocument() throws ParserConfigurationException { + return newDocumentBuilder().newDocument(); + } +} diff --git a/libs/wxpay-sdk-0.0.1.jar b/libs/wxpay-sdk-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..a1538763855e5ffa4aaf9d4fdfa3290c735159d5 GIT binary patch literal 63608 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

nz;k7l{3%>RI;(4u0{R-y?2l)wb#|)?o)g!Yf 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 PIw%Ur7|*?a{p + + 4.0.0 + + com.ruoyi + ruoyi + pom + 3.6.0 + + ruoyi + http://www.ruoyi.vip + 若依管理系统 + + + 3.6.0 + 3.0.9 + UTF-8 + UTF-8 + 1.8 + 3.1.1 + 1.2.6 + 1.21 + 3.0.0 + 2.3.2 + 2.1.4 + 1.3.1 + 1.2.76 + 5.8.0 + 5.8.0 + 2.11.0 + 1.4 + 3.2.2 + 4.1.2 + 1.7 + 0.9.1 + 4.8.10.ALL + + + + + + + + + com.google.zxing + core + 3.4.0 + + + + com.alipay.sdk + alipay-sdk-java + ${alipay.version} + + + fastjson + com.alibaba + + + + + org.bouncycastle + bcprov-jdk16 + 1.46 + + + + dom4j + dom4j + 1.6.1 + + + + + com.github.qcloudsms + qcloudsms + 1.0.6 + + + com.aliyun + aliyun-java-sdk-core + 4.0.6 + + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + + com.qcloud + cos_api + 5.6.8 + + + + com.aliyun.oss + aliyun-sdk-oss + 2.5.0 + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.2.13.RELEASE + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + eu.bitwalker + UserAgentUtils + ${bitwalker.version} + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + net.java.dev.jna + jna + ${jna.version} + + + + net.java.dev.jna + jna-platform + ${jna.version} + + + + + io.springfox + springfox-boot-starter + ${swagger.version} + + + io.swagger + swagger-models + + + + + + + commons-io + commons-io + ${commons.io.version} + + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity + ${velocity.version} + + + commons-collections + commons-collections + + + + + + + commons-collections + commons-collections + ${commons.collections.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + + com.github.penggle + kaptcha + ${kaptcha.version} + + + + + com.ruoyi + ruoyi-quartz + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-generator + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-framework + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-system + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-segchk + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-segchk-web + ${ruoyi.version} + + + + com.github.wxpay + wxpay-sdk + ${wxsdk.version} + + + + + + ruoyi-segchk + ruoyi-segchk-web + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-quartz + ruoyi-generator + ruoyi-common + + + wxpay-sdk + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + 512m + 1048m + + + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + + \ No newline at end of file diff --git a/pom.xmlbak b/pom.xmlbak new file mode 100644 index 0000000..56ac15a --- /dev/null +++ b/pom.xmlbak @@ -0,0 +1,281 @@ + + + 4.0.0 + + com.ruoyi + ruoyi + 3.6.0 + + ruoyi + http://www.ruoyi.vip + 若依管理系统 + + + 3.6.0 + UTF-8 + UTF-8 + 1.8 + 3.1.1 + 1.2.6 + 1.21 + 3.0.0 + 2.3.2 + 2.1.4 + 1.3.1 + 1.2.76 + 5.8.0 + 5.8.0 + 2.11.0 + 1.4 + 3.2.2 + 4.1.2 + 1.7 + 0.9.1 + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.2.13.RELEASE + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + eu.bitwalker + UserAgentUtils + ${bitwalker.version} + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + net.java.dev.jna + jna + ${jna.version} + + + + net.java.dev.jna + jna-platform + ${jna.version} + + + + + io.springfox + springfox-boot-starter + ${swagger.version} + + + io.swagger + swagger-models + + + + + + + commons-io + commons-io + ${commons.io.version} + + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity + ${velocity.version} + + + commons-collections + commons-collections + + + + + + + commons-collections + commons-collections + ${commons.collections.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + + com.github.penggle + kaptcha + ${kaptcha.version} + + + + + com.ruoyi + ruoyi-quartz + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-generator + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-framework + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-system + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-segchk + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-segchk-web + ${ruoyi.version} + + + + + + ruoyi-segchk + ruoyi-segchk-web + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-quartz + ruoyi-generator + ruoyi-common + + pom + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + \ No newline at end of file diff --git a/pom1.xml b/pom1.xml new file mode 100644 index 0000000..f5bc269 --- /dev/null +++ b/pom1.xml @@ -0,0 +1,320 @@ + + + 4.0.0 + + com.ruoyi + ruoyi + 3.0.0 + + ruoyi + http://www.ruoyi.vip + 魔金商城平台管理 + + + 3.0.0 + UTF-8 + UTF-8 + 1.8 + 1.3.2 + 1.1.14 + 1.19 + 2.9.2 + 1.2.5 + 1.2.70 + 3.9.1 + 2.5 + 1.3.3 + 3.17 + 1.7 + 0.9.0 + 4.8.10.ALL + + + + + + + + + com.google.zxing + core + 3.4.0 + + + + com.alipay.sdk + alipay-sdk-java + ${alipay.version} + + + fastjson + com.alibaba + + + + + org.bouncycastle + bcprov-jdk16 + 1.46 + + + + dom4j + dom4j + 1.6.1 + + + + com.github.qcloudsms + qcloudsms + 1.0.6 + + + com.aliyun + aliyun-java-sdk-core + 4.0.6 + + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + + com.qcloud + cos_api + 5.6.8 + + + + com.aliyun.oss + aliyun-sdk-oss + 2.5.0 + + + + org.projectlombok + lombok + 1.18.12 + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + org.springframework.boot + spring-boot-dependencies + 2.1.1.RELEASE + 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-swagger2 + ${swagger.version} + + + io.swagger + swagger-annotations + + + io.swagger + swagger-models + + + + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + + commons-io + commons-io + ${commons.io.version} + + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity + ${velocity.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jwt.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-mall + ${ruoyi.version} + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + + + + ruoyi-store + + ruoyi-web + ruoyi-admin + ruoyi-framework + + ruoyi-system + ruoyi-mall + ruoyi-quartz + ruoyi-generator + ruoyi-common + + pom + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/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..93af423 --- /dev/null +++ b/ruoyi-admin/pom.xml @@ -0,0 +1,98 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + + 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 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 + + false + ${project.artifactId} + + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/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..390b435 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -0,0 +1,32 @@ +package com.ruoyi; + +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +/** + * 启动程序 + * + * @author ruoyi + */ +@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +public class RuoYiApplication +{ + public static void main(String[] args) + { + // 第一个参数为账户名 第二个参数为密码 第三个参数为盐对应用户表salt(如果没有可以不用填) + // 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/security/SecurityConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/security/SecurityConfig.java new file mode 100644 index 0000000..f6592ef --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/SecurityConfig.java @@ -0,0 +1,131 @@ +package com.ruoyi.security; + +import com.ruoyi.security.filter.JwtAuthenticationTokenFilter; +import com.ruoyi.security.handle.AuthenticationEntryPointImpl; +import com.ruoyi.security.handle.LogoutSuccessHandlerImpl; +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.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * 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; + + /** + * 解决 无法直接注入 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 | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * + * @ss.hasPermi | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + httpSecurity + // CRSF禁用,因为不使用session + .csrf().disable() + // 认证失败处理类 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 验证码captchaImage 允许匿名访问 + .antMatchers("/login", "/captchaImage").anonymous() + .antMatchers( + HttpMethod.GET, + "/*.html", + "/**/*.html", + "/**/*.css", + "/**/*.js" + ).permitAll() + .antMatchers("/profile/**").anonymous() + .antMatchers("/common/download**").anonymous() + .antMatchers("/common/download/resource**").anonymous() + .antMatchers("/swagger-ui.html").anonymous() + .antMatchers("/swagger-resources/**").anonymous() + .antMatchers("/webjars/**").anonymous() + .antMatchers("/*/api-docs").anonymous() + .antMatchers("/druid/**").anonymous() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.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-admin/src/main/java/com/ruoyi/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-admin/src/main/java/com/ruoyi/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..6254c51 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,43 @@ +package com.ruoyi.security.filter; + +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; +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 javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 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 { + logger.debug(request.getRequestURI()); + 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-admin/src/main/java/com/ruoyi/security/handle/AuthenticationEntryPointImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..7112571 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/handle/AuthenticationEntryPointImpl.java @@ -0,0 +1,33 @@ +package com.ruoyi.security.handle; + +import com.alibaba.fastjson.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; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Serializable; + +/** + * 认证失败处理类 返回未授权 + * + * @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-admin/src/main/java/com/ruoyi/security/handle/LogoutSuccessHandlerImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..95c16dd --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/handle/LogoutSuccessHandlerImpl.java @@ -0,0 +1,51 @@ +package com.ruoyi.security.handle; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.constant.Constants; +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.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; +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 javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 自定义退出处理类 返回成功 + * + * @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.error(HttpStatus.SUCCESS, "退出成功"))); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/Server.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/Server.java new file mode 100644 index 0000000..db3c8ab --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/Server.java @@ -0,0 +1,211 @@ +package com.ruoyi.security.web.domain; + +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.security.web.domain.server.*; +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; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + * 服务器相关信息 + * + * @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; + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) { + FileSystem fileSystem = os.getFileSystem(); + OSFileStore[] fsArray = fileSystem.getFileStores().toArray(new OSFileStore[0]); + 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); + } + } + + 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")); + } + + /** + * 字节转换 + * + * @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-admin/src/main/java/com/ruoyi/security/web/domain/server/Cpu.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Cpu.java new file mode 100644 index 0000000..37dcf3c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Cpu.java @@ -0,0 +1,88 @@ +package com.ruoyi.security.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-admin/src/main/java/com/ruoyi/security/web/domain/server/Jvm.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Jvm.java new file mode 100644 index 0000000..c44f437 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Jvm.java @@ -0,0 +1,107 @@ +package com.ruoyi.security.web.domain.server; + +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.DateUtils; + +import java.lang.management.ManagementFactory; + +/** + * 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.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Mem.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Mem.java new file mode 100644 index 0000000..d98a29e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Mem.java @@ -0,0 +1,53 @@ +package com.ruoyi.security.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-admin/src/main/java/com/ruoyi/security/web/domain/server/Sys.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Sys.java new file mode 100644 index 0000000..014a138 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/Sys.java @@ -0,0 +1,73 @@ +package com.ruoyi.security.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-admin/src/main/java/com/ruoyi/security/web/domain/server/SysFile.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/SysFile.java new file mode 100644 index 0000000..9f7ddb1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/domain/server/SysFile.java @@ -0,0 +1,99 @@ +package com.ruoyi.security.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-admin/src/main/java/com/ruoyi/security/web/exception/GlobalExceptionHandler.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..554ab27 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,105 @@ +package com.ruoyi.security.web.exception; + +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.CustomException; +import com.ruoyi.common.exception.DemoModeException; +import com.ruoyi.common.exception.base.BaseException; +import com.ruoyi.common.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.validation.BindException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.NoHandlerFoundException; + +/** + * 全局异常处理器 + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 基础异常 + */ + @ExceptionHandler(BaseException.class) + public AjaxResult baseException(BaseException e) { + return AjaxResult.error(e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(CustomException.class) + public AjaxResult businessException(CustomException e) { + if (StringUtils.isNull(e.getCode())) { + return AjaxResult.error(e.getMessage()); + } + return AjaxResult.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(NoHandlerFoundException.class) + public AjaxResult handlerNoFoundException(Exception e) { + log.error(e.getMessage(), e); + return AjaxResult.error(HttpStatus.NOT_FOUND, "路径不存在,请检查路径是否正确"); + } + + @ExceptionHandler(AccessDeniedException.class) + public AjaxResult handleAuthorizationException(AccessDeniedException e) { + log.error(e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权"); + } + + @ExceptionHandler(AccountExpiredException.class) + public AjaxResult handleAccountExpiredException(AccountExpiredException e) { + log.error(e.getMessage(), e); + return AjaxResult.error(e.getMessage()); + } + + @ExceptionHandler(UsernameNotFoundException.class) + public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e) { + log.error(e.getMessage(), e); + return AjaxResult.error(e.getMessage()); + } + + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e) { + log.error(e.getMessage(), e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult validatedBindException(BindException e) { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object validExceptionHandler(MethodArgumentNotValidException e) { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 演示模式异常 + */ + @ExceptionHandler(DemoModeException.class) + public AjaxResult demoModeException(DemoModeException e) { + return AjaxResult.error("演示模式,不允许操作"); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/PermissionService.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/PermissionService.java new file mode 100644 index 0000000..6e1127b --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/PermissionService.java @@ -0,0 +1,153 @@ +package com.ruoyi.security.web.service; + +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.TokenService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.Set; + +/** + * 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 = ","; + + @Autowired + private TokenService tokenService; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) { + if (StringUtils.isEmpty(permission)) { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) { + if (StringUtils.isEmpty(permissions)) { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + 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 = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) { + return false; + } + for (SysRole sysRole : loginUser.getUser().getRoles()) { + String roleKey = sysRole.getRoleKey(); + if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(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 = tokenService.getLoginUser(ServletUtils.getRequest()); + 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-admin/src/main/java/com/ruoyi/security/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysLoginService.java new file mode 100644 index 0000000..bf586d0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysLoginService.java @@ -0,0 +1,80 @@ +package com.ruoyi.security.web.service; + +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.exception.CustomException; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.web.service.TokenService; +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 javax.annotation.Resource; + +/** + * 登录校验方法 + * + * @author ruoyi + */ +@Component +public class SysLoginService { + @Autowired + private TokenService tokenService; + + @Resource + private AuthenticationManager authenticationManager; + + @Autowired + private RedisCache redisCache; + + /** + * 登录验证 + * + * @param username 用户名 + * @param password 密码 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public String login(String username, String password, String code, String uuid) { + String verifyKey = Constants.CAPTCHA_CODE_KEY + 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(); + } + // 用户验证 + Authentication authentication = null; + try { + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken(username, password)); + } 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 CustomException(e.getMessage()); + } + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + // 生成token + return tokenService.createToken(loginUser); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysPermissionService.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysPermissionService.java new file mode 100644 index 0000000..443afb7 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/SysPermissionService.java @@ -0,0 +1,58 @@ +package com.ruoyi.security.web.service; + +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.segchk.service.ISegchkProviderMgtService; +import com.ruoyi.system.service.ISysMenuService; +import com.ruoyi.system.service.ISysRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashSet; +import java.util.Set; + +/** + * 用户权限处理 + * + * @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 { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + return perms; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/UserDetailsServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..db42920 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/security/web/service/UserDetailsServiceImpl.java @@ -0,0 +1,52 @@ +package com.ruoyi.security.web.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.base.BaseException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysUserService; +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; + +/** + * 用户验证处理 + * + * @author ruoyi + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private ISysUserService userService; + + @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 UsernameNotFoundException("登录用户:" + username + " 不存在"); + } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { + log.info("登录用户:{} 已被删除.", username); + throw new BaseException("对不起,您的账号:" + username + " 已被删除"); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + log.info("登录用户:{} 已被停用.", username); + throw new BaseException("对不起,您的账号:" + username + " 已停用"); + } + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) { + return new LoginUser(user, permissionService.getMenuPermission(user)); + } +} 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..0aad226 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -0,0 +1,96 @@ +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.beans.factory.annotation.Value; +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.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; + + // 验证码类型 + @Value("${ruoyi.captchaType}") + private String captchaType; + + @Autowired + private ISysConfigService configService; + /** + * 生成验证码 + */ + @GetMapping("/captchaImage") + public AjaxResult getCode(HttpServletResponse response) throws IOException + { + AjaxResult ajax = AjaxResult.success(); + boolean captchaOnOff = configService.selectCaptchaOnOff(); + ajax.put("captchaOnOff", captchaOnOff); + if (!captchaOnOff) + { + return ajax; + } + + // 保存验证码信息 + String uuid = IdUtils.simpleUUID(); + String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + // 生成验证码 + 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..bf5b910 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -0,0 +1,334 @@ +package com.ruoyi.web.controller.common; + +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.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 +public class CommonController +{ + private static final Logger log = LoggerFactory.getLogger(CommonController.class); + + @Autowired + private ServerConfig serverConfig; + + /** + * 通用下载请求 + * + * @param fileName 文件名称 + * @param delete 是否删除 + */ + @GetMapping("common/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("/common/upload") + public AjaxResult uploadFile(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/upload with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传商家执照 + */ + @PostMapping("/common/store_cert") + public AjaxResult storeCert(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_cert"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_cert with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传商家小图标 + */ + @PostMapping("/common/store_smallicon") + public AjaxResult storeSmallicon(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_smallicon"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_smallicon with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传商家大图标 + */ + @PostMapping("/common/store_bigicon") + public AjaxResult storeBigicon(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_bigicon"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_bigicon with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 上传商家轮播图 + */ + @PostMapping("/common/store_banner") + public AjaxResult storeBanner(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_banner"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_banner with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传商家环境 + */ + @PostMapping("/common/store_env") + public AjaxResult storeEnv(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_env"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_env with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 上传商家详情 + */ + @PostMapping("/common/store_details") + public AjaxResult storeDetails(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/store_details"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/store_details with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传行业标签 + */ + @PostMapping("/common/keyword") + public AjaxResult keyword(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/keyword"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/keyword with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传优惠券 + */ + @PostMapping("/common/preference") + public AjaxResult preference(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/preference"; + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + + String url = serverConfig.getUrl() + fileName; + log.debug("/common/preference with url: {{}}, filename: {{}}", url, fileName ); + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 本地资源通用下载 + */ + @GetMapping("/common/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..7b97de2 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java @@ -0,0 +1,53 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +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.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.common.utils.StringUtils; + +/** + * 缓存监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/cache") +public class CacheController +{ + @Autowired + private RedisTemplate redisTemplate; + + @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); + } +} 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..7c3c812 --- /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 com.ruoyi.security.web.domain.Server; +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; + +/** + * 服务器监控 + * + * @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..339f242 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java @@ -0,0 +1,67 @@ +package com.ruoyi.web.controller.monitor; + +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.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.SysLogininfor; +import com.ruoyi.system.service.ISysLogininforService; + +/** + * 系统访问记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/logininfor") +public class SysLogininforController extends BaseController +{ + @Autowired + private ISysLogininforService logininforService; + + @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')") + @GetMapping("/export") + public AjaxResult export(SysLogininfor logininfor) + { + List list = logininforService.selectLogininforList(logininfor); + ExcelUtil util = new ExcelUtil(SysLogininfor.class); + return util.exportExcel(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 AjaxResult.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..1d7eb02 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -0,0 +1,67 @@ +package com.ruoyi.web.controller.monitor; + +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.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')") + @GetMapping("/export") + public AjaxResult export(SysOperLog operLog) + { + List list = operLogService.selectOperLogList(operLog); + ExcelUtil util = new ExcelUtil(SysOperLog.class); + return util.exportExcel(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 AjaxResult.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..9b157ea --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -0,0 +1,92 @@ +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.Constants; +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(Constants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList(); + for (String key : keys) + { + LoginUser user = redisCache.getCacheObject(key); + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + } + else if (StringUtils.isNotEmpty(ipaddr)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + } + else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) + { + if (StringUtils.equals(userName, user.getUsername())) + { + 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(Constants.LOGIN_TOKEN_KEY + tokenId); + return AjaxResult.success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCarouseMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCarouseMgtController.java new file mode 100644 index 0000000..c766f54 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCarouseMgtController.java @@ -0,0 +1,183 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkCarouseMgt; +import com.ruoyi.segchk.service.ISegchkCarouseMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg首页轮播图管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_carouse_mgt") +public class SegchkCarouseMgtController extends BaseController +{ + @Autowired + private ISegchkCarouseMgtService segchkCarouseMgtService; + + /** + * 查询seg首页轮播图管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkCarouseMgt segchkCarouseMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCarouseMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkCarouseMgtService.selectSegchkCarouseMgtList(segchkCarouseMgt); + return getDataTable(list); + } + + /** + * 导出seg首页轮播图管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:export')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkCarouseMgt segchkCarouseMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCarouseMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkCarouseMgtService.selectSegchkCarouseMgtList(segchkCarouseMgt); + ExcelUtil util = new ExcelUtil(SegchkCarouseMgt.class); + return util.exportExcel(list, "seg首页轮播图管理数据"); + } + + /** + * 获取seg首页轮播图管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:query')") + @GetMapping(value = "/{carouseId}") + public AjaxResult getInfo(@PathVariable("carouseId") Long carouseId) + { + return AjaxResult.success(segchkCarouseMgtService.selectSegchkCarouseMgtByCarouseId(carouseId)); + } + + /** + * 新增seg首页轮播图管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:add')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkCarouseMgt segchkCarouseMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCarouseMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkCarouseMgtService.insertSegchkCarouseMgt(segchkCarouseMgt)); + } + + /** + * 修改seg首页轮播图管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:edit')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.UPDATE) + @PutMapping("edit_info") + public AjaxResult edit(@RequestBody SegchkCarouseMgt segchkCarouseMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCarouseMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkCarouseMgtService.updateSegchkCarouseMgt(segchkCarouseMgt)); + } + + /** + * 修改seg首页轮播图管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:edit')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.UPDATE) + @PutMapping("/mgt_state") + public AjaxResult mgt_state(@RequestBody SegchkCarouseMgt segchkCarouseMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCarouseMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkCarouseMgtService.updateSegchkCarouseMgt(segchkCarouseMgt)); + } + + + /** + * 修改seg首页轮播图管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:edit')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.UPDATE) + @PutMapping("/sort_update") + public AjaxResult sort_update(@RequestBody String[] sortInfos) + { + logger.debug("sort_update with {}", sortInfos); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + ; + } + return toAjax(segchkCarouseMgtService.updateSegchkCarouseMgtSort(sortInfos)); + } + + /** + * 删除seg首页轮播图管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:remove')") + @Log(title = "seg首页轮播图管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{carouseIds}") + public AjaxResult remove(@PathVariable Long[] carouseIds) + { + return toAjax(segchkCarouseMgtService.deleteSegchkCarouseMgtByCarouseIds(carouseIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkChargeCardController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkChargeCardController.java new file mode 100644 index 0000000..6bc002e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkChargeCardController.java @@ -0,0 +1,154 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkChargeCard; +import com.ruoyi.segchk.service.ISegchkChargeCardService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg充值卡管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_charge_card") +public class SegchkChargeCardController extends BaseController +{ + @Autowired + private ISegchkChargeCardService segchkChargeCardService; + + /** + * 查询seg充值卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkChargeCard segchkChargeCard) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkChargeCard.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkChargeCardService.selectSegchkChargeCardList(segchkChargeCard); + return getDataTable(list); + } + + /** + * 导出seg充值卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:export')") + @Log(title = "seg充值卡管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkChargeCard segchkChargeCard) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkChargeCard.setProviderId(sysUser.getProviderId()); + } + List list = segchkChargeCardService.selectSegchkChargeCardList(segchkChargeCard); + ExcelUtil util = new ExcelUtil(SegchkChargeCard.class); + return util.exportExcel(list, "seg充值卡管理数据"); + } + + /** + * 获取seg充值卡管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:query')") + @GetMapping(value = "/{cardTypeId}") + public AjaxResult getInfo(@PathVariable("cardTypeId") Long cardTypeId) + { + SegchkChargeCard segchkChargeCard = new SegchkChargeCard(); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkChargeCard.setProviderId(sysUser.getProviderId()); + } + return AjaxResult.success(segchkChargeCardService.selectSegchkChargeCardByCardTypeId(cardTypeId)); + } + + /** + * 新增seg充值卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:add')") + @Log(title = "seg充值卡管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkChargeCard segchkChargeCard) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + if(ObjectUtils.isEmpty(segchkChargeCard.getProviderId())){ + return AjaxResult.error("500", "请输入运营商id"); + } + } + else{ + segchkChargeCard.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkChargeCardService.insertSegchkChargeCard(segchkChargeCard)); + } + + /** + * 修改seg充值卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:edit')") + @Log(title = "seg充值卡管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkChargeCard segchkChargeCard) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkChargeCard.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkChargeCardService.updateSegchkChargeCard(segchkChargeCard)); + } + + /** + * 删除seg充值卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_charge_card:remove')") + @Log(title = "seg充值卡管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{cardTypeIds}") + public AjaxResult remove(@PathVariable String[] cardTypeIds) + { + return toAjax(segchkChargeCardService.deleteSegchkChargeCardByCardTypeIds(cardTypeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCommentAccController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCommentAccController.java new file mode 100644 index 0000000..a0705ca --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkCommentAccController.java @@ -0,0 +1,145 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkCommentAcc; +import com.ruoyi.segchk.service.ISegchkCommentAccService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家累积评价Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_comment_acc") +public class SegchkCommentAccController extends BaseController +{ + @Autowired + private ISegchkCommentAccService segchkCommentAccService; + + /** + * 查询seg商家累积评价列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkCommentAcc segchkCommentAcc) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCommentAcc.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkCommentAccService.selectSegchkCommentAccList(segchkCommentAcc); + return getDataTable(list); + } + + /** + * 导出seg商家累积评价列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:export')") + @Log(title = "seg商家累积评价", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkCommentAcc segchkCommentAcc) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCommentAcc.setProviderId(sysUser.getProviderId()); + } + List list = segchkCommentAccService.selectSegchkCommentAccList(segchkCommentAcc); + ExcelUtil util = new ExcelUtil(SegchkCommentAcc.class); + return util.exportExcel(list, "seg商家累积评价数据"); + } + + /** + * 获取seg商家累积评价详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:query')") + @GetMapping(value = "/{updateId}") + public AjaxResult getInfo(@PathVariable("updateId") Long updateId) + { + return AjaxResult.success(segchkCommentAccService.selectSegchkCommentAccByUpdateId(updateId)); + } + + /** + * 新增seg商家累积评价 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:add')") + @Log(title = "seg商家累积评价", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkCommentAcc segchkCommentAcc) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCommentAcc.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkCommentAccService.insertSegchkCommentAcc(segchkCommentAcc)); + } + + /** + * 修改seg商家累积评价 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:edit')") + @Log(title = "seg商家累积评价", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkCommentAcc segchkCommentAcc) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkCommentAcc.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkCommentAccService.updateSegchkCommentAcc(segchkCommentAcc)); + } + + /** + * 删除seg商家累积评价 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_comment_acc:remove')") + @Log(title = "seg商家累积评价", businessType = BusinessType.DELETE) + @DeleteMapping("/{updateIds}") + public AjaxResult remove(@PathVariable Long[] updateIds) + { + return toAjax(segchkCommentAccService.deleteSegchkCommentAccByUpdateIds(updateIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkDistrictInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkDistrictInfoController.java new file mode 100644 index 0000000..20d1b84 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkDistrictInfoController.java @@ -0,0 +1,105 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkDistrictInfo; +import com.ruoyi.segchk.service.ISegchkDistrictInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg行政区域代码Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_district_info") +public class SegchkDistrictInfoController extends BaseController +{ + @Autowired + private ISegchkDistrictInfoService segchkDistrictInfoService; + + /** + * 查询seg行政区域代码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkDistrictInfo segchkDistrictInfo) + { + startPage(); + List list = segchkDistrictInfoService.selectSegchkDistrictInfoList(segchkDistrictInfo); + return getDataTable(list); + } + + /** + * 导出seg行政区域代码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:export')") + @Log(title = "seg行政区域代码", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkDistrictInfo segchkDistrictInfo) + { + List list = segchkDistrictInfoService.selectSegchkDistrictInfoList(segchkDistrictInfo); + ExcelUtil util = new ExcelUtil(SegchkDistrictInfo.class); + return util.exportExcel(list, "seg行政区域代码数据"); + } + + /** + * 获取seg行政区域代码详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:query')") + @GetMapping(value = "/{districtId}") + public AjaxResult getInfo(@PathVariable("districtId") Integer districtId) + { + return AjaxResult.success(segchkDistrictInfoService.selectSegchkDistrictInfoByDistrictId(districtId)); + } + + /** + * 新增seg行政区域代码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:add')") + @Log(title = "seg行政区域代码", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkDistrictInfo segchkDistrictInfo) + { + return toAjax(segchkDistrictInfoService.insertSegchkDistrictInfo(segchkDistrictInfo)); + } + + /** + * 修改seg行政区域代码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:edit')") + @Log(title = "seg行政区域代码", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkDistrictInfo segchkDistrictInfo) + { + return toAjax(segchkDistrictInfoService.updateSegchkDistrictInfo(segchkDistrictInfo)); + } + + /** + * 删除seg行政区域代码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_district_info:remove')") + @Log(title = "seg行政区域代码", businessType = BusinessType.DELETE) + @DeleteMapping("/{districtIds}") + public AjaxResult remove(@PathVariable Integer[] districtIds) + { + return toAjax(segchkDistrictInfoService.deleteSegchkDistrictInfoByDistrictIds(districtIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkKeywordLableController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkKeywordLableController.java new file mode 100644 index 0000000..60cba6b --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkKeywordLableController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkKeywordLable; +import com.ruoyi.segchk.service.ISegchkKeywordLableService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg关键字管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_keyword_lable") +public class SegchkKeywordLableController extends BaseController +{ + @Autowired + private ISegchkKeywordLableService segchkKeywordLableService; + + /** + * 查询seg关键字管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkKeywordLable segchkKeywordLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkKeywordLable.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkKeywordLableService.selectSegchkKeywordLableList(segchkKeywordLable); + return getDataTable(list); + } + + /** + * 导出seg关键字管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:export')") + @Log(title = "seg关键字管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkKeywordLable segchkKeywordLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkKeywordLable.setProviderId(sysUser.getProviderId()); + } + List list = segchkKeywordLableService.selectSegchkKeywordLableList(segchkKeywordLable); + ExcelUtil util = new ExcelUtil(SegchkKeywordLable.class); + return util.exportExcel(list, "seg关键字管理数据"); + } + + /** + * 获取seg关键字管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:query')") + @GetMapping(value = "/{keywordId}") + public AjaxResult getInfo(@PathVariable("keywordId") Long keywordId) + { + return AjaxResult.success(segchkKeywordLableService.selectSegchkKeywordLableByKeywordId(keywordId)); + } + + /** + * 新增seg关键字管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:add')") + @Log(title = "seg关键字管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkKeywordLable segchkKeywordLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkKeywordLable.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkKeywordLableService.insertSegchkKeywordLable(segchkKeywordLable)); + } + + /** + * 修改seg关键字管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:edit')") + @Log(title = "seg关键字管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkKeywordLable segchkKeywordLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkKeywordLable.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkKeywordLableService.updateSegchkKeywordLable(segchkKeywordLable)); + } + + /** + * 删除seg关键字管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_keyword_lable:remove')") + @Log(title = "seg关键字管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{keywordIds}") + public AjaxResult remove(@PathVariable Long[] keywordIds) + { + return toAjax(segchkKeywordLableService.deleteSegchkKeywordLableByKeywordIds(keywordIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLableMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLableMgtController.java new file mode 100644 index 0000000..fb2ccbf --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLableMgtController.java @@ -0,0 +1,165 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkLableMgt; +import com.ruoyi.segchk.service.ISegchkLableMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg首页标签管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_lable_mgt") +public class SegchkLableMgtController extends BaseController +{ + @Autowired + private ISegchkLableMgtService segchkLableMgtService; + + /** + * 查询seg首页标签管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkLableMgt segchkLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + logger.debug("segchk:segchk_lable_mgt:list get with---user: {}",sysUser.toString()); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLableMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkLableMgtService.selectSegchkLableMgtList(segchkLableMgt); + return getDataTable(list); + } + + /** + * 导出seg首页标签管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:export')") + @Log(title = "seg首页标签管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkLableMgt segchkLableMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLableMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkLableMgtService.selectSegchkLableMgtList(segchkLableMgt); + ExcelUtil util = new ExcelUtil(SegchkLableMgt.class); + return util.exportExcel(list, "seg首页标签管理数据"); + } + + /** + * 获取seg首页标签管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:query')") + @GetMapping(value = "/{mgtId}") + public AjaxResult getInfo(@PathVariable("mgtId") Long mgtId) + { + return AjaxResult.success(segchkLableMgtService.selectSegchkLableMgtByMgtId(mgtId)); + } + + /** + * 新增seg首页标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:add')") + @Log(title = "seg首页标签管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkLableMgt segchkLableMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkLableMgtService.insertSegchkLableMgt(segchkLableMgt)); + } + + /** + * 修改seg首页标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:edit')") + @Log(title = "seg首页标签管理", businessType = BusinessType.UPDATE) + @PutMapping("/edit_info") + public AjaxResult edit(@RequestBody SegchkLableMgt segchkLableMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkLableMgtService.updateSegchkLableMgt(segchkLableMgt)); + } + + + /** + * 修改seg首页标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:edit')") + @Log(title = "seg首页标签管理", businessType = BusinessType.UPDATE) + @PutMapping("/mgt_state") + public AjaxResult mgt_state(@RequestBody SegchkLableMgt segchkLableMgt) + { + logger.debug("mgt_state with --- {}", segchkLableMgt.toString()); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkLableMgtService.updateSegchkLableMgt(segchkLableMgt)); + } + + /** + * 删除seg首页标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_lable_mgt:remove')") + @Log(title = "seg首页标签管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{mgtIds}") + public AjaxResult remove(@PathVariable Long[] mgtIds) + { + return toAjax(segchkLableMgtService.deleteSegchkLableMgtByProviderIds(mgtIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLogionDetailController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLogionDetailController.java new file mode 100644 index 0000000..5eb65e1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkLogionDetailController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkLogionDetail; +import com.ruoyi.segchk.service.ISegchkLogionDetailService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg登录记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_logion_detail") +public class SegchkLogionDetailController extends BaseController +{ + @Autowired + private ISegchkLogionDetailService segchkLogionDetailService; + + /** + * 查询seg登录记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkLogionDetail segchkLogionDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLogionDetail.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkLogionDetailService.selectSegchkLogionDetailList(segchkLogionDetail); + return getDataTable(list); + } + + /** + * 导出seg登录记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:export')") + @Log(title = "seg登录记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkLogionDetail segchkLogionDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLogionDetail.setProviderId(sysUser.getProviderId()); + } + List list = segchkLogionDetailService.selectSegchkLogionDetailList(segchkLogionDetail); + ExcelUtil util = new ExcelUtil(SegchkLogionDetail.class); + return util.exportExcel(list, "seg登录记录数据"); + } + + /** + * 获取seg登录记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:query')") + @GetMapping(value = "/{loginId}") + public AjaxResult getInfo(@PathVariable("loginId") Long loginId) + { + return AjaxResult.success(segchkLogionDetailService.selectSegchkLogionDetailByLoginId(loginId)); + } + + /** + * 新增seg登录记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:add')") + @Log(title = "seg登录记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkLogionDetail segchkLogionDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLogionDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkLogionDetailService.insertSegchkLogionDetail(segchkLogionDetail)); + } + + /** + * 修改seg登录记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:edit')") + @Log(title = "seg登录记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkLogionDetail segchkLogionDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkLogionDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkLogionDetailService.updateSegchkLogionDetail(segchkLogionDetail)); + } + + /** + * 删除seg登录记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_logion_detail:remove')") + @Log(title = "seg登录记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{loginIds}") + public AjaxResult remove(@PathVariable Long[] loginIds) + { + return toAjax(segchkLogionDetailService.deleteSegchkLogionDetailByLoginIds(loginIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkMsgDetailController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkMsgDetailController.java new file mode 100644 index 0000000..40eb032 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkMsgDetailController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkMsgDetail; +import com.ruoyi.segchk.service.ISegchkMsgDetailService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg消息记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_msg_detail") +public class SegchkMsgDetailController extends BaseController +{ + @Autowired + private ISegchkMsgDetailService segchkMsgDetailService; + + /** + * 查询seg消息记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkMsgDetail segchkMsgDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkMsgDetail.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkMsgDetailService.selectSegchkMsgDetailList(segchkMsgDetail); + return getDataTable(list); + } + + /** + * 导出seg消息记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:export')") + @Log(title = "seg消息记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkMsgDetail segchkMsgDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkMsgDetail.setProviderId(sysUser.getProviderId()); + } + List list = segchkMsgDetailService.selectSegchkMsgDetailList(segchkMsgDetail); + ExcelUtil util = new ExcelUtil(SegchkMsgDetail.class); + return util.exportExcel(list, "seg消息记录数据"); + } + + /** + * 获取seg消息记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:query')") + @GetMapping(value = "/{msgId}") + public AjaxResult getInfo(@PathVariable("msgId") Long msgId) + { + return AjaxResult.success(segchkMsgDetailService.selectSegchkMsgDetailByMsgId(msgId)); + } + + /** + * 新增seg消息记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:add')") + @Log(title = "seg消息记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkMsgDetail segchkMsgDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkMsgDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkMsgDetailService.insertSegchkMsgDetail(segchkMsgDetail)); + } + + /** + * 修改seg消息记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:edit')") + @Log(title = "seg消息记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkMsgDetail segchkMsgDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkMsgDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkMsgDetailService.updateSegchkMsgDetail(segchkMsgDetail)); + } + + /** + * 删除seg消息记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_msg_detail:remove')") + @Log(title = "seg消息记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{msgIds}") + public AjaxResult remove(@PathVariable Long[] msgIds) + { + return toAjax(segchkMsgDetailService.deleteSegchkMsgDetailByMsgIds(msgIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkPreferenceLableController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkPreferenceLableController.java new file mode 100644 index 0000000..2e84908 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkPreferenceLableController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkPreferenceLable; +import com.ruoyi.segchk.service.ISegchkPreferenceLableService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg优惠管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_preference_lable") +public class SegchkPreferenceLableController extends BaseController +{ + @Autowired + private ISegchkPreferenceLableService segchkPreferenceLableService; + + /** + * 查询seg优惠管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkPreferenceLable segchkPreferenceLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkPreferenceLable.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkPreferenceLableService.selectSegchkPreferenceLableList(segchkPreferenceLable); + return getDataTable(list); + } + + /** + * 导出seg优惠管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:export')") + @Log(title = "seg优惠管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkPreferenceLable segchkPreferenceLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkPreferenceLable.setProviderId(sysUser.getProviderId()); + } + List list = segchkPreferenceLableService.selectSegchkPreferenceLableList(segchkPreferenceLable); + ExcelUtil util = new ExcelUtil(SegchkPreferenceLable.class); + return util.exportExcel(list, "seg优惠管理数据"); + } + + /** + * 获取seg优惠管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:query')") + @GetMapping(value = "/{preferenceId}") + public AjaxResult getInfo(@PathVariable("preferenceId") Long preferenceId) + { + return AjaxResult.success(segchkPreferenceLableService.selectSegchkPreferenceLableByPreferenceId(preferenceId)); + } + + /** + * 新增seg优惠管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:add')") + @Log(title = "seg优惠管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkPreferenceLable segchkPreferenceLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkPreferenceLable.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkPreferenceLableService.insertSegchkPreferenceLable(segchkPreferenceLable)); + } + + /** + * 修改seg优惠管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:edit')") + @Log(title = "seg优惠管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkPreferenceLable segchkPreferenceLable) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkPreferenceLable.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkPreferenceLableService.updateSegchkPreferenceLable(segchkPreferenceLable)); + } + + /** + * 删除seg优惠管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_preference_lable:remove')") + @Log(title = "seg优惠管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{preferenceIds}") + public AjaxResult remove(@PathVariable Long[] preferenceIds) + { + return toAjax(segchkPreferenceLableService.deleteSegchkPreferenceLableByPreferenceIds(preferenceIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkProviderMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkProviderMgtController.java new file mode 100644 index 0000000..dba1e4a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkProviderMgtController.java @@ -0,0 +1,161 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkProviderMgt; +import com.ruoyi.segchk.service.ISegchkProviderMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg运营商管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_provider_mgt") +public class SegchkProviderMgtController extends BaseController +{ + @Autowired + private ISegchkProviderMgtService segchkProviderMgtService; + + /** + * 查询seg运营商管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkProviderMgt segchkProviderMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkProviderMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkProviderMgtService.selectSegchkProviderMgtList(segchkProviderMgt); + return getDataTable(list); + } + + /** + * 导出seg运营商管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:export')") + @Log(title = "seg运营商管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkProviderMgt segchkProviderMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkProviderMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkProviderMgtService.selectSegchkProviderMgtList(segchkProviderMgt); + ExcelUtil util = new ExcelUtil(SegchkProviderMgt.class); + return util.exportExcel(list, "seg运营商管理数据"); + } + + /** + * 获取seg运营商管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:query')") + @GetMapping(value = "/{providerId}") + public AjaxResult getInfo(@PathVariable("providerId") Long providerId) + { + return AjaxResult.success(segchkProviderMgtService.selectSegchkProviderMgtByProviderId(providerId)); + } + + /** + * 新增seg运营商管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:add')") + @Log(title = "seg运营商管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkProviderMgt segchkProviderMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkProviderMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkProviderMgtService.insertSegchkProviderMgt(segchkProviderMgt)); + } + + /** + * 修改seg运营商管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:edit')") + @Log(title = "seg运营商管理", businessType = BusinessType.UPDATE) + @PutMapping("/edit") + public AjaxResult edit(@RequestBody SegchkProviderMgt segchkProviderMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkProviderMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkProviderMgtService.updateSegchkProviderMgt(segchkProviderMgt)); + } + + /** + * 修改seg运营商管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:edit')") + @Log(title = "seg运营商管理", businessType = BusinessType.UPDATE) + @PutMapping("/status") + public AjaxResult status(@RequestBody SegchkProviderMgt segchkProviderMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkProviderMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkProviderMgtService.updateSegchkProviderMgt(segchkProviderMgt)); + } + + /** + * 删除seg运营商管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_provider_mgt:remove')") + @Log(title = "seg运营商管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{providerIds}") + public AjaxResult remove(@PathVariable Long[] providerIds) + { + return toAjax(segchkProviderMgtService.deleteSegchkProviderMgtByProviderIds(providerIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkRecommenderStoreController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkRecommenderStoreController.java new file mode 100644 index 0000000..cfb3d2a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkRecommenderStoreController.java @@ -0,0 +1,161 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkRecommenderStore; +import com.ruoyi.segchk.service.ISegchkRecommenderStoreService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg首页推荐商户Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_recommender_store") +public class SegchkRecommenderStoreController extends BaseController +{ + @Autowired + private ISegchkRecommenderStoreService segchkRecommenderStoreService; + + /** + * 查询seg首页推荐商户列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkRecommenderStore segchkRecommenderStore) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkRecommenderStore.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkRecommenderStoreService.selectSegchkRecommenderStoreList(segchkRecommenderStore); + return getDataTable(list); + } + + /** + * 导出seg首页推荐商户列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:export')") + @Log(title = "seg首页推荐商户", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkRecommenderStore segchkRecommenderStore) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkRecommenderStore.setProviderId(sysUser.getProviderId()); + } + List list = segchkRecommenderStoreService.selectSegchkRecommenderStoreList(segchkRecommenderStore); + ExcelUtil util = new ExcelUtil(SegchkRecommenderStore.class); + return util.exportExcel(list, "seg首页推荐商户数据"); + } + + /** + * 获取seg首页推荐商户详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:query')") + @GetMapping(value = "/{recommenderId}") + public AjaxResult getInfo(@PathVariable("recommenderId") Long recommenderId) + { + return AjaxResult.success(segchkRecommenderStoreService.selectSegchkRecommenderStoreByRecommenderId(recommenderId)); + } + + /** + * 新增seg首页推荐商户 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:add')") + @Log(title = "seg首页推荐商户", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkRecommenderStore segchkRecommenderStore) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkRecommenderStore.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkRecommenderStoreService.insertSegchkRecommenderStore(segchkRecommenderStore)); + } + + /** + * 修改seg首页推荐商户 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:edit')") + @Log(title = "seg首页推荐商户", businessType = BusinessType.UPDATE) + @PutMapping("/edit_info") + public AjaxResult edit(@RequestBody SegchkRecommenderStore segchkRecommenderStore) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkRecommenderStore.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkRecommenderStoreService.updateSegchkRecommenderStore(segchkRecommenderStore)); + } + + /** + * 修改seg首页推荐商户 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:edit')") + @Log(title = "seg首页推荐商户", businessType = BusinessType.UPDATE) + @PutMapping("/mgt_state") + public AjaxResult mgt_state(@RequestBody SegchkRecommenderStore segchkRecommenderStore) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkRecommenderStore.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkRecommenderStoreService.updateSegchkRecommenderStore(segchkRecommenderStore)); + } + + /** + * 删除seg首页推荐商户 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_recommender_store:remove')") + @Log(title = "seg首页推荐商户", businessType = BusinessType.DELETE) + @DeleteMapping("/{recommenderIds}") + public AjaxResult remove(@PathVariable Long[] recommenderIds) + { + return toAjax(segchkRecommenderStoreService.deleteSegchkRecommenderStoreByRecommenderIds(recommenderIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSalerInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSalerInfoController.java new file mode 100644 index 0000000..b8a51ff --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSalerInfoController.java @@ -0,0 +1,161 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkSalerInfo; +import com.ruoyi.segchk.service.ISegchkSalerInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg销售人员信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_saler_info") +public class SegchkSalerInfoController extends BaseController +{ + @Autowired + private ISegchkSalerInfoService segchkSalerInfoService; + + /** + * 查询seg销售人员信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkSalerInfo segchkSalerInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSalerInfo.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkSalerInfoService.selectSegchkSalerInfoList(segchkSalerInfo); + return getDataTable(list); + } + + /** + * 导出seg销售人员信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:export')") + @Log(title = "seg销售人员信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkSalerInfo segchkSalerInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSalerInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkSalerInfoService.selectSegchkSalerInfoList(segchkSalerInfo); + ExcelUtil util = new ExcelUtil(SegchkSalerInfo.class); + return util.exportExcel(list, "seg销售人员信息数据"); + } + + /** + * 获取seg销售人员信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:query')") + @GetMapping(value = "/{salerId}") + public AjaxResult getInfo(@PathVariable("salerId") Integer salerId) + { + return AjaxResult.success(segchkSalerInfoService.selectSegchkSalerInfoBySalerId(salerId)); + } + + /** + * 新增seg销售人员信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:add')") + @Log(title = "seg销售人员信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkSalerInfo segchkSalerInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSalerInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSalerInfoService.insertSegchkSalerInfo(segchkSalerInfo)); + } + + /** + * 修改seg销售人员信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:edit')") + @Log(title = "seg销售人员信息", businessType = BusinessType.UPDATE) + @PutMapping("/edit") + public AjaxResult edit(@RequestBody SegchkSalerInfo segchkSalerInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSalerInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSalerInfoService.updateSegchkSalerInfo(segchkSalerInfo)); + } + + /** + * 修改seg销售人员信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:edit')") + @Log(title = "seg销售人员信息", businessType = BusinessType.UPDATE) + @PutMapping("/update_status") + public AjaxResult update_status(@RequestBody SegchkSalerInfo segchkSalerInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSalerInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSalerInfoService.updateSegchkSalerInfo(segchkSalerInfo)); + } + + /** + * 删除seg销售人员信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_saler_info:remove')") + @Log(title = "seg销售人员信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{salerIds}") + public AjaxResult remove(@PathVariable Integer[] salerIds) + { + return toAjax(segchkSalerInfoService.deleteSegchkSalerInfoBySalerIds(salerIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSelfServiceChkController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSelfServiceChkController.java new file mode 100644 index 0000000..777d5c0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSelfServiceChkController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkSelfServiceChk; +import com.ruoyi.segchk.service.ISegchkSelfServiceChkService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg自定义卡核消记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_self_service_chk") +public class SegchkSelfServiceChkController extends BaseController +{ + @Autowired + private ISegchkSelfServiceChkService segchkSelfServiceChkService; + + /** + * 查询seg自定义卡核消记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkSelfServiceChk segchkSelfServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSelfServiceChk.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkSelfServiceChkService.selectSegchkSelfServiceChkList(segchkSelfServiceChk); + return getDataTable(list); + } + + /** + * 导出seg自定义卡核消记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:export')") + @Log(title = "seg自定义卡核消记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkSelfServiceChk segchkSelfServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSelfServiceChk.setProviderId(sysUser.getProviderId()); + } + List list = segchkSelfServiceChkService.selectSegchkSelfServiceChkList(segchkSelfServiceChk); + ExcelUtil util = new ExcelUtil(SegchkSelfServiceChk.class); + return util.exportExcel(list, "seg自定义卡核消记录数据"); + } + + /** + * 获取seg自定义卡核消记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:query')") + @GetMapping(value = "/{chkServiceId}") + public AjaxResult getInfo(@PathVariable("chkServiceId") Long chkServiceId) + { + return AjaxResult.success(segchkSelfServiceChkService.selectSegchkSelfServiceChkByChkServiceId(chkServiceId)); + } + + /** + * 新增seg自定义卡核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:add')") + @Log(title = "seg自定义卡核消记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkSelfServiceChk segchkSelfServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSelfServiceChk.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSelfServiceChkService.insertSegchkSelfServiceChk(segchkSelfServiceChk)); + } + + /** + * 修改seg自定义卡核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:edit')") + @Log(title = "seg自定义卡核消记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkSelfServiceChk segchkSelfServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSelfServiceChk.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSelfServiceChkService.updateSegchkSelfServiceChk(segchkSelfServiceChk)); + } + + /** + * 删除seg自定义卡核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk: segchk_self_service_chk:remove')") + @Log(title = "seg自定义卡核消记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{chkServiceIds}") + public AjaxResult remove(@PathVariable Long[] chkServiceIds) + { + return toAjax(segchkSelfServiceChkService.deleteSegchkSelfServiceChkByChkServiceIds(chkServiceIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceChkController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceChkController.java new file mode 100644 index 0000000..ee57936 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceChkController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkServiceChk; +import com.ruoyi.segchk.service.ISegchkServiceChkService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg核消记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_service_chk") +public class SegchkServiceChkController extends BaseController +{ + @Autowired + private ISegchkServiceChkService segchkServiceChkService; + + /** + * 查询seg核消记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkServiceChk segchkServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceChk.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkServiceChkService.selectSegchkServiceChkList(segchkServiceChk); + return getDataTable(list); + } + + /** + * 导出seg核消记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:export')") + @Log(title = "seg核消记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkServiceChk segchkServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceChk.setProviderId(sysUser.getProviderId()); + } + List list = segchkServiceChkService.selectSegchkServiceChkList(segchkServiceChk); + ExcelUtil util = new ExcelUtil(SegchkServiceChk.class); + return util.exportExcel(list, "seg核消记录数据"); + } + + /** + * 获取seg核消记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:query')") + @GetMapping(value = "/{chkServiceId}") + public AjaxResult getInfo(@PathVariable("chkServiceId") Long chkServiceId) + { + return AjaxResult.success(segchkServiceChkService.selectSegchkServiceChkByChkServiceId(chkServiceId)); + } + + /** + * 新增seg核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:add')") + @Log(title = "seg核消记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkServiceChk segchkServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceChk.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkServiceChkService.insertSegchkServiceChk(segchkServiceChk)); + } + + /** + * 修改seg核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:edit')") + @Log(title = "seg核消记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkServiceChk segchkServiceChk) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceChk.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkServiceChkService.updateSegchkServiceChk(segchkServiceChk)); + } + + /** + * 删除seg核消记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_chk:remove')") + @Log(title = "seg核消记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{chkServiceIds}") + public AjaxResult remove(@PathVariable Long[] chkServiceIds) + { + return toAjax(segchkServiceChkService.deleteSegchkServiceChkByChkServiceIds(chkServiceIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceCommentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceCommentController.java new file mode 100644 index 0000000..d67feb3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkServiceCommentController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkServiceComment; +import com.ruoyi.segchk.service.ISegchkServiceCommentService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg评价记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_service_comment") +public class SegchkServiceCommentController extends BaseController +{ + @Autowired + private ISegchkServiceCommentService segchkServiceCommentService; + + /** + * 查询seg评价记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkServiceComment segchkServiceComment) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceComment.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkServiceCommentService.selectSegchkServiceCommentList(segchkServiceComment); + return getDataTable(list); + } + + /** + * 导出seg评价记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:export')") + @Log(title = "seg评价记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkServiceComment segchkServiceComment) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceComment.setProviderId(sysUser.getProviderId()); + } + List list = segchkServiceCommentService.selectSegchkServiceCommentList(segchkServiceComment); + ExcelUtil util = new ExcelUtil(SegchkServiceComment.class); + return util.exportExcel(list, "seg评价记录数据"); + } + + /** + * 获取seg评价记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:query')") + @GetMapping(value = "/{commentId}") + public AjaxResult getInfo(@PathVariable("commentId") Long commentId) + { + return AjaxResult.success(segchkServiceCommentService.selectSegchkServiceCommentByCommentId(commentId)); + } + + /** + * 新增seg评价记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:add')") + @Log(title = "seg评价记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkServiceComment segchkServiceComment) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceComment.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkServiceCommentService.insertSegchkServiceComment(segchkServiceComment)); + } + + /** + * 修改seg评价记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:edit')") + @Log(title = "seg评价记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkServiceComment segchkServiceComment) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkServiceComment.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkServiceCommentService.updateSegchkServiceComment(segchkServiceComment)); + } + + /** + * 删除seg评价记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_service_comment:remove')") + @Log(title = "seg评价记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{commentIds}") + public AjaxResult remove(@PathVariable Long[] commentIds) + { + return toAjax(segchkServiceCommentService.deleteSegchkServiceCommentByCommentIds(commentIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSimpleListController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSimpleListController.java new file mode 100644 index 0000000..3a0651b --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSimpleListController.java @@ -0,0 +1,304 @@ +package com.ruoyi.web.controller.segchk; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.BaseEntity; +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.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.service.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * seg首页轮播图管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/simple_list") +public class SegchkSimpleListController extends BaseController +{ + @Autowired + private ISegchkProviderMgtService segchkProviderMgtService; + @Autowired + private ISegchkSalerInfoService segchkSalerInfoService; + @Autowired + private ISegchkStoreBasicInfoService segchkStoreBasicInfoService; + + @Autowired + private ISegchkChargeCardService segchkChargeCardService; + + @Autowired + private ISegchkKeywordLableService segchkKeywordLableService; + + + @Autowired + private ISegchkPreferenceLableService segchkPreferenceLableService; + + @Autowired + private ISegchkDistrictInfoService segchkDistrictInfoService; + + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/salerList") + public TableDataInfo saler_list() + { + logger.debug("salerList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkSalerInfo segchkSalerInfo = new SegchkSalerInfo(); + segchkSalerInfo.setProviderId(providerId); + List list = segchkSalerInfoService.selectSegchkSalerInfoList(segchkSalerInfo); + List collect = list.parallelStream().filter(v -> v.getSalerState() == 0).map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getSalerId())); + simpleListObj1.setValue(String.valueOf(v.getSalerName())); + return simpleListObj1; + }).collect(Collectors.toList()); + return getDataTable(collect); + } + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/providerList") + public TableDataInfo provider_list() + { + logger.debug("providerList is call"); + SimpleListObj simpleListObj = new SimpleListObj(); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkProviderMgt segchkProviderMgt = new SegchkProviderMgt(); + segchkProviderMgt.setProviderId(providerId); + List list = segchkProviderMgtService.selectSegchkProviderMgtList(segchkProviderMgt); + List collect = list.parallelStream().map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getProviderId())); + simpleListObj1.setValue(String.valueOf(v.getNickName())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("providerList ret : {}", v.toString())); + return getDataTable(collect); + } + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/storeList") + public TableDataInfo store_list() + { + logger.debug("storeList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkStoreBasicInfo segchkStoreBasicInfo = new SegchkStoreBasicInfo(); + segchkStoreBasicInfo.setProviderId(providerId); + List list = segchkStoreBasicInfoService.selectSegchkStoreBasicInfoList(segchkStoreBasicInfo); + List collect = list.parallelStream().map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getStoreId())); + simpleListObj1.setValue(String.valueOf(v.getStoreName())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("providerList ret : {}", v.toString())); + return getDataTable(collect); + } + + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/ChargeCardList") + public TableDataInfo charge_card_list() + { + logger.debug("ChargeCardList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkChargeCard segchkChargeCard = new SegchkChargeCard(); + segchkChargeCard.setProviderId(providerId); + List list = segchkChargeCardService.selectSegchkChargeCardList(segchkChargeCard); + List collect = list.parallelStream().map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getCardTypeId())); + simpleListObj1.setValue(String.valueOf(v.getCardTypeName())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("ChargeCardList ret : {}", v.toString())); + return getDataTable(collect); + } + + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/KerwordList") + public TableDataInfo kerword_list() + { + logger.debug("KerwordList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkKeywordLable segchkKeywordLable = new SegchkKeywordLable(); + segchkKeywordLable.setProviderId(providerId); + List list = segchkKeywordLableService.selectSegchkKeywordLableList(segchkKeywordLable); + List collect = list.parallelStream().map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getKeywordId())); + simpleListObj1.setValue(String.valueOf(v.getKeywordName())); + simpleListObj1.setImgUrl(String.valueOf(v.getKeywordUrl())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("KerwordList ret : {}", v.toString())); + return getDataTable(collect); + } + + + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/PreferenceLableList") + public TableDataInfo preference_lable_list() + { + logger.debug("PreferenceLableList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + SegchkPreferenceLable segchkPreferenceLable = new SegchkPreferenceLable(); + segchkPreferenceLable.setProviderId(providerId); + List list = segchkPreferenceLableService.selectSegchkPreferenceLableList(segchkPreferenceLable); + List collect = list.parallelStream().map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(v.getProviderId())); + simpleListObj1.setKey(String.valueOf(v.getPreferenceId())); + simpleListObj1.setValue(String.valueOf(v.getPreferenceName())); + simpleListObj1.setImgUrl(String.valueOf(v.getPreferenceUrl())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("PreferenceLableList ret : {}", v.toString())); + return getDataTable(collect); + } + + /** + * 查询seg首页轮播图管理列表 + */ + @UnAuth +// @PreAuthorize("@ss.hasPermi('segchk:segchk_carouse_mgt:list')") + @GetMapping("/DistictList") + public TableDataInfo distict_list() + { + logger.debug("DistictList is call"); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); +// sysUser.getNickName(); + Long providerId = sysUser.getUserId() == 1 ? null : sysUser.getProviderId(); + startPage(); + + SegchkDistrictInfo segchkDistrictInfo = new SegchkDistrictInfo(); + List list = segchkDistrictInfoService.selectSegchkDistrictInfoList(segchkDistrictInfo); + List collect = list.parallelStream().filter(v -> v.getDistrictLevel() == 0 || v.getDistrictLevel() == 1).map(v -> { + SimpleListObj simpleListObj1 = new SimpleListObj(); + simpleListObj1.setProviderId(String.valueOf(providerId)); + simpleListObj1.setKey(String.valueOf(v.getDistrictId())); + simpleListObj1.setValue(String.valueOf(v.getDistrictName())); + return simpleListObj1; + }).collect(Collectors.toList()); + collect.forEach(v -> logger.debug("PreferenceLableList ret : {}", v.toString())); + return getDataTable(collect); + } + + + private class SimpleListObj extends BaseEntity { + private String providerId; + private String key; + private String value; + private String imgUrl; + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + @Override + public String toString() { + return "SimpleListObj{" + + "providerId='" + providerId + '\'' + + ", key='" + key + '\'' + + ", value='" + value + '\'' + + ", imgUrl='" + imgUrl + '\'' + + '}'; + } + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSmsDetailController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSmsDetailController.java new file mode 100644 index 0000000..dd056a6 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSmsDetailController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkSmsDetail; +import com.ruoyi.segchk.service.ISegchkSmsDetailService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg短信记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_sms_detail") +public class SegchkSmsDetailController extends BaseController +{ + @Autowired + private ISegchkSmsDetailService segchkSmsDetailService; + + /** + * 查询seg短信记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkSmsDetail segchkSmsDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSmsDetail.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkSmsDetailService.selectSegchkSmsDetailList(segchkSmsDetail); + return getDataTable(list); + } + + /** + * 导出seg短信记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:export')") + @Log(title = "seg短信记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkSmsDetail segchkSmsDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSmsDetail.setProviderId(sysUser.getProviderId()); + } + List list = segchkSmsDetailService.selectSegchkSmsDetailList(segchkSmsDetail); + ExcelUtil util = new ExcelUtil(SegchkSmsDetail.class); + return util.exportExcel(list, "seg短信记录数据"); + } + + /** + * 获取seg短信记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:query')") + @GetMapping(value = "/{shortMsgId}") + public AjaxResult getInfo(@PathVariable("shortMsgId") Long shortMsgId) + { + return AjaxResult.success(segchkSmsDetailService.selectSegchkSmsDetailByShortMsgId(shortMsgId)); + } + + /** + * 新增seg短信记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:add')") + @Log(title = "seg短信记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkSmsDetail segchkSmsDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSmsDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSmsDetailService.insertSegchkSmsDetail(segchkSmsDetail)); + } + + /** + * 修改seg短信记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:edit')") + @Log(title = "seg短信记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkSmsDetail segchkSmsDetail) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkSmsDetail.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkSmsDetailService.updateSegchkSmsDetail(segchkSmsDetail)); + } + + /** + * 删除seg短信记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_sms_detail:remove')") + @Log(title = "seg短信记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{shortMsgIds}") + public AjaxResult remove(@PathVariable Long[] shortMsgIds) + { + return toAjax(segchkSmsDetailService.deleteSegchkSmsDetailByShortMsgIds(shortMsgIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreAccountController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreAccountController.java new file mode 100644 index 0000000..9bd80f1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreAccountController.java @@ -0,0 +1,142 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreAccount; +import com.ruoyi.segchk.service.ISegchkStoreAccountService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商户余额信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_account") +public class SegchkStoreAccountController extends BaseController +{ + @Autowired + private ISegchkStoreAccountService segchkStoreAccountService; + + /** + * 查询seg商户余额信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreAccount segchkStoreAccount) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreAccount.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreAccountService.selectSegchkStoreAccountList(segchkStoreAccount); + return getDataTable(list); + } + + /** + * 导出seg商户余额信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:export')") + @Log(title = "seg商户余额信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreAccount segchkStoreAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreAccount.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreAccountService.selectSegchkStoreAccountList(segchkStoreAccount); + ExcelUtil util = new ExcelUtil(SegchkStoreAccount.class); + return util.exportExcel(list, "seg商户余额信息数据"); + } + + /** + * 获取seg商户余额信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:query')") + @GetMapping(value = "/{accountId}") + public AjaxResult getInfo(@PathVariable("accountId") Long accountId) + { + return AjaxResult.success(segchkStoreAccountService.selectSegchkStoreAccountByAccountId(accountId)); + } + + /** + * 新增seg商户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:add')") + @Log(title = "seg商户余额信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreAccount segchkStoreAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreAccount.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreAccountService.insertSegchkStoreAccount(segchkStoreAccount)); + } + + /** + * 修改seg商户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:edit')") + @Log(title = "seg商户余额信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreAccount segchkStoreAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreAccount.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreAccountService.updateSegchkStoreAccount(segchkStoreAccount)); + } + + /** + * 删除seg商户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_account:remove')") + @Log(title = "seg商户余额信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{accountIds}") + public AjaxResult remove(@PathVariable Long[] accountIds) + { + return toAjax(segchkStoreAccountService.deleteSegchkStoreAccountByAccountIds(accountIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreBasicInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreBasicInfoController.java new file mode 100644 index 0000000..bd89d10 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreBasicInfoController.java @@ -0,0 +1,213 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreBasicInfo; +import com.ruoyi.segchk.service.ISegchkStoreBasicInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家基础信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_basic_info") +public class SegchkStoreBasicInfoController extends BaseController +{ + @Autowired + private ISegchkStoreBasicInfoService segchkStoreBasicInfoService; + + /** + * 查询seg商家基础信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreBasicInfo segchkStoreBasicInfo) + { +// 获取当前登录用户信息 + LoginUser loginUser = getLoginUser(); + SysUser sysUser = loginUser.getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + System.out.println("segchk:segchk_store_basic_info:list userinfo:" + loginUser.toString()); + System.out.println("segchk:segchk_store_basic_info:list userinfo:" + sysUser.getRoleId()); + sysUser.getRoles().forEach(it -> System.out.println(it.toString())); + startPage(); + List list = segchkStoreBasicInfoService.selectSegchkStoreBasicInfoList(segchkStoreBasicInfo); + return getDataTable(list); + } + + /** + * 导出seg商家基础信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:export')") + @Log(title = "seg商家基础信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreBasicInfo segchkStoreBasicInfo) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreBasicInfoService.selectSegchkStoreBasicInfoList(segchkStoreBasicInfo); + ExcelUtil util = new ExcelUtil(SegchkStoreBasicInfo.class); + return util.exportExcel(list, "seg商家基础信息数据"); + } + + /** + * 获取seg商家基础信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:query')") + @GetMapping(value = "/{storeId}") + public AjaxResult getInfo(@PathVariable("storeId") Long storeId) + { + return AjaxResult.success(segchkStoreBasicInfoService.selectSegchkStoreBasicInfoByStoreId(storeId)); + } + + /** + * 新增seg商家基础信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:add')") + @Log(title = "seg商家基础信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreBasicInfo segchkStoreBasicInfo) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + int i = segchkStoreBasicInfoService.insertSegchkStoreBasicInfo(segchkStoreBasicInfo); + if(i < 0){ + return AjaxResult.error(500, "手机号码已绑定商户"); + } + else { + return toAjax(i); + } + } + + /** + * 修改seg商家基础信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:edit')") + @Log(title = "seg商家基础信息", businessType = BusinessType.UPDATE) + @PutMapping("edit_info") + public AjaxResult edit(@RequestBody SegchkStoreBasicInfo segchkStoreBasicInfo) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + logger.debug("edit_info with ---> {}", segchkStoreBasicInfo.toString()); + int i = segchkStoreBasicInfoService.updateSegchkStoreBasicInfo(segchkStoreBasicInfo); + if(i < 0){ + return AjaxResult.error(500, "手机号码已绑定商户"); + } + else { + return toAjax(i); + } + } + + /** + * 修改seg商家基础信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:edit')") + @Log(title = "seg商家基础信息", businessType = BusinessType.UPDATE) + @PutMapping("update_detail") + public AjaxResult update_detail(@RequestBody SegchkStoreBasicInfo segchkStoreBasicInfo) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + logger.debug("update_detail with ---> {}", segchkStoreBasicInfo.toString()); + int i = segchkStoreBasicInfoService.updateSegchkStoreDetail(segchkStoreBasicInfo); + return toAjax(i); + } + + /** + * 修改seg商家服务状态 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:edit')") + @Log(title = "seg商家基础信息", businessType = BusinessType.UPDATE) + @PutMapping("service_state") +// public AjaxResult service_state(Long providerId, Long storeId, String serviceState) + public AjaxResult service_state(@RequestBody SegchkStoreBasicInfo segchkStoreBasicInfo) + { +// SegchkStoreBasicInfo segchkStoreBasicInfo = new SegchkStoreBasicInfo(); +// segchkStoreBasicInfo.setProviderId(providerId); +// segchkStoreBasicInfo.setStoreId(storeId); +// segchkStoreBasicInfo.setServiceState(serviceState); +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreBasicInfo.setProviderId(sysUser.getProviderId()); + } + logger.debug("service_state with: {}", segchkStoreBasicInfo.toString()); + return toAjax(segchkStoreBasicInfoService.updateSegchkStoreServiceStatus(segchkStoreBasicInfo)); + } + + /** + * 删除seg商家基础信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_basic_info:remove')") + @Log(title = "seg商家基础信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{storeIds}") + public AjaxResult remove(@PathVariable Long[] storeIds) + { + return toAjax(segchkStoreBasicInfoService.deleteSegchkStoreBasicInfoByStoreIds(storeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreCashController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreCashController.java new file mode 100644 index 0000000..199bd44 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreCashController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreCash; +import com.ruoyi.segchk.service.ISegchkStoreCashService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商户户提现记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_cash") +public class SegchkStoreCashController extends BaseController +{ + @Autowired + private ISegchkStoreCashService segchkStoreCashService; + + /** + * 查询seg商户户提现记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreCash segchkStoreCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCash.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreCashService.selectSegchkStoreCashList(segchkStoreCash); + return getDataTable(list); + } + + /** + * 导出seg商户户提现记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:export')") + @Log(title = "seg商户户提现记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreCash segchkStoreCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCash.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreCashService.selectSegchkStoreCashList(segchkStoreCash); + ExcelUtil util = new ExcelUtil(SegchkStoreCash.class); + return util.exportExcel(list, "seg商户户提现记录数据"); + } + + /** + * 获取seg商户户提现记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:query')") + @GetMapping(value = "/{cashId}") + public AjaxResult getInfo(@PathVariable("cashId") Long cashId) + { + return AjaxResult.success(segchkStoreCashService.selectSegchkStoreCashByCashId(cashId)); + } + + /** + * 新增seg商户户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:add')") + @Log(title = "seg商户户提现记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreCash segchkStoreCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCash.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreCashService.insertSegchkStoreCash(segchkStoreCash)); + } + + /** + * 修改seg商户户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:edit')") + @Log(title = "seg商户户提现记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreCash segchkStoreCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCash.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreCashService.updateSegchkStoreCash(segchkStoreCash)); + } + + /** + * 删除seg商户户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_cash:remove')") + @Log(title = "seg商户户提现记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{cashIds}") + public AjaxResult remove(@PathVariable Long[] cashIds) + { + return toAjax(segchkStoreCashService.deleteSegchkStoreCashByCashIds(cashIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChargeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChargeController.java new file mode 100644 index 0000000..3173959 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChargeController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreCharge; +import com.ruoyi.segchk.service.ISegchkStoreChargeService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商户充值记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_charge") +public class SegchkStoreChargeController extends BaseController +{ + @Autowired + private ISegchkStoreChargeService segchkStoreChargeService; + + /** + * 查询seg商户充值记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreCharge segchkStoreCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCharge.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreChargeService.selectSegchkStoreChargeList(segchkStoreCharge); + return getDataTable(list); + } + + /** + * 导出seg商户充值记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:export')") + @Log(title = "seg商户充值记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreCharge segchkStoreCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCharge.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreChargeService.selectSegchkStoreChargeList(segchkStoreCharge); + ExcelUtil util = new ExcelUtil(SegchkStoreCharge.class); + return util.exportExcel(list, "seg商户充值记录数据"); + } + + /** + * 获取seg商户充值记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:query')") + @GetMapping(value = "/{chargeId}") + public AjaxResult getInfo(@PathVariable("chargeId") Long chargeId) + { + return AjaxResult.success(segchkStoreChargeService.selectSegchkStoreChargeByChargeId(chargeId)); + } + + /** + * 新增seg商户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:add')") + @Log(title = "seg商户充值记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreCharge segchkStoreCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCharge.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreChargeService.insertSegchkStoreCharge(segchkStoreCharge)); + } + + /** + * 修改seg商户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:edit')") + @Log(title = "seg商户充值记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreCharge segchkStoreCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreCharge.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreChargeService.updateSegchkStoreCharge(segchkStoreCharge)); + } + + /** + * 删除seg商户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_charge:remove')") + @Log(title = "seg商户充值记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{chargeIds}") + public AjaxResult remove(@PathVariable Long[] chargeIds) + { + return toAjax(segchkStoreChargeService.deleteSegchkStoreChargeByChargeIds(chargeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChkMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChkMgtController.java new file mode 100644 index 0000000..fd30328 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreChkMgtController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreChkMgt; +import com.ruoyi.segchk.service.ISegchkStoreChkMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家核消卡管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_chk_mgt") +public class SegchkStoreChkMgtController extends BaseController +{ + @Autowired + private ISegchkStoreChkMgtService segchkStoreChkMgtService; + + /** + * 查询seg商家核消卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreChkMgt segchkStoreChkMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreChkMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreChkMgtService.selectSegchkStoreChkMgtList(segchkStoreChkMgt); + return getDataTable(list); + } + + /** + * 导出seg商家核消卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:export')") + @Log(title = "seg商家核消卡管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreChkMgt segchkStoreChkMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreChkMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreChkMgtService.selectSegchkStoreChkMgtList(segchkStoreChkMgt); + ExcelUtil util = new ExcelUtil(SegchkStoreChkMgt.class); + return util.exportExcel(list, "seg商家核消卡管理数据"); + } + + /** + * 获取seg商家核消卡管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:query')") + @GetMapping(value = "/{mgtId}") + public AjaxResult getInfo(@PathVariable("mgtId") Integer mgtId) + { + return AjaxResult.success(segchkStoreChkMgtService.selectSegchkStoreChkMgtByMgtId(mgtId)); + } + + /** + * 新增seg商家核消卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:add')") + @Log(title = "seg商家核消卡管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreChkMgt segchkStoreChkMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreChkMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreChkMgtService.insertSegchkStoreChkMgt(segchkStoreChkMgt)); + } + + /** + * 修改seg商家核消卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:edit')") + @Log(title = "seg商家核消卡管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreChkMgt segchkStoreChkMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreChkMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreChkMgtService.updateSegchkStoreChkMgt(segchkStoreChkMgt)); + } + + /** + * 删除seg商家核消卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_chk_mgt:remove')") + @Log(title = "seg商家核消卡管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{mgtIds}") + public AjaxResult remove(@PathVariable Integer[] mgtIds) + { + return toAjax(segchkStoreChkMgtService.deleteSegchkStoreChkMgtByMgtIds(mgtIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreImageController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreImageController.java new file mode 100644 index 0000000..a4d7523 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreImageController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreImage; +import com.ruoyi.segchk.service.ISegchkStoreImageService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家图片信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_image") +public class SegchkStoreImageController extends BaseController +{ + @Autowired + private ISegchkStoreImageService segchkStoreImageService; + + /** + * 查询seg商家图片信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreImage segchkStoreImage) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreImage.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreImageService.selectSegchkStoreImageList(segchkStoreImage); + return getDataTable(list); + } + + /** + * 导出seg商家图片信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:export')") + @Log(title = "seg商家图片信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreImage segchkStoreImage) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreImage.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreImageService.selectSegchkStoreImageList(segchkStoreImage); + ExcelUtil util = new ExcelUtil(SegchkStoreImage.class); + return util.exportExcel(list, "seg商家图片信息数据"); + } + + /** + * 获取seg商家图片信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:query')") + @GetMapping(value = "/{storeId}") + public AjaxResult getInfo(@PathVariable("storeId") Long storeId) + { + return AjaxResult.success(segchkStoreImageService.selectSegchkStoreImageByStoreId(storeId)); + } + + /** + * 新增seg商家图片信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:add')") + @Log(title = "seg商家图片信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreImage segchkStoreImage) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreImage.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreImageService.insertSegchkStoreImage(segchkStoreImage)); + } + + /** + * 修改seg商家图片信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:edit')") + @Log(title = "seg商家图片信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreImage segchkStoreImage) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreImage.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreImageService.updateSegchkStoreImage(segchkStoreImage)); + } + + /** + * 删除seg商家图片信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_image:remove')") + @Log(title = "seg商家图片信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{storeIds}") + public AjaxResult remove(@PathVariable Long[] storeIds) + { + return toAjax(segchkStoreImageService.deleteSegchkStoreImageByStoreIds(storeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreLableMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreLableMgtController.java new file mode 100644 index 0000000..4108424 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreLableMgtController.java @@ -0,0 +1,166 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreLableMgt; +import com.ruoyi.segchk.service.ISegchkStoreLableMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家标签管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_lable_mgt") +public class SegchkStoreLableMgtController extends BaseController +{ + @Autowired + private ISegchkStoreLableMgtService segchkStoreLableMgtService; + + /** + * 查询seg商家标签管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreLableMgt segchkStoreLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreLableMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreLableMgtService.selectSegchkStoreLableMgtList(segchkStoreLableMgt); + return getDataTable(list); + } + + /** + * 导出seg商家标签管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:export')") + @Log(title = "seg商家标签管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreLableMgt segchkStoreLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreLableMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreLableMgtService.selectSegchkStoreLableMgtList(segchkStoreLableMgt); + ExcelUtil util = new ExcelUtil(SegchkStoreLableMgt.class); + return util.exportExcel(list, "seg商家标签管理数据"); + } + + /** + * 获取seg商家标签管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:query')") + @GetMapping(value = "/{mgtId}") + public AjaxResult getInfo(@PathVariable("mgtId") Integer mgtId) + { + return AjaxResult.success(segchkStoreLableMgtService.selectSegchkStoreLableMgtByMgtId(mgtId)); + } + + /** + * 新增seg商家标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:add')") + @Log(title = "seg商家标签管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreLableMgt segchkStoreLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreLableMgtService.insertSegchkStoreLableMgt(segchkStoreLableMgt)); + } + + /** + * 修改seg商家标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:edit')") + @Log(title = "seg商家标签管理", businessType = BusinessType.UPDATE) + @PutMapping("/edit") + public AjaxResult edit(@RequestBody SegchkStoreLableMgt segchkStoreLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreLableMgtService.updateSegchkStoreLableMgt(segchkStoreLableMgt)); + } + + /** + * 修改seg商家标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:edit')") + @Log(title = "seg商家标签管理", businessType = BusinessType.UPDATE) + @PutMapping("/update_status") + public AjaxResult update_status(@RequestBody SegchkStoreLableMgt segchkStoreLableMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreLableMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreLableMgtService.updateSegchkStoreLableMgt(segchkStoreLableMgt)); + } + + /** + * 删除seg商家标签管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_lable_mgt:remove')") + @Log(title = "seg商家标签管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{mgtIds}") + public AjaxResult remove(@PathVariable Integer[] mgtIds) + { + return toAjax(segchkStoreLableMgtService.deleteSegchkStoreLableMgtByMgtIds(mgtIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreRewardController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreRewardController.java new file mode 100644 index 0000000..a510282 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreRewardController.java @@ -0,0 +1,145 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreReward; +import com.ruoyi.segchk.service.ISegchkStoreRewardService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商户奖励Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_reward") +public class SegchkStoreRewardController extends BaseController +{ + @Autowired + private ISegchkStoreRewardService segchkStoreRewardService; + + /** + * 查询seg商户奖励列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreReward segchkStoreReward) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreReward.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreRewardService.selectSegchkStoreRewardList(segchkStoreReward); + return getDataTable(list); + } + + /** + * 导出seg商户奖励列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:export')") + @Log(title = "seg商户奖励", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreReward segchkStoreReward) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreReward.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreRewardService.selectSegchkStoreRewardList(segchkStoreReward); + ExcelUtil util = new ExcelUtil(SegchkStoreReward.class); + return util.exportExcel(list, "seg商户奖励数据"); + } + + /** + * 获取seg商户奖励详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:query')") + @GetMapping(value = "/{rewardId}") + public AjaxResult getInfo(@PathVariable("rewardId") Long rewardId) + { + return AjaxResult.success(segchkStoreRewardService.selectSegchkStoreRewardByRewardId(rewardId)); + } + + /** + * 新增seg商户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:add')") + @Log(title = "seg商户奖励", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreReward segchkStoreReward) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreReward.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreRewardService.insertSegchkStoreReward(segchkStoreReward)); + } + + /** + * 修改seg商户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:edit')") + @Log(title = "seg商户奖励", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreReward segchkStoreReward) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreReward.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreRewardService.updateSegchkStoreReward(segchkStoreReward)); + } + + /** + * 删除seg商户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_reward:remove')") + @Log(title = "seg商户奖励", businessType = BusinessType.DELETE) + @DeleteMapping("/{rewardIds}") + public AjaxResult remove(@PathVariable Long[] rewardIds) + { + return toAjax(segchkStoreRewardService.deleteSegchkStoreRewardByRewardIds(rewardIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSecurityController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSecurityController.java new file mode 100644 index 0000000..45c3dc5 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSecurityController.java @@ -0,0 +1,145 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreSecurity; +import com.ruoyi.segchk.service.ISegchkStoreSecurityService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商户密码Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_security") +public class SegchkStoreSecurityController extends BaseController +{ + @Autowired + private ISegchkStoreSecurityService segchkStoreSecurityService; + + /** + * 查询seg商户密码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreSecurity segchkStoreSecurity) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSecurity.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreSecurityService.selectSegchkStoreSecurityList(segchkStoreSecurity); + return getDataTable(list); + } + + /** + * 导出seg商户密码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:export')") + @Log(title = "seg商户密码", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreSecurity segchkStoreSecurity) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSecurity.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreSecurityService.selectSegchkStoreSecurityList(segchkStoreSecurity); + ExcelUtil util = new ExcelUtil(SegchkStoreSecurity.class); + return util.exportExcel(list, "seg商户密码数据"); + } + + /** + * 获取seg商户密码详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:query')") + @GetMapping(value = "/{pwdId}") + public AjaxResult getInfo(@PathVariable("pwdId") Long pwdId) + { + return AjaxResult.success(segchkStoreSecurityService.selectSegchkStoreSecurityByPwdId(pwdId)); + } + + /** + * 新增seg商户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:add')") + @Log(title = "seg商户密码", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreSecurity segchkStoreSecurity) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSecurity.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreSecurityService.insertSegchkStoreSecurity(segchkStoreSecurity)); + } + + /** + * 修改seg商户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:edit')") + @Log(title = "seg商户密码", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreSecurity segchkStoreSecurity) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSecurity.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreSecurityService.updateSegchkStoreSecurity(segchkStoreSecurity)); + } + + /** + * 删除seg商户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_security:remove')") + @Log(title = "seg商户密码", businessType = BusinessType.DELETE) + @DeleteMapping("/{pwdIds}") + public AjaxResult remove(@PathVariable Long[] pwdIds) + { + return toAjax(segchkStoreSecurityService.deleteSegchkStoreSecurityByPwdIds(pwdIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSelfMgtController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSelfMgtController.java new file mode 100644 index 0000000..90b5889 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkStoreSelfMgtController.java @@ -0,0 +1,142 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkStoreSelfMgt; +import com.ruoyi.segchk.service.ISegchkStoreSelfMgtService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg商家自定义卡管理Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_store_self_mgt") +public class SegchkStoreSelfMgtController extends BaseController +{ + @Autowired + private ISegchkStoreSelfMgtService segchkStoreSelfMgtService; + + /** + * 查询seg商家自定义卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkStoreSelfMgt segchkStoreSelfMgt) + { + +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSelfMgt.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkStoreSelfMgtService.selectSegchkStoreSelfMgtList(segchkStoreSelfMgt); + return getDataTable(list); + } + + /** + * 导出seg商家自定义卡管理列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:export')") + @Log(title = "seg商家自定义卡管理", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkStoreSelfMgt segchkStoreSelfMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSelfMgt.setProviderId(sysUser.getProviderId()); + } + List list = segchkStoreSelfMgtService.selectSegchkStoreSelfMgtList(segchkStoreSelfMgt); + ExcelUtil util = new ExcelUtil(SegchkStoreSelfMgt.class); + return util.exportExcel(list, "seg商家自定义卡管理数据"); + } + + /** + * 获取seg商家自定义卡管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:query')") + @GetMapping(value = "/{freeCardId}") + public AjaxResult getInfo(@PathVariable("freeCardId") Long freeCardId) + { + return AjaxResult.success(segchkStoreSelfMgtService.selectSegchkStoreSelfMgtByFreeCardId(freeCardId)); + } + + /** + * 新增seg商家自定义卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:add')") + @Log(title = "seg商家自定义卡管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkStoreSelfMgt segchkStoreSelfMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSelfMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreSelfMgtService.insertSegchkStoreSelfMgt(segchkStoreSelfMgt)); + } + + /** + * 修改seg商家自定义卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:edit')") + @Log(title = "seg商家自定义卡管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkStoreSelfMgt segchkStoreSelfMgt) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkStoreSelfMgt.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkStoreSelfMgtService.updateSegchkStoreSelfMgt(segchkStoreSelfMgt)); + } + + /** + * 删除seg商家自定义卡管理 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_store_self_mgt:remove')") + @Log(title = "seg商家自定义卡管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{freeCardIds}") + public AjaxResult remove(@PathVariable Long[] freeCardIds) + { + return toAjax(segchkStoreSelfMgtService.deleteSegchkStoreSelfMgtByFreeCardIds(freeCardIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSystemSettingController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSystemSettingController.java new file mode 100644 index 0000000..4bc0eb0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkSystemSettingController.java @@ -0,0 +1,131 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.segchk.domain.BaseInfoSet; +import com.ruoyi.segchk.domain.SegchkBaseInfoSet; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkSystemSetting; +import com.ruoyi.segchk.service.ISegchkSystemSettingService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 系统设置Controller + * + * @author yinzhiying + * @date 2021-10-27 + */ +@RestController +@RequestMapping("/segchk/segchk_system_setting") +public class SegchkSystemSettingController extends BaseController +{ + @Autowired + private ISegchkSystemSettingService segchkSystemSettingService; + + /** + * 查询系统设置列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkSystemSetting segchkSystemSetting) + { + startPage(); + List list = segchkSystemSettingService.selectSegchkSystemSettingList(segchkSystemSetting); + return getDataTable(list); + } + + /** + * 导出系统设置列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:export')") + @Log(title = "系统设置", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkSystemSetting segchkSystemSetting) + { + List list = segchkSystemSettingService.selectSegchkSystemSettingList(segchkSystemSetting); + ExcelUtil util = new ExcelUtil(SegchkSystemSetting.class); + return util.exportExcel(list, "系统设置数据"); + } + + /** + * 获取系统设置详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return AjaxResult.success(segchkSystemSettingService.selectSegchkSystemSettingById(id)); + } + + /** + * 新增系统设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:add')") + @Log(title = "系统设置", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkSystemSetting segchkSystemSetting) + { + return toAjax(segchkSystemSettingService.insertSegchkSystemSetting(segchkSystemSetting)); + } + + /** + * 修改系统设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:edit')") + @Log(title = "系统设置", businessType = BusinessType.UPDATE) + @PutMapping("/edit") + public AjaxResult edit(@RequestBody SegchkSystemSetting segchkSystemSetting) + { + return toAjax(segchkSystemSettingService.updateSegchkSystemSetting(segchkSystemSetting)); + } + + /** + * 删除系统设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting:remove')") + @Log(title = "系统设置", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(segchkSystemSettingService.deleteSegchkSystemSettingByIds(ids)); + } + + /** + * 查询 + */ + @UnAuth + @GetMapping("/query") + public AjaxResult query() + { + BaseInfoSet baseInfoSet = segchkSystemSettingService.queryBaseInfoSet(); + return AjaxResult.success(baseInfoSet); + } + + + /** + * 修改系统设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_system_setting')") + @Log(title = "系统设置", businessType = BusinessType.UPDATE) + @PutMapping("/update") + public AjaxResult update(@RequestBody BaseInfoSet baseInfoSet) + { + logger.debug("update with --- {}", baseInfoSet.toString()); + return toAjax(segchkSystemSettingService.editBaseInfoSet(baseInfoSet, 1)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserAccountController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserAccountController.java new file mode 100644 index 0000000..438fd56 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserAccountController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserAccount; +import com.ruoyi.segchk.service.ISegchkUserAccountService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户余额信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_account") +public class SegchkUserAccountController extends BaseController +{ + @Autowired + private ISegchkUserAccountService segchkUserAccountService; + + /** + * 查询seg用户余额信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserAccount segchkUserAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserAccount.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserAccountService.selectSegchkUserAccountList(segchkUserAccount); + return getDataTable(list); + } + + /** + * 导出seg用户余额信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:export')") + @Log(title = "seg用户余额信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserAccount segchkUserAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserAccount.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserAccountService.selectSegchkUserAccountList(segchkUserAccount); + ExcelUtil util = new ExcelUtil(SegchkUserAccount.class); + return util.exportExcel(list, "seg用户余额信息数据"); + } + + /** + * 获取seg用户余额信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:query')") + @GetMapping(value = "/{accountId}") + public AjaxResult getInfo(@PathVariable("accountId") Long accountId) + { + return AjaxResult.success(segchkUserAccountService.selectSegchkUserAccountByAccountId(accountId)); + } + + /** + * 新增seg用户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:add')") + @Log(title = "seg用户余额信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserAccount segchkUserAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserAccount.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserAccountService.insertSegchkUserAccount(segchkUserAccount)); + } + + /** + * 修改seg用户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:edit')") + @Log(title = "seg用户余额信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserAccount segchkUserAccount) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserAccount.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserAccountService.updateSegchkUserAccount(segchkUserAccount)); + } + + /** + * 删除seg用户余额信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_account:remove')") + @Log(title = "seg用户余额信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{accountIds}") + public AjaxResult remove(@PathVariable Long[] accountIds) + { + return toAjax(segchkUserAccountService.deleteSegchkUserAccountByAccountIds(accountIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserBasicInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserBasicInfoController.java new file mode 100644 index 0000000..f7dca79 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserBasicInfoController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserBasicInfo; +import com.ruoyi.segchk.service.ISegchkUserBasicInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户基本信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_basic_info") +public class SegchkUserBasicInfoController extends BaseController +{ + @Autowired + private ISegchkUserBasicInfoService segchkUserBasicInfoService; + + /** + * 查询seg用户基本信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserBasicInfo segchkUserBasicInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserBasicInfo.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserBasicInfoService.selectSegchkUserBasicInfoList(segchkUserBasicInfo); + return getDataTable(list); + } + + /** + * 导出seg用户基本信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:export')") + @Log(title = "seg用户基本信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserBasicInfo segchkUserBasicInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserBasicInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserBasicInfoService.selectSegchkUserBasicInfoList(segchkUserBasicInfo); + ExcelUtil util = new ExcelUtil(SegchkUserBasicInfo.class); + return util.exportExcel(list, "seg用户基本信息数据"); + } + + /** + * 获取seg用户基本信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:query')") + @GetMapping(value = "/{userId}") + public AjaxResult getInfo(@PathVariable("userId") Long userId) + { + return AjaxResult.success(segchkUserBasicInfoService.selectSegchkUserBasicInfoByUserId(userId)); + } + + /** + * 新增seg用户基本信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:add')") + @Log(title = "seg用户基本信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserBasicInfo segchkUserBasicInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserBasicInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserBasicInfoService.insertSegchkUserBasicInfo(segchkUserBasicInfo)); + } + + /** + * 修改seg用户基本信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:edit')") + @Log(title = "seg用户基本信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserBasicInfo segchkUserBasicInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserBasicInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserBasicInfoService.updateSegchkUserBasicInfo(segchkUserBasicInfo)); + } + + /** + * 删除seg用户基本信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_basic_info:remove')") + @Log(title = "seg用户基本信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + return toAjax(segchkUserBasicInfoService.deleteSegchkUserBasicInfoByUserIds(userIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCashController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCashController.java new file mode 100644 index 0000000..3b65ba5 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCashController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserCash; +import com.ruoyi.segchk.service.ISegchkUserCashService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户提现记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_cash") +public class SegchkUserCashController extends BaseController +{ + @Autowired + private ISegchkUserCashService segchkUserCashService; + + /** + * 查询seg用户提现记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserCash segchkUserCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCash.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserCashService.selectSegchkUserCashList(segchkUserCash); + return getDataTable(list); + } + + /** + * 导出seg用户提现记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:export')") + @Log(title = "seg用户提现记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserCash segchkUserCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCash.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserCashService.selectSegchkUserCashList(segchkUserCash); + ExcelUtil util = new ExcelUtil(SegchkUserCash.class); + return util.exportExcel(list, "seg用户提现记录数据"); + } + + /** + * 获取seg用户提现记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:query')") + @GetMapping(value = "/{cashId}") + public AjaxResult getInfo(@PathVariable("cashId") Long cashId) + { + return AjaxResult.success(segchkUserCashService.selectSegchkUserCashByCashId(cashId)); + } + + /** + * 新增seg用户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:add')") + @Log(title = "seg用户提现记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserCash segchkUserCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCash.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCashService.insertSegchkUserCash(segchkUserCash)); + } + + /** + * 修改seg用户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:edit')") + @Log(title = "seg用户提现记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserCash segchkUserCash) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCash.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCashService.updateSegchkUserCash(segchkUserCash)); + } + + /** + * 删除seg用户提现记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_cash:remove')") + @Log(title = "seg用户提现记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{cashIds}") + public AjaxResult remove(@PathVariable Long[] cashIds) + { + return toAjax(segchkUserCashService.deleteSegchkUserCashByCashIds(cashIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCertificationInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCertificationInfoController.java new file mode 100644 index 0000000..38c86fe --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCertificationInfoController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserCertificationInfo; +import com.ruoyi.segchk.service.ISegchkUserCertificationInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户实名认证信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_certification_info") +public class SegchkUserCertificationInfoController extends BaseController +{ + @Autowired + private ISegchkUserCertificationInfoService segchkUserCertificationInfoService; + + /** + * 查询seg用户实名认证信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserCertificationInfo segchkUserCertificationInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCertificationInfo.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserCertificationInfoService.selectSegchkUserCertificationInfoList(segchkUserCertificationInfo); + return getDataTable(list); + } + + /** + * 导出seg用户实名认证信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:export')") + @Log(title = "seg用户实名认证信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserCertificationInfo segchkUserCertificationInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCertificationInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserCertificationInfoService.selectSegchkUserCertificationInfoList(segchkUserCertificationInfo); + ExcelUtil util = new ExcelUtil(SegchkUserCertificationInfo.class); + return util.exportExcel(list, "seg用户实名认证信息数据"); + } + + /** + * 获取seg用户实名认证信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:query')") + @GetMapping(value = "/{usercardId}") + public AjaxResult getInfo(@PathVariable("usercardId") Long usercardId) + { + return AjaxResult.success(segchkUserCertificationInfoService.selectSegchkUserCertificationInfoByUsercardId(usercardId)); + } + + /** + * 新增seg用户实名认证信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:add')") + @Log(title = "seg用户实名认证信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserCertificationInfo segchkUserCertificationInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCertificationInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCertificationInfoService.insertSegchkUserCertificationInfo(segchkUserCertificationInfo)); + } + + /** + * 修改seg用户实名认证信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:edit')") + @Log(title = "seg用户实名认证信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserCertificationInfo segchkUserCertificationInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCertificationInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCertificationInfoService.updateSegchkUserCertificationInfo(segchkUserCertificationInfo)); + } + + /** + * 删除seg用户实名认证信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_certification_info:remove')") + @Log(title = "seg用户实名认证信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{usercardIds}") + public AjaxResult remove(@PathVariable Long[] usercardIds) + { + return toAjax(segchkUserCertificationInfoService.deleteSegchkUserCertificationInfoByUsercardIds(usercardIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserChargeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserChargeController.java new file mode 100644 index 0000000..18a2d49 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserChargeController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserCharge; +import com.ruoyi.segchk.service.ISegchkUserChargeService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户充值记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_charge") +public class SegchkUserChargeController extends BaseController +{ + @Autowired + private ISegchkUserChargeService segchkUserChargeService; + + /** + * 查询seg用户充值记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserCharge segchkUserCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCharge.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserChargeService.selectSegchkUserChargeList(segchkUserCharge); + return getDataTable(list); + } + + /** + * 导出seg用户充值记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:export')") + @Log(title = "seg用户充值记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserCharge segchkUserCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCharge.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserChargeService.selectSegchkUserChargeList(segchkUserCharge); + ExcelUtil util = new ExcelUtil(SegchkUserCharge.class); + return util.exportExcel(list, "seg用户充值记录数据"); + } + + /** + * 获取seg用户充值记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:query')") + @GetMapping(value = "/{chargeId}") + public AjaxResult getInfo(@PathVariable("chargeId") Long chargeId) + { + return AjaxResult.success(segchkUserChargeService.selectSegchkUserChargeByChargeId(chargeId)); + } + + /** + * 新增seg用户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:add')") + @Log(title = "seg用户充值记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserCharge segchkUserCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCharge.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserChargeService.insertSegchkUserCharge(segchkUserCharge)); + } + + /** + * 修改seg用户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:edit')") + @Log(title = "seg用户充值记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserCharge segchkUserCharge) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCharge.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserChargeService.updateSegchkUserCharge(segchkUserCharge)); + } + + /** + * 删除seg用户充值记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_charge:remove')") + @Log(title = "seg用户充值记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{chargeIds}") + public AjaxResult remove(@PathVariable Long[] chargeIds) + { + return toAjax(segchkUserChargeService.deleteSegchkUserChargeByChargeIds(chargeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCollectController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCollectController.java new file mode 100644 index 0000000..363b378 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserCollectController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserCollect; +import com.ruoyi.segchk.service.ISegchkUserCollectService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户收藏记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_collect") +public class SegchkUserCollectController extends BaseController +{ + @Autowired + private ISegchkUserCollectService segchkUserCollectService; + + /** + * 查询seg用户收藏记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserCollect segchkUserCollect) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCollect.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserCollectService.selectSegchkUserCollectList(segchkUserCollect); + return getDataTable(list); + } + + /** + * 导出seg用户收藏记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:export')") + @Log(title = "seg用户收藏记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserCollect segchkUserCollect) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCollect.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserCollectService.selectSegchkUserCollectList(segchkUserCollect); + ExcelUtil util = new ExcelUtil(SegchkUserCollect.class); + return util.exportExcel(list, "seg用户收藏记录数据"); + } + + /** + * 获取seg用户收藏记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:query')") + @GetMapping(value = "/{collectId}") + public AjaxResult getInfo(@PathVariable("collectId") Long collectId) + { + return AjaxResult.success(segchkUserCollectService.selectSegchkUserCollectByCollectId(collectId)); + } + + /** + * 新增seg用户收藏记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:add')") + @Log(title = "seg用户收藏记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserCollect segchkUserCollect) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCollect.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCollectService.insertSegchkUserCollect(segchkUserCollect)); + } + + /** + * 修改seg用户收藏记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:edit')") + @Log(title = "seg用户收藏记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserCollect segchkUserCollect) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserCollect.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserCollectService.updateSegchkUserCollect(segchkUserCollect)); + } + + /** + * 删除seg用户收藏记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_collect:remove')") + @Log(title = "seg用户收藏记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{collectIds}") + public AjaxResult remove(@PathVariable Long[] collectIds) + { + return toAjax(segchkUserCollectService.deleteSegchkUserCollectByCollectIds(collectIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserExtInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserExtInfoController.java new file mode 100644 index 0000000..fc4f8db --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserExtInfoController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserExtInfo; +import com.ruoyi.segchk.service.ISegchkUserExtInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户扩展信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_ext_info") +public class SegchkUserExtInfoController extends BaseController +{ + @Autowired + private ISegchkUserExtInfoService segchkUserExtInfoService; + + /** + * 查询seg用户扩展信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserExtInfo segchkUserExtInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserExtInfo.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserExtInfoService.selectSegchkUserExtInfoList(segchkUserExtInfo); + return getDataTable(list); + } + + /** + * 导出seg用户扩展信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:export')") + @Log(title = "seg用户扩展信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserExtInfo segchkUserExtInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserExtInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserExtInfoService.selectSegchkUserExtInfoList(segchkUserExtInfo); + ExcelUtil util = new ExcelUtil(SegchkUserExtInfo.class); + return util.exportExcel(list, "seg用户扩展信息数据"); + } + + /** + * 获取seg用户扩展信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:query')") + @GetMapping(value = "/{userId}") + public AjaxResult getInfo(@PathVariable("userId") Long userId) + { + return AjaxResult.success(segchkUserExtInfoService.selectSegchkUserExtInfoByUserId(userId)); + } + + /** + * 新增seg用户扩展信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:add')") + @Log(title = "seg用户扩展信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserExtInfo segchkUserExtInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserExtInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserExtInfoService.insertSegchkUserExtInfo(segchkUserExtInfo)); + } + + /** + * 修改seg用户扩展信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:edit')") + @Log(title = "seg用户扩展信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserExtInfo segchkUserExtInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserExtInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserExtInfoService.updateSegchkUserExtInfo(segchkUserExtInfo)); + } + + /** + * 删除seg用户扩展信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_ext_info:remove')") + @Log(title = "seg用户扩展信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + return toAjax(segchkUserExtInfoService.deleteSegchkUserExtInfoByUserIds(userIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserLikegoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserLikegoController.java new file mode 100644 index 0000000..8d6d703 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserLikegoController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserLikego; +import com.ruoyi.segchk.service.ISegchkUserLikegoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户想去记录Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_likego") +public class SegchkUserLikegoController extends BaseController +{ + @Autowired + private ISegchkUserLikegoService segchkUserLikegoService; + + /** + * 查询seg用户想去记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserLikego segchkUserLikego) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserLikego.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserLikegoService.selectSegchkUserLikegoList(segchkUserLikego); + return getDataTable(list); + } + + /** + * 导出seg用户想去记录列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:export')") + @Log(title = "seg用户想去记录", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserLikego segchkUserLikego) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserLikego.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserLikegoService.selectSegchkUserLikegoList(segchkUserLikego); + ExcelUtil util = new ExcelUtil(SegchkUserLikego.class); + return util.exportExcel(list, "seg用户想去记录数据"); + } + + /** + * 获取seg用户想去记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:query')") + @GetMapping(value = "/{likegoId}") + public AjaxResult getInfo(@PathVariable("likegoId") Long likegoId) + { + return AjaxResult.success(segchkUserLikegoService.selectSegchkUserLikegoByLikegoId(likegoId)); + } + + /** + * 新增seg用户想去记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:add')") + @Log(title = "seg用户想去记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserLikego segchkUserLikego) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserLikego.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserLikegoService.insertSegchkUserLikego(segchkUserLikego)); + } + + /** + * 修改seg用户想去记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:edit')") + @Log(title = "seg用户想去记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserLikego segchkUserLikego) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserLikego.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserLikegoService.updateSegchkUserLikego(segchkUserLikego)); + } + + /** + * 删除seg用户想去记录 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_likego:remove')") + @Log(title = "seg用户想去记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{likegoIds}") + public AjaxResult remove(@PathVariable Long[] likegoIds) + { + return toAjax(segchkUserLikegoService.deleteSegchkUserLikegoByLikegoIds(likegoIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardController.java new file mode 100644 index 0000000..19dc1bd --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserReward; +import com.ruoyi.segchk.service.ISegchkUserRewardService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户奖励Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_reward") +public class SegchkUserRewardController extends BaseController +{ + @Autowired + private ISegchkUserRewardService segchkUserRewardService; + + /** + * 查询seg用户奖励列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserReward segchkUserReward) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserReward.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserRewardService.selectSegchkUserRewardList(segchkUserReward); + return getDataTable(list); + } + + /** + * 导出seg用户奖励列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:export')") + @Log(title = "seg用户奖励", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserReward segchkUserReward) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserReward.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserRewardService.selectSegchkUserRewardList(segchkUserReward); + ExcelUtil util = new ExcelUtil(SegchkUserReward.class); + return util.exportExcel(list, "seg用户奖励数据"); + } + + /** + * 获取seg用户奖励详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:query')") + @GetMapping(value = "/{rewardId}") + public AjaxResult getInfo(@PathVariable("rewardId") Long rewardId) + { + return AjaxResult.success(segchkUserRewardService.selectSegchkUserRewardByRewardId(rewardId)); + } + + /** + * 新增seg用户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:add')") + @Log(title = "seg用户奖励", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserReward segchkUserReward) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserReward.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserRewardService.insertSegchkUserReward(segchkUserReward)); + } + + /** + * 修改seg用户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:edit')") + @Log(title = "seg用户奖励", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserReward segchkUserReward) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserReward.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserRewardService.updateSegchkUserReward(segchkUserReward)); + } + + /** + * 删除seg用户奖励 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward:remove')") + @Log(title = "seg用户奖励", businessType = BusinessType.DELETE) + @DeleteMapping("/{rewardIds}") + public AjaxResult remove(@PathVariable Long[] rewardIds) + { + return toAjax(segchkUserRewardService.deleteSegchkUserRewardByRewardIds(rewardIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardCtlController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardCtlController.java new file mode 100644 index 0000000..8e46aa8 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserRewardCtlController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserRewardCtl; +import com.ruoyi.segchk.service.ISegchkUserRewardCtlService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg会员推荐控制Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_reward_ctl") +public class SegchkUserRewardCtlController extends BaseController +{ + @Autowired + private ISegchkUserRewardCtlService segchkUserRewardCtlService; + + /** + * 查询seg会员推荐控制列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserRewardCtl segchkUserRewardCtl) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserRewardCtl.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserRewardCtlService.selectSegchkUserRewardCtlList(segchkUserRewardCtl); + return getDataTable(list); + } + + /** + * 导出seg会员推荐控制列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:export')") + @Log(title = "seg会员推荐控制", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserRewardCtl segchkUserRewardCtl) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserRewardCtl.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserRewardCtlService.selectSegchkUserRewardCtlList(segchkUserRewardCtl); + ExcelUtil util = new ExcelUtil(SegchkUserRewardCtl.class); + return util.exportExcel(list, "seg会员推荐控制数据"); + } + + /** + * 获取seg会员推荐控制详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:query')") + @GetMapping(value = "/{rewardCtlId}") + public AjaxResult getInfo(@PathVariable("rewardCtlId") Integer rewardCtlId) + { + return AjaxResult.success(segchkUserRewardCtlService.selectSegchkUserRewardCtlByRewardCtlId(rewardCtlId)); + } + + /** + * 新增seg会员推荐控制 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:add')") + @Log(title = "seg会员推荐控制", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserRewardCtl segchkUserRewardCtl) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserRewardCtl.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserRewardCtlService.insertSegchkUserRewardCtl(segchkUserRewardCtl)); + } + + /** + * 修改seg会员推荐控制 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:edit')") + @Log(title = "seg会员推荐控制", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserRewardCtl segchkUserRewardCtl) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserRewardCtl.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserRewardCtlService.updateSegchkUserRewardCtl(segchkUserRewardCtl)); + } + + /** + * 删除seg会员推荐控制 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_reward_ctl:remove')") + @Log(title = "seg会员推荐控制", businessType = BusinessType.DELETE) + @DeleteMapping("/{rewardCtlIds}") + public AjaxResult remove(@PathVariable Integer[] rewardCtlIds) + { + return toAjax(segchkUserRewardCtlService.deleteSegchkUserRewardCtlByRewardCtlIds(rewardCtlIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserSecurityController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserSecurityController.java new file mode 100644 index 0000000..e4a40ae --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserSecurityController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserSecurity; +import com.ruoyi.segchk.service.ISegchkUserSecurityService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户密码Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_security") +public class SegchkUserSecurityController extends BaseController +{ + @Autowired + private ISegchkUserSecurityService segchkUserSecurityService; + + /** + * 查询seg用户密码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserSecurity segchkUserSecurity) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserSecurity.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserSecurityService.selectSegchkUserSecurityList(segchkUserSecurity); + return getDataTable(list); + } + + /** + * 导出seg用户密码列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:export')") + @Log(title = "seg用户密码", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserSecurity segchkUserSecurity) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserSecurity.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserSecurityService.selectSegchkUserSecurityList(segchkUserSecurity); + ExcelUtil util = new ExcelUtil(SegchkUserSecurity.class); + return util.exportExcel(list, "seg用户密码数据"); + } + + /** + * 获取seg用户密码详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:query')") + @GetMapping(value = "/{pwdId}") + public AjaxResult getInfo(@PathVariable("pwdId") Long pwdId) + { + return AjaxResult.success(segchkUserSecurityService.selectSegchkUserSecurityByPwdId(pwdId)); + } + + /** + * 新增seg用户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:add')") + @Log(title = "seg用户密码", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserSecurity segchkUserSecurity) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserSecurity.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserSecurityService.insertSegchkUserSecurity(segchkUserSecurity)); + } + + /** + * 修改seg用户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:edit')") + @Log(title = "seg用户密码", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserSecurity segchkUserSecurity) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserSecurity.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserSecurityService.updateSegchkUserSecurity(segchkUserSecurity)); + } + + /** + * 删除seg用户密码 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_security:remove')") + @Log(title = "seg用户密码", businessType = BusinessType.DELETE) + @DeleteMapping("/{pwdIds}") + public AjaxResult remove(@PathVariable Long[] pwdIds) + { + return toAjax(segchkUserSecurityService.deleteSegchkUserSecurityByPwdIds(pwdIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserVipController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserVipController.java new file mode 100644 index 0000000..e084f31 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserVipController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserVip; +import com.ruoyi.segchk.service.ISegchkUserVipService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg会员卡Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_vip") +public class SegchkUserVipController extends BaseController +{ + @Autowired + private ISegchkUserVipService segchkUserVipService; + + /** + * 查询seg会员卡列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserVip segchkUserVip) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserVip.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserVipService.selectSegchkUserVipList(segchkUserVip); + return getDataTable(list); + } + + /** + * 导出seg会员卡列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:export')") + @Log(title = "seg会员卡", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserVip segchkUserVip) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserVip.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserVipService.selectSegchkUserVipList(segchkUserVip); + ExcelUtil util = new ExcelUtil(SegchkUserVip.class); + return util.exportExcel(list, "seg会员卡数据"); + } + + /** + * 获取seg会员卡详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:query')") + @GetMapping(value = "/{cardId}") + public AjaxResult getInfo(@PathVariable("cardId") Long cardId) + { + return AjaxResult.success(segchkUserVipService.selectSegchkUserVipByCardId(cardId)); + } + + /** + * 新增seg会员卡 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:add')") + @Log(title = "seg会员卡", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserVip segchkUserVip) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserVip.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserVipService.insertSegchkUserVip(segchkUserVip)); + } + + /** + * 修改seg会员卡 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:edit')") + @Log(title = "seg会员卡", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserVip segchkUserVip) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserVip.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserVipService.updateSegchkUserVip(segchkUserVip)); + } + + /** + * 删除seg会员卡 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_vip:remove')") + @Log(title = "seg会员卡", businessType = BusinessType.DELETE) + @DeleteMapping("/{cardIds}") + public AjaxResult remove(@PathVariable Long[] cardIds) + { + return toAjax(segchkUserVipService.deleteSegchkUserVipByCardIds(cardIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserWechatController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserWechatController.java new file mode 100644 index 0000000..7bdd15e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkUserWechatController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.segchk.service.ISegchkUserWechatService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg用户微信信息Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_user_wechat") +public class SegchkUserWechatController extends BaseController +{ + @Autowired + private ISegchkUserWechatService segchkUserWechatService; + + /** + * 查询seg用户微信信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkUserWechat segchkUserWechat) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserWechat.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkUserWechatService.selectSegchkUserWechatList(segchkUserWechat); + return getDataTable(list); + } + + /** + * 导出seg用户微信信息列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:export')") + @Log(title = "seg用户微信信息", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkUserWechat segchkUserWechat) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserWechat.setProviderId(sysUser.getProviderId()); + } + List list = segchkUserWechatService.selectSegchkUserWechatList(segchkUserWechat); + ExcelUtil util = new ExcelUtil(SegchkUserWechat.class); + return util.exportExcel(list, "seg用户微信信息数据"); + } + + /** + * 获取seg用户微信信息详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:query')") + @GetMapping(value = "/{userId}") + public AjaxResult getInfo(@PathVariable("userId") Long userId) + { + return AjaxResult.success(segchkUserWechatService.selectSegchkUserWechatByUserId(userId)); + } + + /** + * 新增seg用户微信信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:add')") + @Log(title = "seg用户微信信息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkUserWechat segchkUserWechat) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserWechat.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserWechatService.insertSegchkUserWechat(segchkUserWechat)); + } + + /** + * 修改seg用户微信信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:edit')") + @Log(title = "seg用户微信信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkUserWechat segchkUserWechat) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkUserWechat.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkUserWechatService.updateSegchkUserWechat(segchkUserWechat)); + } + + /** + * 删除seg用户微信信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_user_wechat:remove')") + @Log(title = "seg用户微信信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + return toAjax(segchkUserWechatService.deleteSegchkUserWechatByUserIds(userIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkVipSetInfoController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkVipSetInfoController.java new file mode 100644 index 0000000..5445bce --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/segchk/SegchkVipSetInfoController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.segchk; + +import java.util.List; + +import com.ruoyi.common.core.domain.entity.SysUser; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.segchk.domain.SegchkVipSetInfo; +import com.ruoyi.segchk.service.ISegchkVipSetInfoService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * seg会员卡设置Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/segchk/segchk_vip_set_info") +public class SegchkVipSetInfoController extends BaseController +{ + @Autowired + private ISegchkVipSetInfoService segchkVipSetInfoService; + + /** + * 查询seg会员卡设置列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:list')") + @GetMapping("/list") + public TableDataInfo list(SegchkVipSetInfo segchkVipSetInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkVipSetInfo.setProviderId(sysUser.getProviderId()); + } + startPage(); + List list = segchkVipSetInfoService.selectSegchkVipSetInfoList(segchkVipSetInfo); + return getDataTable(list); + } + + /** + * 导出seg会员卡设置列表 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:export')") + @Log(title = "seg会员卡设置", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SegchkVipSetInfo segchkVipSetInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkVipSetInfo.setProviderId(sysUser.getProviderId()); + } + List list = segchkVipSetInfoService.selectSegchkVipSetInfoList(segchkVipSetInfo); + ExcelUtil util = new ExcelUtil(SegchkVipSetInfo.class); + return util.exportExcel(list, "seg会员卡设置数据"); + } + + /** + * 获取seg会员卡设置详细信息 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:query')") + @GetMapping(value = "/{modeId}") + public AjaxResult getInfo(@PathVariable("modeId") Integer modeId) + { + return AjaxResult.success(segchkVipSetInfoService.selectSegchkVipSetInfoByModeId(modeId)); + } + + /** + * 新增seg会员卡设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:add')") + @Log(title = "seg会员卡设置", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SegchkVipSetInfo segchkVipSetInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkVipSetInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkVipSetInfoService.insertSegchkVipSetInfo(segchkVipSetInfo)); + } + + /** + * 修改seg会员卡设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:edit')") + @Log(title = "seg会员卡设置", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SegchkVipSetInfo segchkVipSetInfo) + { +// 获取当前登录用户信息 + SysUser sysUser = getLoginUser().getUser(); + if(sysUser.getUserId() == 1){ +// 说明是超级管理员 + ; + } + else{ + segchkVipSetInfo.setProviderId(sysUser.getProviderId()); + } + return toAjax(segchkVipSetInfoService.updateSegchkVipSetInfo(segchkVipSetInfo)); + } + + /** + * 删除seg会员卡设置 + */ + @PreAuthorize("@ss.hasPermi('segchk:segchk_vip_set_info:remove')") + @Log(title = "seg会员卡设置", businessType = BusinessType.DELETE) + @DeleteMapping("/{modeIds}") + public AjaxResult remove(@PathVariable Integer[] modeIds) + { + return toAjax(segchkVipSetInfoService.deleteSegchkVipSetInfoByModeIds(modeIds)); + } +} 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..f44c392 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -0,0 +1,135 @@ +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.annotation.RepeatSubmit; +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.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')") + @GetMapping("/export") + public AjaxResult export(SysConfig config) + { + List list = configService.selectConfigList(config); + ExcelUtil util = new ExcelUtil(SysConfig.class); + return util.exportExcel(list, "参数数据"); + } + + /** + * 根据参数编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:config:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long configId) + { + return AjaxResult.success(configService.selectConfigById(configId)); + } + + /** + * 根据参数键名查询参数值 + */ + @GetMapping(value = "/configKey/{configKey}") + public AjaxResult getConfigKey(@PathVariable String configKey) + { + return AjaxResult.success(configService.selectConfigByKey(configKey)); + } + + /** + * 新增参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:add')") + @Log(title = "参数管理", businessType = BusinessType.INSERT) + @PostMapping + @RepeatSubmit + public AjaxResult add(@Validated @RequestBody SysConfig config) + { + if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return AjaxResult.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 (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return AjaxResult.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 AjaxResult.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..51fc807 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -0,0 +1,162 @@ +package com.ruoyi.web.controller.system; + +import java.util.Iterator; +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 AjaxResult.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()); + Iterator it = depts.iterator(); + while (it.hasNext()) + { + SysDept d = (SysDept) it.next(); + if (d.getDeptId().intValue() == deptId + || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")) + { + it.remove(); + } + } + return AjaxResult.success(depts); + } + + /** + * 根据部门编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:dept:query')") + @GetMapping(value = "/{deptId}") + public AjaxResult getInfo(@PathVariable Long deptId) + { + return AjaxResult.success(deptService.selectDeptById(deptId)); + } + + /** + * 获取部门下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return AjaxResult.success(deptService.buildDeptTreeSelect(depts)); + } + + /** + * 加载对应角色部门列表树 + */ + @GetMapping(value = "/roleDeptTreeselect/{roleId}") + public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId) + { + List depts = deptService.selectDeptList(new SysDept()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.buildDeptTreeSelect(depts)); + return ajax; + } + + /** + * 新增部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:add')") + @Log(title = "部门管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDept dept) + { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return AjaxResult.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) + { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + else if (dept.getParentId().equals(dept.getDeptId())) + { + return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } + else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) + && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) + { + return AjaxResult.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 AjaxResult.error("存在下级部门,不允许删除"); + } + if (deptService.checkDeptExistUser(deptId)) + { + return AjaxResult.error("部门存在用户,不允许删除"); + } + 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..7609689 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java @@ -0,0 +1,120 @@ +package com.ruoyi.web.controller.system; + +import java.util.ArrayList; +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.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')") + @GetMapping("/export") + public AjaxResult export(SysDictData dictData) + { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil util = new ExcelUtil(SysDictData.class); + return util.exportExcel(list, "字典数据"); + } + + /** + * 查询字典数据详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictCode}") + public AjaxResult getInfo(@PathVariable Long dictCode) + { + return AjaxResult.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 AjaxResult.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..c2e4d74 --- /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 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.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')") + @GetMapping("/export") + public AjaxResult export(SysDictType dictType) + { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil util = new ExcelUtil(SysDictType.class); + return util.exportExcel(list, "字典类型"); + } + + /** + * 查询字典类型详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictId}") + public AjaxResult getInfo(@PathVariable Long dictId) + { + return AjaxResult.success(dictTypeService.selectDictTypeById(dictId)); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictType dict) + { + if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return AjaxResult.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 (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return AjaxResult.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 AjaxResult.success(); + } + + /** + * 获取字典选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List dictTypes = dictTypeService.selectDictTypeAll(); + return AjaxResult.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..20803a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -0,0 +1,102 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.ruoyi.security.web.service.SysLoginService; +import com.ruoyi.security.web.service.SysPermissionService; +import com.ruoyi.segchk.service.ISegchkProviderMgtService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.ObjectUtils; +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.system.service.ISysMenuService; + +/** + * 登录验证 + * + * @author ruoyi + */ +@RestController +public class SysLoginController +{ + @Autowired + private SysLoginService loginService; + + @Autowired + private ISysMenuService menuService; + + @Autowired + private SysPermissionService permissionService; + + + + @Autowired + private ISegchkProviderMgtService segchkProviderMgtService; + /** + * 登录方法 + * + * @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); + System.out.println("login token is : " + token); + return ajax; + } + + /** + * 获取用户信息 + * + * @return 用户信息 + */ + @GetMapping("getInfo") + public AjaxResult getInfo() + { + SysUser user = SecurityUtils.getLoginUser().getUser(); + Long providerId = segchkProviderMgtService.getProviderIdByPhoneNo(user.getPhonenumber()); + // 角色集合 + Set roles = permissionService.getRolePermission(user); + user.setProviderId(providerId); + // 权限集合 + Set permissions = permissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + System.out.println("getInfo with " + user.toString()); + System.out.println("getInfo with " + String.join(",", roles)); + System.out.println("getInfo with " + String.join(",", permissions)); + return ajax; + } + + /** + * 获取路由信息 + * + * @return 路由信息 + */ + @GetMapping("getRouters") + public AjaxResult getRouters() + { + Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); + List menus = menuService.selectMenuTreeByUserId(userId); + List collect = menus.parallelStream().map(v -> v.toString()).collect(Collectors.toList()); + System.out.println(String.format("getRouters with {}---{}", userId, String.join(",", collect))); + 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..4a9f73f --- /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 AjaxResult.success(menus); + } + + /** + * 根据菜单编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:menu:query')") + @GetMapping(value = "/{menuId}") + public AjaxResult getInfo(@PathVariable Long menuId) + { + return AjaxResult.success(menuService.selectMenuById(menuId)); + } + + /** + * 获取菜单下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysMenu menu) + { + List menus = menuService.selectMenuList(menu, getUserId()); + return AjaxResult.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 (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return AjaxResult.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 (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + else if (menu.getMenuId().equals(menu.getParentId())) + { + return AjaxResult.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 AjaxResult.error("存在子菜单,不允许删除"); + } + if (menuService.checkMenuExistRole(menuId)) + { + return AjaxResult.error("菜单已分配,不允许删除"); + } + 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..4da9f04 --- /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 AjaxResult.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..c2501c7 --- /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 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.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')") + @GetMapping("/export") + public AjaxResult export(SysPost post) + { + List list = postService.selectPostList(post); + ExcelUtil util = new ExcelUtil(SysPost.class); + return util.exportExcel(list, "岗位数据"); + } + + /** + * 根据岗位编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:post:query')") + @GetMapping(value = "/{postId}") + public AjaxResult getInfo(@PathVariable Long postId) + { + return AjaxResult.success(postService.selectPostById(postId)); + } + + /** + * 新增岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:add')") + @Log(title = "岗位管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysPost post) + { + if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return AjaxResult.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 (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return AjaxResult.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 AjaxResult.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..90eb8f3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -0,0 +1,141 @@ +package com.ruoyi.web.controller.system; + +import java.io.IOException; +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.constant.UserConstants; +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.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) + { + if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + LoginUser loginUser = getLoginUser(); + SysUser sysUser = loginUser.getUser(); + user.setUserId(sysUser.getUserId()); + user.setPassword(null); + if (userService.updateUserProfile(user) > 0) + { + // 更新缓存用户信息 + sysUser.setNickName(user.getNickName()); + sysUser.setPhonenumber(user.getPhonenumber()); + sysUser.setEmail(user.getEmail()); + sysUser.setSex(user.getSex()); + tokenService.setLoginUser(loginUser); + return AjaxResult.success(); + } + return AjaxResult.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 AjaxResult.error("修改密码失败,旧密码错误"); + } + if (SecurityUtils.matchesPassword(newPassword, password)) + { + return AjaxResult.error("新密码不能与旧密码相同"); + } + if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) + { + // 更新缓存用户密码 + loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); + tokenService.setLoginUser(loginUser); + return AjaxResult.success(); + } + return AjaxResult.error("修改密码异常,请联系管理员"); + } + + /** + * 头像上传 + */ + @Log(title = "用户头像", businessType = BusinessType.UPDATE) + @PostMapping("/avatar") + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException + { + if (!file.isEmpty()) + { + LoginUser loginUser = getLoginUser(); + String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file); + if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("imgUrl", avatar); + // 更新缓存用户头像 + loginUser.getUser().setAvatar(avatar); + tokenService.setLoginUser(loginUser); + return ajax; + } + } + return AjaxResult.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..762f1d9 --- /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.util.StringUtils; +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.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..1f9359f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -0,0 +1,240 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; + +import com.ruoyi.security.web.service.SysPermissionService; +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.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.TokenService; +import com.ruoyi.system.domain.SysUserRole; +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; + + @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')") + @GetMapping("/export") + public AjaxResult export(SysRole role) + { + List list = roleService.selectRoleList(role); + ExcelUtil util = new ExcelUtil(SysRole.class); + return util.exportExcel(list, "角色数据"); + } + + /** + * 根据角色编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/{roleId}") + public AjaxResult getInfo(@PathVariable Long roleId) + { + return AjaxResult.success(roleService.selectRoleById(roleId)); + } + + /** + * 新增角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:add')") + @Log(title = "角色管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysRole role) + { + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return AjaxResult.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); + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return AjaxResult.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 AjaxResult.success(); + } + return AjaxResult.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); + 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); + 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 AjaxResult.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) + { + return toAjax(roleService.insertAuthUsers(roleId, userIds)); + } +} 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..1eadb54 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -0,0 +1,249 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +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.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.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 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')") + @GetMapping("/export") + public AjaxResult export(SysUser user) + { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + return util.exportExcel(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 AjaxResult.success(message); + } + + @GetMapping("/importTemplate") + public AjaxResult importTemplate() + { + ExcelUtil util = new ExcelUtil(SysUser.class); + return util.importTemplateExcel("用户数据"); + } + + /** + * 根据用户编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping(value = { "/", "/{userId}" }) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long 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)) + { + ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId)); + ajax.put("postIds", postService.selectPostListByUserId(userId)); + ajax.put("roleIds", roleService.selectRoleListByUserId(userId)); + } + return ajax; + } + + /** + * 新增用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:add')") + @Log(title = "用户管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysUser user) + { + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setCreateBy(getUsername()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + return toAjax(userService.insertUser(user)); + } + + /** + * 修改用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysUser user) + { + userService.checkUserAllowed(user); + if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUpdateBy(getUsername()); + return toAjax(userService.updateUser(user)); + } + + /** + * 删除用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:remove')") + @Log(title = "用户管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + if (ArrayUtils.contains(userIds, getUserId())) + { + return error("当前用户不能删除"); + } + return toAjax(userService.deleteUserByIds(userIds)); + } + + /** + * 重置密码 + */ + @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public AjaxResult resetPwd(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(getUsername()); + return toAjax(userService.resetPwd(user)); + } + + + /** + * 重置密码admin忘记密码时 + */ +// @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") +// @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetadminself") + public AjaxResult resetadminself() + { +// userService.checkUserAllowed(user); + SysUser user = new SysUser(); + user.setPassword("yzy123456"); + user.setUserId(1L); + user.setUserName("admin"); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(user.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); + 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.insertUserAuth(userId, roleIds); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java new file mode 100644 index 0000000..f66ca24 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java @@ -0,0 +1,24 @@ +package com.ruoyi.web.controller.tool; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import com.ruoyi.common.core.controller.BaseController; + +/** + * swagger 接口 + * + * @author ruoyi + */ +@Controller +@RequestMapping("/tool/swagger") +public class SwaggerController extends BaseController +{ + @PreAuthorize("@ss.hasPermi('tool:swagger:view')") + @GetMapping() + public String index() + { + return redirect("/swagger-ui.html"); + } +} 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..381ab13 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java @@ -0,0 +1,181 @@ +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.AjaxResult; +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 AjaxResult userList() + { + List userList = new ArrayList(users.values()); + return AjaxResult.success(userList); + } + + @ApiOperation("获取用户详细") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") + @GetMapping("/{userId}") + public AjaxResult getUser(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + return AjaxResult.success(users.get(userId)); + } + else + { + return error("用户不存在"); + } + } + + @ApiOperation("新增用户") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"), + @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"), + @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"), + @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String") + }) + @PostMapping("/save") + public AjaxResult save(UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return error("用户ID不能为空"); + } + return AjaxResult.success(users.put(user.getUserId(), user)); + } + + @ApiOperation("更新用户") + @PutMapping("/update") + public AjaxResult update(@RequestBody UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return error("用户ID不能为空"); + } + if (users.isEmpty() || !users.containsKey(user.getUserId())) + { + return error("用户不存在"); + } + users.remove(user.getUserId()); + return AjaxResult.success(users.put(user.getUserId(), user)); + } + + @ApiOperation("删除用户信息") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") + @DeleteMapping("/{userId}") + public AjaxResult delete(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + users.remove(userId); + return success(); + } + else + { + return error("用户不存在"); + } + } +} + +@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/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/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml new file mode 100644 index 0000000..fbedc1f --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -0,0 +1,119 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.6.0 + # 版权年份 + copyrightYear: 2021 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath F:\ideaproj\RuoYi-Vue\uploadPath) + profile: F:\ideaproj\RuoYi-Vue\uploadPath + # 获取ip地址开关 + addressEnabled: false + # 验证码类型 math 数组计算 char 字符验证 + captchaType: math + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 7070 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + + +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://10.1.192.113:13306/yzy_ruoyi_vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true + username: yzyuser + password: yzy123456 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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 + # redis 配置 + redis: + # 地址 + host: 10.1.192.113 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 0 + # 密码 + password: retinabd@2020 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms +debug: true \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application-kaleprod.yml b/ruoyi-admin/src/main/resources/application-kaleprod.yml new file mode 100644 index 0000000..ec50130 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-kaleprod.yml @@ -0,0 +1,118 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.6.0 + # 版权年份 + copyrightYear: 2021 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: /home/seg_yinzy/data/applet + # 获取ip地址开关 + addressEnabled: false + # 验证码类型 math 数组计算 char 字符验证 + captchaType: math + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 7070 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + + +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.30:8306/segchksaas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true + username: segchksaas + password: 2wsx@WSX + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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 + # redis 配置 + redis: + # 地址 + host: 192.168.2.40 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 3 + # 密码 + password: seg_123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml new file mode 100644 index 0000000..080cdc5 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-test.yml @@ -0,0 +1,118 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.6.0 + # 版权年份 + copyrightYear: 2021 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: /home/seg_yinzy/data/applet + # 获取ip地址开关 + addressEnabled: false + # 验证码类型 math 数组计算 char 字符验证 + captchaType: math + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 7070 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + + +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.30:8306/kaletest?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true + username: segchksaas + password: 2wsx@WSX + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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 + # redis 配置 + redis: + # 地址 + host: 192.168.2.40 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 2 + # 密码 + password: seg_123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml new file mode 100644 index 0000000..536a0f8 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application.yml @@ -0,0 +1,98 @@ +# 项目相关配置 +#ruoyi: +# # 名称 +# name: RuoYi +# # 版本 +# version: 3.6.0 +# # 版权年份 +# copyrightYear: 2021 +# # 实例演示开关 +# demoEnabled: true +# # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) +# profile: D:/ruoyi/uploadPath +# # 获取ip地址开关 +# addressEnabled: false +# # 验证码类型 math 数组计算 char 字符验证 +# captchaType: math + +## 开发环境配置 +#server: +# # 服务器的HTTP端口,默认为8080 +# port: 7070 +# servlet: +# # 应用的访问路径 +# context-path: / +# tomcat: +# # tomcat的URI编码 +# uri-encoding: UTF-8 +# # tomcat最大线程数,默认为200 +# max-threads: 800 +# # Tomcat启动初始化的线程数,默认值25 +# min-spare-threads: 30 +# +## 日志配置 +#logging: +# level: +# com.ruoyi: debug +# org.springframework: warn + +# Spring配置 +spring: + # 资源信息 + messages: + # 国际化资源文件路径 + basename: i18n/messages + profiles: + active: druid + # 文件上传 + servlet: + multipart: + # 单个文件大小 + max-file-size: 10MB + # 设置总上传的文件大小 + max-request-size: 20MB + # 服务模块 + devtools: + restart: + # 热部署开关 + enabled: true + +# 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/* 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..71cf52d --- /dev/null +++ b/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -0,0 +1,37 @@ +#错误消息 +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}次,帐户锁定10分钟 +user.password.delete=对不起,您的账号已被删除 +user.blocked=用户已封禁,请联系管理员 +role.blocked=角色已封禁,请联系管理员 +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..01528cf --- /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..e8b52be --- /dev/null +++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml new file mode 100644 index 0000000..834840e --- /dev/null +++ b/ruoyi-common/pom.xml @@ -0,0 +1,126 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + + 4.0.0 + + ruoyi-common + + + common通用工具 + + + + + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + + javax.validation + validation-api + + + + + org.apache.commons + commons-lang3 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.alibaba + fastjson + + + + + commons-io + commons-io + + + + + commons-fileupload + commons-fileupload + + + + + org.apache.poi + poi-ooxml + + + + + org.yaml + snakeyaml + + + + + io.jsonwebtoken + jjwt + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + + eu.bitwalker + UserAgentUtils + + + + + javax.servlet + javax.servlet-api + + + + + \ No newline at end of file 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..176878e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -0,0 +1,28 @@ +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 ""; +} 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..b09f4ce --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -0,0 +1,165 @@ +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; + +/** + * 自定义导出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; + + /** + * 导出类型(0数字 1字符串) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出时在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 {}; + + /** + * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. + */ + public boolean isExport() default true; + + /** + * 另一个类中的属性名称,支持多级获取,以小数点隔开 + */ + public String targetAttr() default ""; + + /** + * 是否自动统计数据,在最后追加一行统计数据总和 + */ + public boolean isStatistics() default false; + + /** + * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右) + */ + Align align() default Align.AUTO; + + public enum Align + { + AUTO(0), LEFT(1), CENTER(2), RIGHT(3); + private final int value; + + Align(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + /** + * 字段类型(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..eb05dc7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java @@ -0,0 +1,41 @@ +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; +} 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..69461ea --- /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.Constants; +import com.ruoyi.common.enums.LimitType; + +/** + * 限流注解 + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RateLimiter +{ + /** + * 限流key + */ + public String key() default Constants.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..9e350f1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java @@ -0,0 +1,23 @@ +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 +{ + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/UnAuth.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/UnAuth.java new file mode 100644 index 0000000..e8f1c95 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/UnAuth.java @@ -0,0 +1,14 @@ +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; + +/** + * 不需要拦截注解 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface UnAuth { +} 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..faf25be --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -0,0 +1,124 @@ +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; + + 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 getImportPath() + { + return getProfile() + "/import"; + } + + /** + * 获取头像上传路径 + */ + public static String getAvatarPath() + { + return getProfile() + "/avatar"; + } + + /** + * 获取下载路径 + */ + public static String getDownloadPath() + { + return getProfile() + "/download/"; + } + + /** + * 获取上传路径 + */ + public static String getUploadPath() + { + return getProfile() + "/upload"; + } +} diff --git a/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..d36253c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -0,0 +1,151 @@ +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"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 防重提交 redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 限流 redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 验证码有效期(分钟) + */ + 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"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi://"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap://"; +} 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..1fa328e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java @@ -0,0 +1,114 @@ +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 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..d60afee --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java @@ -0,0 +1,89 @@ +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; +} 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..4ed6009 --- /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 String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; + + /** + * 用户名长度限制 + */ + 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..d164f3f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java @@ -0,0 +1,184 @@ +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.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() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) + { + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + PageHelper.startPage(pageNum, pageSize, orderBy); + } + } + + /** + * 设置请求排序数据 + */ + protected void startOrderBy() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) + { + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + PageHelper.orderBy(orderBy); + } + } + + /** + * 响应请求分页数据 + */ + @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 error(String message) + { + return AjaxResult.error(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().getUser().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..28e5a68 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java @@ -0,0 +1,148 @@ +package com.ruoyi.common.core.domain; + +import java.util.HashMap; +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); + } + + /** + * 返回错误消息 + * + * @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); + } +} 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..f7d5bf4 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -0,0 +1,114 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * Entity基类 + * + * @author ruoyi + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 搜索值 */ + private String searchValue; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** 备注 */ + private String remark; + + /** 请求参数 */ + 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/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..bd835db --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java @@ -0,0 +1,77 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * Treeselect树结构实体类 + * + * @author ruoyi + */ +public class TreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点名称 */ + private String label; + + /** 子节点 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect() + { + + } + + public TreeSelect(SysDept dept) + { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysMenu menu) + { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/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..c9238e2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -0,0 +1,202 @@ +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.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 String orderNum; + + /** 负责人 */ + private String leader; + + /** 联系电话 */ + private String phone; + + /** 邮箱 */ + private String email; + + /** 部门状态:0正常,1停用 */ + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 父部门名称 */ + private String parentName; + + /** 子部门 */ + private List children = new ArrayList(); + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + @NotBlank(message = "部门名称不能为空") + @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + @NotBlank(message = "显示顺序不能为空") + public String getOrderNum() + { + return orderNum; + } + + public void setOrderNum(String 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..3f152b3 --- /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) ? true : false; + } + + 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..d2c4249 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -0,0 +1,94 @@ +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.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个字符") + 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..94d654a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -0,0 +1,245 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.ArrayList; +import java.util.List; +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; + +/** + * 菜单权限表 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 String orderNum; + + /** 路由地址 */ + private String path; + + /** 组件路径 */ + private String component; + + /** 是否为外链(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; + } + + @NotBlank(message = "显示顺序不能为空") + public String getOrderNum() + { + return orderNum; + } + + public void setOrderNum(String 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 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..36629eb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -0,0 +1,226 @@ +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.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 String 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; + + 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; + } + + @NotBlank(message = "显示顺序不能为空") + public String getRoleSort() + { + return roleSort; + } + + public void setRoleSort(String 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; + } + + @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..dc03436 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -0,0 +1,365 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.Email; +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.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +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; + +/** + * 用户对象 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; + + /** 用户邮箱 */ + @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; + + /** 盐加密 */ + private String salt; + + /** 帐号状态(0正常 1停用) */ + @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 最后登录IP */ + @Excel(name = "最后登录IP", type = Type.EXPORT) + private String loginIp; + + /** 最后登录时间 */ + @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) + private Date loginDate; + + /** 部门对象 */ + @Excels({ + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + }) + private SysDept dept; + + /** 角色对象 */ + private List roles; + + /** 角色组 */ + private Long[] roleIds; + + /** 岗位组 */ + private Long[] postIds; + + /** 角色ID */ + private Long roleId; + +// 行政代码 + private Long distictId; + +// 运营商id + private Long providerId; + + 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; + } + + @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") + public String getPhonenumber() + { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) + { + this.phonenumber = phonenumber; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + @JsonIgnore + @JsonProperty + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getSalt() + { + return salt; + } + + public void setSalt(String salt) + { + this.salt = salt; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getLoginIp() + { + return loginIp; + } + + public void setLoginIp(String loginIp) + { + this.loginIp = loginIp; + } + + public Date getLoginDate() + { + return loginDate; + } + + public void setLoginDate(Date loginDate) + { + this.loginDate = loginDate; + } + + public SysDept getDept() + { + return dept; + } + + public void setDept(SysDept dept) + { + this.dept = dept; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + public Long[] getRoleIds() + { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) + { + this.roleIds = roleIds; + } + + public Long[] getPostIds() + { + return postIds; + } + + public void setPostIds(Long[] postIds) + { + this.postIds = postIds; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("salt", getSalt()) + .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()) + .append("distict", getDistictId()) + .append("provider", getProviderId()) + .toString(); + } + + public Long getDistictId() { + return distictId; + } + + public void setDistictId(Long distictId) { + this.distictId = distictId; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } +} 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..03948b4 --- /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..a8a0d0f --- /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 java.util.Collection; +import java.util.Set; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 登录用户身份权限 + * + * @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 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; + } + + 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; + } + + @JsonIgnore + @Override + public String getPassword() + { + return user.getPassword(); + } + + @Override + public String getUsername() + { + return user.getUserName(); + } + + /** + * 账户是否未过期,过期无法验证 + */ + @JsonIgnore + @Override + public boolean isAccountNonExpired() + { + return true; + } + + /** + * 指定用户是否解锁,锁定的用户无法进行身份验证 + * + * @return + */ + @JsonIgnore + @Override + public boolean isAccountNonLocked() + { + return true; + } + + /** + * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 + * + * @return + */ + @JsonIgnore + @Override + public boolean isCredentialsNonExpired() + { + return true; + } + + /** + * 是否可用 ,禁用的用户不能身份验证 + * + * @return + */ + @JsonIgnore + @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..b9d5e6e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -0,0 +1,84 @@ +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"; + + 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; + } + } +} 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..14eb1e1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.core.page; + +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 PageDomain getPageDomain() + { + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); + pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); + pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); + pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); + 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..22a610d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -0,0 +1,234 @@ +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 缓存键值 + * @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 long deleteObject(final Collection collection) + { + return redisTemplate.delete(collection); + } + + /** + * 缓存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); + } + + /** + * 获得缓存的基本对象列表 + * + * @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..1fb7461 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java @@ -0,0 +1,1005 @@ +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": + return true; + case "false": + return false; + case "yes": + return true; + case "ok": + return true; + case "no": + return false; + case "1": + return true; + 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 new BigDecimal((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/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java new file mode 100644 index 0000000..be6f739 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java @@ -0,0 +1,36 @@ +package com.ruoyi.common.enums; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.Nullable; + +/** + * 请求方式 + * + * @author ruoyi + */ +public enum HttpMethod +{ + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + + private static final Map mappings = new HashMap<>(16); + + static + { + for (HttpMethod httpMethod : values()) + { + mappings.put(httpMethod.name(), httpMethod); + } + } + + @Nullable + public static HttpMethod resolve(@Nullable String method) + { + return (method != null ? mappings.get(method) : null); + } + + public boolean matches(String method) + { + return (this == resolve(method)); + } +} diff --git a/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/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/exception/CustomException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java new file mode 100644 index 0000000..b9ee3af --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java @@ -0,0 +1,37 @@ +package com.ruoyi.common.exception; + +/** + * 自定义异常 + * + * @author ruoyi + */ +public class CustomException extends RuntimeException { + private static final long serialVersionUID = 1L; + + private Integer code; + + private String message; + + public CustomException(String message) { + this.message = message; + } + + public CustomException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public CustomException(String message, Throwable e) { + super(message, e); + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public Integer getCode() { + return code; + } +} diff --git a/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/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java new file mode 100644 index 0000000..211441b --- /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; + } + + 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..cce6052 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java @@ -0,0 +1,77 @@ +package com.ruoyi.common.exception; + +/** + * 业务异常 + * + * @author ruoyi + */ +public 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; + } + + 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; + } + + public void setCode(Integer code) { + this.code = code; + } +} \ 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/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java new file mode 100644 index 0000000..f1c8e83 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java @@ -0,0 +1,81 @@ +package com.ruoyi.common.exception.file; + +import java.util.Arrays; +import org.apache.commons.fileupload.FileUploadException; + +/** + * 文件上传 误异常类 + * + * @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 : [" + filename + "], extension : [" + extension + "], allowed 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/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/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/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..614c24c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java @@ -0,0 +1,75 @@ +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; + +/** + * 构建可重复读取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("UTF-8"); + response.setCharacterEncoding("UTF-8"); + + body = HttpHelper.getBodyString(request).getBytes("UTF-8"); + } + + @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..99323ed --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java @@ -0,0 +1,74 @@ +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; + +/** + * 防止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 || method.matches("GET") || method.matches("DELETE")) + { + 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..4508c92 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,104 @@ +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[] escapseValues = new String[length]; + for (int i = 0; i < length; i++) + { + // 防xss攻击和过滤前后空格 + escapseValues[i] = EscapeUtil.clean(values[i]).trim(); + } + return escapseValues; + } + 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(); + final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8")); + return new ServletInputStream() + { + @Override + public boolean isFinished() + { + return true; + } + + @Override + public boolean isReady() + { + return true; + } + + @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..536cb3c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -0,0 +1,155 @@ +package com.ruoyi.common.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +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 String getDatePoor(Date endDate, Date nowDate) + { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - nowDate.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 + "分钟"; + } +} 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..fd9946d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -0,0 +1,183 @@ +package com.ruoyi.common.utils; + +import java.util.Collection; +import java.util.List; +import com.ruoyi.common.constant.Constants; +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) + { + Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + if (StringUtils.isNotNull(cacheObj)) + { + List dictDatas = StringUtils.cast(cacheObj); + return dictDatas; + } + 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.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas)) + { + for (SysDictData dict : datas) + { + for (String value : dictValue.split(separator)) + { + if (value.equals(dict.getDictValue())) + { + propertyString.append(dict.getDictLabel() + 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() + 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(Constants.SYS_DICT_KEY + "*"); + SpringUtils.getBean(RedisCache.class).deleteObject(keys); + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + public static String getCacheKey(String configKey) + { + return Constants.SYS_DICT_KEY + configKey; + } +} 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..ae81a69 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java @@ -0,0 +1,40 @@ +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)); + String str = sw.toString(); + return str; + } + + 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/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/RedisCahceKey.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisCahceKey.java new file mode 100644 index 0000000..9888118 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisCahceKey.java @@ -0,0 +1,91 @@ +package com.ruoyi.common.utils; + +/** + * Created by 魔金商城 on 18/2/6. + * redis缓存中的key + */ +public interface RedisCahceKey { + + /** + * mobile端首页缓存key + */ + String MOBILE_TEMPLATE = "MOBILE_TEMPLATE"; + + /** + * 地区缓存key + */ + String AREA = "AREA"; + + /** + * 基本信息设置缓存key + */ + String BASE_INFO_SET = "BASE_INFO_SET"; + + /** + * pc端首页缓存key + */ + String PC_TEMPLATE = "PC_TEMPLATE"; + + + // pc端店铺首页模版缓存key + String STORE_PC_TEMPLATE = "STORE_PC_TEMPLATE"; + + /** + * 手机端专题页缓存key + */ + String MOBILE_THEMATIC = "MOBILE_THEMATIC"; + + /** + * PC端专题页缓存key + */ + String PC_THEMATIC = "PC_THEMATIC"; + + /** + * APP端首页模版缓存key + */ + String APP_INDEX_TEMPLATE = "APP_INDEX_TEMPLATE"; + + /** + * APP 专题页缓存 + */ + String APP_THEMATIC = "APP_THEMATIC"; + + /** + * APPLET 端首页模版缓存key + */ + String APPLET_INDEX_TEMPLATE = "APPLET_INDEX_TEMPLATE"; + + /** + * APPLET 专题页缓存 + */ + String APPLET_THEMATIC = "APPLET_THEMATIC"; + + + /** + * 促销设置缓存key + */ + String MARKETING_SETTING = "MARKETING_SETTING"; + + /** + * 微信用户关联缓存key + */ + String WE_CHAT_CUSTOMER_LINK = "WE_CHAT_CUSTOMER_LINK"; + + /** + * 微信用户关联缓存key + */ + String WE_CHAT_OPENID = "WE_CHAT_OPENID"; + + /** + * app版本 + */ + String APP_VERSION = "APP_VERSION"; + /** + * 社区团购设置 + */ + String COMMUNITY_BUY_SETTING = "COMMUNITY_BUY_SETTING"; + /** + * 社区推广 + */ + String COMMUNITY_BUY_INDEX = "COMMUNITY_BUY_INDEX"; +} 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..ab9ebcf --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java @@ -0,0 +1,136 @@ +package com.ruoyi.common.utils; + +import java.io.IOException; +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.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); + } + + /** + * 获取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 待渲染的字符串 + * @return null + */ + public static String 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(); + } + return null; + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + String accept = request.getHeader("accept"); + if (accept != null && accept.indexOf("application/json") != -1) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) + { + return true; + } + return false; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SnowflakeIdWorker.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SnowflakeIdWorker.java new file mode 100644 index 0000000..ece52e1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SnowflakeIdWorker.java @@ -0,0 +1,171 @@ +package com.ruoyi.common.utils; + + +/** + * Created by 魔金商城 on 17/11/02. + *

    + * Twitter_Snowflake
    + * SnowFlake的结构如下(每部分用-分开):
    + * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
    + * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
    + * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) + * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
    + * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
    + * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
    + * 加起来刚好64位,为一个Long型。
    + * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 + */ +public class SnowflakeIdWorker { + /** + * 开始时间截 (2015-01-01) + */ + private final long twepoch = 1420041600000L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long datacenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private long workerId; + + /** + * 数据中心ID(0~31) + */ + private long datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + //==============================Constructors===================================== + + /** + * 构造函数 + * + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeIdWorker(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + +} \ No newline at end of file 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..4ca2bfc --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java @@ -0,0 +1,534 @@ +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; + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @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; + } + 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; + } +} \ 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..1934195 --- /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/VerifyCodeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java new file mode 100644 index 0000000..5fdf3a9 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java @@ -0,0 +1,228 @@ +package com.ruoyi.common.utils; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Random; +import javax.imageio.ImageIO; + +/** + * 验证码工具类 + * + * @author ruoyi + */ +public class VerifyCodeUtils +{ + // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 + public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; + + private static Random random = new SecureRandom(); + + /** + * 使用系统默认字符源生成验证码 + * + * @param verifySize 验证码长度 + * @return + */ + public static String generateVerifyCode(int verifySize) + { + return generateVerifyCode(verifySize, VERIFY_CODES); + } + + /** + * 使用指定源生成验证码 + * + * @param verifySize 验证码长度 + * @param sources 验证码字符源 + * @return + */ + public static String generateVerifyCode(int verifySize, String sources) + { + if (sources == null || sources.length() == 0) + { + sources = VERIFY_CODES; + } + int codesLen = sources.length(); + Random rand = new Random(System.currentTimeMillis()); + StringBuilder verifyCode = new StringBuilder(verifySize); + for (int i = 0; i < verifySize; i++) + { + verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1))); + } + return verifyCode.toString(); + } + + /** + * 输出指定验证码图片流 + * + * @param w + * @param h + * @param os + * @param code + * @throws IOException + */ + public static void outputImage(int w, int h, OutputStream os, String code) throws IOException + { + int verifySize = code.length(); + BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Random rand = new Random(); + Graphics2D g2 = image.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color[] colors = new Color[5]; + Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, + Color.ORANGE, Color.PINK, Color.YELLOW }; + float[] fractions = new float[colors.length]; + for (int i = 0; i < colors.length; i++) + { + colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; + fractions[i] = rand.nextFloat(); + } + Arrays.sort(fractions); + + g2.setColor(Color.GRAY);// 设置边框色 + g2.fillRect(0, 0, w, h); + + Color c = getRandColor(200, 250); + g2.setColor(c);// 设置背景色 + g2.fillRect(0, 2, w, h - 4); + + // 绘制干扰线 + Random random = new Random(); + g2.setColor(getRandColor(160, 200));// 设置线条的颜色 + for (int i = 0; i < 20; i++) + { + int x = random.nextInt(w - 1); + int y = random.nextInt(h - 1); + int xl = random.nextInt(6) + 1; + int yl = random.nextInt(12) + 1; + g2.drawLine(x, y, x + xl + 40, y + yl + 20); + } + + // 添加噪点 + float yawpRate = 0.05f;// 噪声率 + int area = (int) (yawpRate * w * h); + for (int i = 0; i < area; i++) + { + int x = random.nextInt(w); + int y = random.nextInt(h); + int rgb = getRandomIntColor(); + image.setRGB(x, y, rgb); + } + + shear(g2, w, h, c);// 使图片扭曲 + + g2.setColor(getRandColor(100, 160)); + int fontSize = h - 4; + Font font = new Font("Algerian", Font.ITALIC, fontSize); + g2.setFont(font); + char[] chars = code.toCharArray(); + for (int i = 0; i < verifySize; i++) + { + AffineTransform affine = new AffineTransform(); + affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), + (w / verifySize) * i + fontSize / 2, h / 2); + g2.setTransform(affine); + g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); + } + + g2.dispose(); + ImageIO.write(image, "jpg", os); + } + + private static Color getRandColor(int fc, int bc) + { + if (fc > 255) { + fc = 255; + } + if (bc > 255) { + bc = 255; + } + int r = fc + random.nextInt(bc - fc); + int g = fc + random.nextInt(bc - fc); + int b = fc + random.nextInt(bc - fc); + return new Color(r, g, b); + } + + private static int getRandomIntColor() + { + int[] rgb = getRandomRgb(); + int color = 0; + for (int c : rgb) + { + color = color << 8; + color = color | c; + } + return color; + } + + private static int[] getRandomRgb() + { + int[] rgb = new int[3]; + for (int i = 0; i < 3; i++) + { + rgb[i] = random.nextInt(255); + } + return rgb; + } + + private static void shear(Graphics g, int w1, int h1, Color color) + { + shearX(g, w1, h1, color); + shearY(g, w1, h1, color); + } + + private static void shearX(Graphics g, int w1, int h1, Color color) + { + + int period = random.nextInt(2); + + boolean borderGap = true; + int frames = 1; + int phase = random.nextInt(2); + + for (int i = 0; i < h1; i++) + { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); + g.copyArea(0, i, w1, 1, (int) d, 0); + if (borderGap) + { + g.setColor(color); + g.drawLine((int) d, i, 0, i); + g.drawLine((int) d + w1, i, w1, i); + } + } + + } + + private static void shearY(Graphics g, int w1, int h1, Color color) + { + + int period = random.nextInt(40) + 10; // 50; + + boolean borderGap = true; + int frames = 20; + int phase = 7; + for (int i = 0; i < w1; i++) + { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); + g.copyArea(i, 0, 1, h1, 0, (int) d); + if (borderGap) + { + g.setColor(color); + g.drawLine(i, (int) d, i, 0); + g.drawLine(i, (int) d + h1, i, h1); + } + + } + } +} \ 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/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..eb12806 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -0,0 +1,235 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import java.io.IOException; +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.IdUtils; + +/** + * 文件上传工具类 + * + * @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 = 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); + + File desc = getAbsoluteFile(baseDir, fileName); + file.transferTo(desc); + String pathFileName = getPathFileName(baseDir, fileName); + return pathFileName; + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) + { + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + return fileName; + } + + 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); + String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + return pathFileName; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @return + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (DEFAULT_MAX_SIZE != -1 && 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(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..ff33055 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -0,0 +1,256 @@ +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; + +/** + * 文件处理工具类 + * + * @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()) + { + file.delete(); + flag = true; + } + 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 真实文件名 + * @return + */ + 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.setHeader("Content-disposition", contentDispositionValue.toString()); + } + + /** + * 百分号编码工具方法 + * + * @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; + } +} 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..0b7b5aa --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java @@ -0,0 +1,101 @@ +package com.ruoyi.common.utils.file; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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 key 地址 + * @return 字节数据 + */ + public static byte[] readFile(String url) + { + InputStream in = null; + ByteArrayOutputStream baos = 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); + IOUtils.closeQuietly(baos); + } + } +} 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/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java new file mode 100644 index 0000000..7f74ac2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java @@ -0,0 +1,155 @@ +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) + { + int len; + if ((text == null) || ((len = text.length()) == 0)) + { + return StringUtils.EMPTY; + } + StringBuilder buffer = new StringBuilder(len + (len >> 2)); + char c; + for (int i = 0; i < len; i++) + { + c = text.charAt(i); + if (c < 64) + { + buffer.append(TEXT[c]); + } + else + { + buffer.append(c); + } + } + return buffer.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 html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println(EscapeUtil.clean(html)); + System.out.println(EscapeUtil.escape(html)); + System.out.println(EscapeUtil.unescape(html)); + } +} 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..cd8cd4f --- /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 (false == 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..dac60ad --- /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.Charset; +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, Charset.forName("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..9aee92e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java @@ -0,0 +1,262 @@ +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.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; + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 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 = url + "?" + param; + 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 + { + String urlNameString = url; + log.info("sendPost - {}", urlNameString); + URL realUrl = new URL(urlNameString); + 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(), "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("ISO-8859-1"), "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..01c24fc --- /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.fastjson.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) + { + String address = UNKNOWN; + // 内网不查询 + 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 = JSONObject.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 address; + } +} 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..1b3f42b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java @@ -0,0 +1,195 @@ +package com.ruoyi.common.utils.ip; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.html.EscapeUtil; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils +{ + 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" : EscapeUtil.clean(ip); + } + + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + 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; + } + + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + } + return "127.0.0.1"; + } + + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + } + return "未知"; + } +} \ No newline at end of file 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..4862a4b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -0,0 +1,1256 @@ +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.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +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.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.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.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); + + /** + * 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 short maxHeight; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + public void init(List list, String sheetName, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + createExcelField(); + createWorkbook(); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(StringUtils.EMPTY, is); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is) 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(0); + 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. + Field[] allFields = clazz.getDeclaredFields(); + // 定义一个map用于存放列的序号和field. + Map fieldsMap = new HashMap(); + for (int col = 0; col < allFields.length; col++) + { + Field field = allFields[col]; + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + // 设置类的私有字段属性可访问. + field.setAccessible(true); + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, field); + } + } + } + for (int i = 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 = fieldsMap.get(entry.getKey()); + // 取得类型,并根据对象类型设置值. + 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 = DateUtils.parseDateToStr(dateFormat, (Date) 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) + { + 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)) + { + Excel attr = field.getAnnotation(Excel.class); + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) + { + PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); + if (image == null) + { + val = ""; + } + 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) + { + this.init(list, sheetName, Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param response 返回数据 + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + * @throws IOException + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName) throws IOException + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(list, sheetName, Type.EXPORT); + exportExcel(response.getOutputStream()); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + this.init(null, sheetName, Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName) throws IOException + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(null, sheetName, Type.IMPORT); + exportExcel(response.getOutputStream()); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public void exportExcel(OutputStream out) + { + try + { + writeSheet(); + wb.write(out); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + } + finally + { + IOUtils.closeQuietly(wb); + IOUtils.closeQuietly(out); + } + } + + /** + * 对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. + double sheetNo = Math.ceil(list.size() / sheetSize); + for (int index = 0; index <= sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(0); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + this.createCell(excel, row, column++); + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + for (int i = startNo; i < endNo; i++) + { + row = sheet.createRow(i + 1 - startNo); + // 得到导出对象. + T vo = (T) list.get(i); + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + // 设置实体类私有属性可访问 + field.setAccessible(true); + 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); + 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.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(IndexedColors.WHITE.getIndex()); + style.setFont(headerFont); + styles.put("header", 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); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.LEFT); + styles.put("data1", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + styles.put("data2", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.RIGHT); + styles.put("data3", style); + + return styles; + } + + /** + * 创建单元格 + */ + public Cell createCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get("header")); + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + 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())) + { + // 这里默认设了2-101列提示. + setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); + } + // 如果设置了combo属性则本列只能选择不能输入 + if (attr.combo().length > 0) + { + // 这里默认设了2-101列只能选择不能输入. + setXSSFValidation(sheet, attr.combo(), 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); + int align = attr.align().value(); + cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); + + // 用于读取对象中的属性 + 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(DateUtils.parseDateToStr(dateFormat, (Date) 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)) + { + cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); + } + 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 promptTitle 提示标题 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + dataValidation.createPromptBox(promptTitle, promptContent); + dataValidation.setShowPromptBox(true); + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @return 设置好的sheet. + */ + public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + } + + /** + * 解析导出值 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(separator, propertyValue)) + { + 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(separator, propertyValue)) + { + 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); + } + + /** + * 合计统计信息 + */ + 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().toString() + "_" + 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.indexOf(".") > -1) + { + 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 = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + putToField(field, field.getAnnotation(Excel.class)); + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel excel : excels) + { + putToField(field, excel); + } + } + } + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); + } + return (short) (maxHeight * 20); + } + + /** + * 放到字段集合中 + */ + private void putToField(Field field, Excel attr) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + this.fields.add(new Object[] { field, attr }); + } + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(double sheetNo, int index) + { + this.sheet = wb.createSheet(); + this.styles = createStyles(wb); + // 设置工作表的名称. + if (sheetNo == 0) + { + wb.setSheetName(index, sheetName); + } + else + { + 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 = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(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; + } +} 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..de77ee8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java @@ -0,0 +1,66 @@ +package com.ruoyi.common.utils.sign; + +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("UTF-8"), "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..9993b98 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java @@ -0,0 +1,146 @@ +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; + } +} 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..a198946 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java @@ -0,0 +1,37 @@ +package com.ruoyi.common.utils.sql; + +import com.ruoyi.common.exception.UtilException; +import com.ruoyi.common.utils.StringUtils; + +/** + * sql操作工具类 + * + * @author ruoyi + */ +public class SqlUtil +{ + /** + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) + */ + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new UtilException("参数不符合规范,不能进行查询"); + } + return value; + } + + /** + * 验证 order by 语法是否符合规范 + */ + public static boolean isValidOrderBySql(String value) + { + return value.matches(SQL_PATTERN); + } +} 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/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java new file mode 100644 index 0000000..062d633 --- /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 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID fastUUID() + { + return randomUUID(false); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID() + { + return randomUUID(true); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID(boolean isSecure) + { + final Random ng = isSecure ? Holder.numberGenerator : getRandom(); + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; /* clear version */ + randomBytes[6] |= 0x40; /* set to version 4 */ + randomBytes[8] &= 0x3f; /* clear variant */ + randomBytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(randomBytes); + } + + /** + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 + * + * @param name 用于构造 UUID 的字节数组。 + * + * @return 根据指定数组生成的 {@code UUID} + */ + public static UUID nameUUIDFromBytes(byte[] name) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException nsae) + { + throw new InternalError("MD5 not supported"); + } + byte[] md5Bytes = md.digest(name); + md5Bytes[6] &= 0x0f; /* clear version */ + md5Bytes[6] |= 0x30; /* set to version 3 */ + md5Bytes[8] &= 0x3f; /* clear variant */ + md5Bytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(md5Bytes); + } + + /** + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 + * + * @param name 指定 {@code UUID} 字符串 + * @return 具有指定值的 {@code UUID} + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 + * + */ + public static UUID fromString(String name) + { + String[] components = name.split("-"); + if (components.length != 5) + { + throw new IllegalArgumentException("Invalid UUID string: " + name); + } + for (int i = 0; i < 5; i++) + { + components[i] = "0x" + components[i]; + } + + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new UUID(mostSigBits, leastSigBits); + } + + /** + * 返回此 UUID 的 128 位值中的最低有效 64 位。 + * + * @return 此 UUID 的 128 位值中的最低有效 64 位。 + */ + public long getLeastSignificantBits() + { + return leastSigBits; + } + + /** + * 返回此 UUID 的 128 位值中的最高有效 64 位。 + * + * @return 此 UUID 的 128 位值中最高有效 64 位。 + */ + public long getMostSignificantBits() + { + return mostSigBits; + } + + /** + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 + *

    + * 版本号具有以下含意: + *

      + *
    • 1 基于时间的 UUID + *
    • 2 DCE 安全 UUID + *
    • 3 基于名称的 UUID + *
    • 4 随机生成的 UUID + *
    + * + * @return 此 {@code UUID} 的版本号 + */ + public int version() + { + // Version is bits masked by 0x000000000000F000 in MS long + return (int) ((mostSigBits >> 12) & 0x0f); + } + + /** + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 + *

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

      + *
    • 0 为 NCS 向后兼容保留 + *
    • 2 IETF RFC 4122(Leach-Salz), 用于此类 + *
    • 6 保留,微软向后兼容 + *
    • 7 保留供以后定义使用 + *
    + * + * @return 此 {@code UUID} 相关联的变体号 + */ + public int variant() + { + // This field is composed of a varying number of bits. + // 0 - - Reserved for NCS backward compatibility + // 1 0 - The IETF aka Leach-Salz variant (used by this class) + // 1 1 0 Reserved, Microsoft backward compatibility + // 1 1 1 Reserved for future definition. + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); + } + + /** + * 与此 UUID 相关联的时间戳值。 + * + *

    + * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。
    + * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 + * + *

    + * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。
    + * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 + */ + public long timestamp() throws UnsupportedOperationException + { + checkTimeBase(); + return (mostSigBits & 0x0FFFL) << 48// + | ((mostSigBits >> 16) & 0x0FFFFL) << 32// + | mostSigBits >>> 32; + } + + /** + * 与此 UUID 相关联的时钟序列值。 + * + *

    + * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 + *

    + * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 + * UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的时钟序列 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public int clockSequence() throws UnsupportedOperationException + { + checkTimeBase(); + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + + /** + * 与此 UUID 相关的节点值。 + * + *

    + * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 + *

    + * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。
    + * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的节点值 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public long node() throws UnsupportedOperationException + { + checkTimeBase(); + return leastSigBits & 0x0000FFFFFFFFFFFFL; + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

    + * UUID 的字符串表示形式由此 BNF 描述: + * + *

    +     * {@code
    +     * UUID                   = ----
    +     * time_low               = 4*
    +     * time_mid               = 2*
    +     * time_high_and_version  = 2*
    +     * variant_and_sequence   = 2*
    +     * node                   = 6*
    +     * hexOctet               = 
    +     * hexDigit               = [0-9a-fA-F]
    +     * }
    +     * 
    + * + * + * + * @return 此{@code UUID} 的字符串表现形式 + * @see #toString(boolean) + */ + @Override + public String toString() + { + return toString(false); + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

    + * UUID 的字符串表示形式由此 BNF 描述: + * + *

    +     * {@code
    +     * UUID                   = ----
    +     * time_low               = 4*
    +     * time_mid               = 2*
    +     * time_high_and_version  = 2*
    +     * variant_and_sequence   = 2*
    +     * node                   = 6*
    +     * hexOctet               = 
    +     * hexDigit               = [0-9a-fA-F]
    +     * }
    +     * 
    + * + * + * + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 + * @return 此{@code UUID} 的字符串表现形式 + */ + public String toString(boolean isSimple) + { + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); + // time_low + builder.append(digits(mostSigBits >> 32, 8)); + if (false == isSimple) + { + builder.append('-'); + } + // time_mid + builder.append(digits(mostSigBits >> 16, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // time_high_and_version + builder.append(digits(mostSigBits, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // variant_and_sequence + builder.append(digits(leastSigBits >> 48, 4)); + if (false == 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-framework/pom.xml b/ruoyi-framework/pom.xml new file mode 100644 index 0000000..15f13e8 --- /dev/null +++ b/ruoyi-framework/pom.xml @@ -0,0 +1,66 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + + 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 + + + + + com.github.penggle + kaptcha + + + javax.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..226e150 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -0,0 +1,181 @@ +package com.ruoyi.framework.aspectj; + +import java.lang.reflect.Method; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +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.utils.StringUtils; +import com.ruoyi.common.utils.SecurityUtils; + +/** + * 数据过滤处理 + * + * @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"; + + // 配置织入点 + @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") + public void dataScopePointCut() + { + } + + @Before("dataScopePointCut()") + public void doBefore(JoinPoint point) throws Throwable + { + clearDataScope(point); + handleDataScope(point); + } + + protected void handleDataScope(final JoinPoint joinPoint) + { + // 获得注解 + DataScope controllerDataScope = getAnnotationLog(joinPoint); + if (controllerDataScope == null) + { + return; + } + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias()); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param userAlias 别名 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) + { + StringBuilder sqlString = new StringBuilder(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + 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(" OR 1=0 "); + } + } + } + + 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) + ")"); + } + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private DataScope getAnnotationLog(JoinPoint joinPoint) + { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) + { + return method.getAnnotation(DataScope.class); + } + return null; + } + + /** + * 拼接权限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..89b5a32 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -0,0 +1,243 @@ +package com.ruoyi.framework.aspectj; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +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.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; +import com.alibaba.fastjson.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.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.SecurityUtils; +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); + + // 配置织入点 + @Pointcut("@annotation(com.ruoyi.common.annotation.Log)") + public void logPointCut() + { + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) + { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) + { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) + { + try + { + // 获得注解 + Log controllerLog = getAnnotationLog(joinPoint); + if (controllerLog == null) + { + return; + } + + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // *========数据库日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + operLog.setOperIp(ip); + // 返回参数 + operLog.setJsonResult(JSON.toJSONString(jsonResult)); + + operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); + 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); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("==前置通知异常=="); + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) 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中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception + { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) + { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private Log getAnnotationLog(JoinPoint joinPoint) throws Exception + { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) + { + return method.getAnnotation(Log.class); + } + return null; + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (int i = 0; i < paramsArray.length; i++) + { + if (StringUtils.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i])) + { + Object jsonObj = JSON.toJSON(paramsArray[i]); + params += jsonObj.toString() + " "; + } + } + } + return params.trim(); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Iterator iter = collection.iterator(); iter.hasNext();) + { + return iter.next() instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) + { + Map.Entry entry = (Map.Entry) iter.next(); + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/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..12aa291 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -0,0 +1,116 @@ +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.Signature; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +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.ServletUtils; +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; + } + + // 配置织入点 + @Pointcut("@annotation(com.ruoyi.common.annotation.RateLimiter)") + public void rateLimiterPointCut() + { + } + + @Before("rateLimiterPointCut()") + public void doBefore(JoinPoint point) throws Throwable + { + RateLimiter rateLimiter = getAnnotationRateLimiter(point); + String key = rateLimiter.key(); + 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(), key); + } + catch (ServiceException e) + { + throw e; + } + catch (Exception e) + { + throw new RuntimeException("服务器限流异常,请稍后再试"); + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private RateLimiter getAnnotationRateLimiter(JoinPoint joinPoint) + { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) + { + return method.getAnnotation(RateLimiter.class); + } + return null; + } + + public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) + { + StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); + if (rateLimiter.limitType() == LimitType.IP) + { + stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())); + } + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + Class targetClass = method.getDeclaringClass(); + stringBuffer.append("-").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..1d4dc1f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -0,0 +1,30 @@ +package com.ruoyi.framework.config; + +import java.util.TimeZone; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * 程序注解配置 + * + * @author ruoyi + */ +@Configuration +// 表示通过aop框架暴露该代理对象,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// 指定要扫描的Mapper类的包的路径 +@MapperScan("com.ruoyi.**.mapper") +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} 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..59812ea --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,71 @@ +package com.ruoyi.framework.config; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import com.alibaba.fastjson.parser.ParserConfig; +import org.springframework.util.Assert; +import java.nio.charset.Charset; + +/** + * Redis使用FastJson序列化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + @SuppressWarnings("unused") + private ObjectMapper objectMapper = new ObjectMapper(); + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static + { + ParserConfig.getGlobalInstance().setAutoTypeSupport(true); + } + + 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, SerializerFeature.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); + } + + public void setObjectMapper(ObjectMapper objectMapper) + { + Assert.notNull(objectMapper, "'objectMapper' must not be null"); + this.objectMapper = objectMapper; + } + + protected JavaType getJavaType(Class clazz) + { + return TypeFactory.defaultInstance().constructType(clazz); + } +} 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..87b3750 --- /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 +@ConditionalOnProperty(value = "xss.enabled", havingValue = "true") +public class FilterConfig +{ + @Value("${xss.excludes}") + private String excludes; + + @Value("${xss.urlPatterns}") + private String urlPatterns; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + 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..3e74580 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java @@ -0,0 +1,75 @@ +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 = (int) Math.round(Math.random() * 2); + 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 (randomoperands == 2) + { + 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]); + } + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + 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..3c3185e --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -0,0 +1,79 @@ +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; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; + +/** + * 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); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + serializer.setObjectMapper(mapper); + + // 使用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 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 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..4f197d7 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -0,0 +1,65 @@ +package com.ruoyi.framework.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.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/"); + } + + /** + * 自定义拦截规则 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); + } + + /** + * 跨域配置 + */ +// @Bean +// public CorsFilter corsFilter() +// { +// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); +// CorsConfiguration config = new CorsConfiguration(); +// config.setAllowCredentials(true); +// // 设置访问源地址 +// config.addAllowedOrigin("*"); +// // 设置访问源请求头 +// config.addAllowedHeader("*"); +// // 设置访问源请求方法 +// config.addAllowedMethod("*"); +// // 对接口配置跨域设置 +// source.registerCorsConfiguration("/**", config); +// return new CorsFilter(source); +// } +} \ No newline at end of file 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..0d67c22 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java @@ -0,0 +1,62 @@ +package com.ruoyi.framework.config; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +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 com.ruoyi.common.utils.Threads; + +/** + * 线程池配置 + * + * @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()) + { + @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..84f7e00 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java @@ -0,0 +1,77 @@ +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.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.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/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..3572db9 --- /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..17d607f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,55 @@ +package com.ruoyi.framework.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import com.alibaba.fastjson.JSONObject; +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 extends HandlerInterceptorAdapter +{ + @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)) + { + AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试"); + ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return super.preHandle(request, response, handler); + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * + * @param request + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request); +} 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..cb4edbe --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -0,0 +1,125 @@ +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.fastjson.JSONObject; +import com.ruoyi.common.constant.Constants; +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; + + /** + * 间隔时间,单位:秒 默认10秒 + * + * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据 + */ + private int intervalTime = 10; + + public void setIntervalTime(int intervalTime) + { + this.intervalTime = intervalTime; + } + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request) + { + String nowParams = ""; + if (request instanceof RepeatedlyRequestWrapper) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + nowParams = HttpHelper.getBodyString(repeatedlyRequest); + } + + // body参数为空,获取Parameter的数据 + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSONObject.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 = request.getHeader(header); + if (StringUtils.isEmpty(submitKey)) + { + submitKey = url; + } + + // 唯一标识(指定key + 消息头) + String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + 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)) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(cacheRepeatKey, cacheMap, intervalTime, TimeUnit.SECONDS); + 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) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < (this.intervalTime * 1000)) + { + 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..23d0230 --- /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(ServletUtils.getRequest()); + 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/web/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java new file mode 100644 index 0000000..0f2db93 --- /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 org.springframework.util.StringUtils; +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.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(); + + boolean captchaOnOff = configService.selectCaptchaOnOff(); + // 验证码开关 + if (captchaOnOff) + { + 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 (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) + { + msg = "保存用户'" + username + "'失败,注册账号已存在"; + } + else + { + SysUser sysUser = new SysUser(); + sysUser.setUserName(username); + sysUser.setNickName(username); + sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword())); + 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 = Constants.CAPTCHA_CODE_KEY + 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..bf28e0f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -0,0 +1,225 @@ +package com.ruoyi.framework.web.service; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * token验证处理 + * + * @author ruoyi + */ +@Component +public class TokenService +{ + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + // 令牌秘钥 + @Value("${token.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Autowired + private RedisCache redisCache; + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(HttpServletRequest request) + { + // 获取请求携带的令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) + { + try + { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user; + } + catch (Exception e) + { + } + } + return null; + } + + /** + * 设置用户身份信息 + */ + public void setLoginUser(LoginUser loginUser) + { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) + { + refreshToken(loginUser); + } + } + + /** + * 删除用户身份信息 + */ + public void delLoginUser(String token) + { + if (StringUtils.isNotEmpty(token)) + { + String userKey = getTokenKey(token); + redisCache.deleteObject(userKey); + } + } + + /** + * 创建令牌 + * + * @param loginUser 用户信息 + * @return 令牌 + */ + public String createToken(LoginUser loginUser) + { + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param loginUser + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) + { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) + { + refreshToken(loginUser); + } + } + + /** + * 刷新令牌有效期 + * + * @param loginUser 登录信息 + */ + public void refreshToken(LoginUser loginUser) + { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + } + + /** + * 设置用户代理信息 + * + * @param loginUser 登录信息 + */ + public void setUserAgent(LoginUser loginUser) + { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + 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 Constants.LOGIN_TOKEN_KEY + uuid; + } +} diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml new file mode 100644 index 0000000..c3ff924 --- /dev/null +++ b/ruoyi-generator/pom.xml @@ -0,0 +1,42 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + + 4.0.0 + + ruoyi-generator + + + generator代码生成 + + + + + + + org.apache.velocity + velocity + + + + + 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..6dfe5e3 --- /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 = "/{talbleId}") + public AjaxResult getInfo(@PathVariable Long talbleId) + { + GenTable table = genTableService.selectGenTableById(talbleId); + List tables = genTableService.selectGenTableAll(); + List list = genTableColumnService.selectGenTableColumnListByTableId(talbleId); + Map map = new HashMap(); + map.put("info", table); + map.put("rows", list); + map.put("tables", tables); + return AjaxResult.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/{talbleId}") + 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 AjaxResult.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 AjaxResult.success(); + } + + /** + * 删除代码生成 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:remove')") + @Log(title = "代码生成", businessType = BusinessType.DELETE) + @DeleteMapping("/{tableIds}") + public AjaxResult remove(@PathVariable Long[] tableIds) + { + genTableService.deleteGenTableByIds(tableIds); + return AjaxResult.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 AjaxResult.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 AjaxResult.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 AjaxResult.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..499da03 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -0,0 +1,500 @@ +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.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.fastjson.JSON; +import com.alibaba.fastjson.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(); + List tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); + + 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 -> { + if (!tableColumnNames.contains(column.getColumnName())) + { + GenUtils.initColumnField(column, table); + 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 = JSONObject.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 = JSONObject.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..06c6821 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -0,0 +1,258 @@ +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); + + 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(); + String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength); + return moduleName; + } + + /** + * 获取业务名 + * + * @param tableName 表名 + * @return 业务名 + */ + public static String getBusinessName(String tableName) + { + int lastIndex = tableName.lastIndexOf("_"); + int nameLength = tableName.length(); + String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength); + return businessName; + } + + /** + * 表名转换成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..32452b8 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java @@ -0,0 +1,35 @@ +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("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + // 定义字符集 + p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); + p.setProperty(Velocity.OUTPUT_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..4472928 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -0,0 +1,362 @@ +package com.ruoyi.generator.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import org.apache.velocity.VelocityContext; +import com.alibaba.fastjson.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); + 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 = JSONObject.parseObject(options); + String parentMenuId = getParentMenuId(paramsObj); + context.put("parentMenuId", parentMenuId); + } + + public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSONObject.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("."); + String basePackage = StringUtils.substring(packageName, 0, lastIndex); + return basePackage; + } + + /** + * 根据列类型获取导入包 + * + * @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 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 = JSONObject.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..89e75bd --- /dev/null +++ b/ruoyi-generator/src/main/resources/generator.yml @@ -0,0 +1,10 @@ +# 代码生成 +gen: + # 作者 + author: yinzhiying + # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool + packageName: com.ruoyi.segchk + # 自动去除表前缀,默认是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..5fa790f --- /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..3162379 --- /dev/null +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..56ff5e6 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -0,0 +1,114 @@ +package ${packageName}.controller; + +import java.util.List; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import ${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 AjaxResult.success(list); + } +#end + + /** + * 导出${functionName}列表 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')") + @Log(title = "${functionName}", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); + return util.exportExcel(list, "${functionName}数据"); + } + + /** + * 获取${functionName}详细信息 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')") + @GetMapping(value = "/{${pkColumn.javaField}}") + public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) + { + return AjaxResult.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..42d015d --- /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${pkColumn.capJavaField}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..75105ce --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -0,0 +1,166 @@ +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 结果 + */ + @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..296d41a --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/js/api.js.vm @@ -0,0 +1,53 @@ +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' + }) +} + +// 导出${functionName} +export function export${BusinessName}(query) { + return request({ + url: '/${moduleName}/${businessName}/export', + method: 'get', + params: query + }) +} \ No newline at end of file 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..dc1fb2b --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -0,0 +1,503 @@ + + + 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..5a3394b --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -0,0 +1,607 @@ + + + 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..0895aee --- /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($velocityCount != $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($velocityCount != $subTable.columns.size()),#end#end) values + + (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($velocityCount != $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..d7167ed --- /dev/null +++ b/ruoyi-quartz/pom.xml @@ -0,0 +1,42 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + + 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..58c69bc --- /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; + +/** + * 定时任务配置 + * + * @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.quartz.impl.jdbcjobstore.JobStoreTX"); + // 集群配置 + 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..b03ceb8 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java @@ -0,0 +1,167 @@ +package com.ruoyi.quartz.controller; + +import java.util.List; +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; + +/** + * 调度任务信息操作处理 + * + * @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) + @GetMapping("/export") + public AjaxResult export(SysJob sysJob) + { + List list = jobService.selectJobList(sysJob); + ExcelUtil util = new ExcelUtil(SysJob.class); + return util.exportExcel(list, "定时任务"); + } + + /** + * 获取定时任务详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobId}") + public AjaxResult getInfo(@PathVariable("jobId") Long jobId) + { + return AjaxResult.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.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); + } + 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.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); + } + 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 + { + jobService.run(job); + return AjaxResult.success(); + } + + /** + * 删除定时任务 + */ + @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 AjaxResult.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..b1f8204 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java @@ -0,0 +1,90 @@ +package com.ruoyi.quartz.controller; + +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.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) + @GetMapping("/export") + public AjaxResult export(SysJobLog sysJobLog) + { + List list = jobLogService.selectJobLogList(sysJobLog); + ExcelUtil util = new ExcelUtil(SysJobLog.class); + return util.exportExcel(list, "调度日志"); + } + + /** + * 根据调度编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long jobLogId) + { + return AjaxResult.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 AjaxResult.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..6d62661 --- /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 void 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..57a5243 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java @@ -0,0 +1,254 @@ +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 + 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 + 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 + 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 + public void deleteJobByIds(Long[] jobIds) throws SchedulerException + { + for (Long jobId : jobIds) + { + SysJob job = jobMapper.selectJobById(jobId); + deleteJob(job); + } + } + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + */ + @Override + @Transactional + 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 + public void run(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + SysJob properties = selectJobById(job.getJobId()); + // 参数 + JobDataMap dataMap = new JobDataMap(); + dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); + scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap); + } + + /** + * 新增任务 + * + * @param job 调度信息 调度信息 + */ + @Override + @Transactional + 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 + 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/task/SegchkTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/SegchkTask.java new file mode 100644 index 0000000..97177ad --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/SegchkTask.java @@ -0,0 +1,28 @@ +package com.ruoyi.quartz.task; + +import com.ruoyi.common.utils.StringUtils; +import org.springframework.stereotype.Component; + +/** + * 定时任务调度测试 + * + * @author ruoyi + */ +@Component("SegchkTask") +public class SegchkTask +{ + 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..40a19bd --- /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).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().getDeclaredMethod(methodName, getMethodParamsType(methodParams)); + method.invoke(bean, getMethodParamsValue(methodParams)); + } + else + { + Method method = bean.getClass().getDeclaredMethod(methodName); + method.invoke(bean); + } + } + + /** + * 校验是否为为class包名 + * + * @param str 名称 + * @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.contains(str, "'")) + { + classs.add(new Object[] { StringUtils.replace(str, "'", ""), String.class }); + } + // boolean布尔类型,等于true或者false + else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) + { + classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + } + // long长整形,包含L + else if (StringUtils.containsIgnoreCase(str, "L")) + { + classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class }); + } + // double浮点类型,包含D + else if (StringUtils.containsIgnoreCase(str, "D")) + { + classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), 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..7f4213f --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java @@ -0,0 +1,113 @@ +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.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.exception.job.TaskException.Code; +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)); + } + + 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); + } + } +} 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-segchk-web/pom.xml b/ruoyi-segchk-web/pom.xml new file mode 100644 index 0000000..3261d3c --- /dev/null +++ b/ruoyi-segchk-web/pom.xml @@ -0,0 +1,141 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + 4.0.0 + jar + ruoyi-segchk-web + + + 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-segchk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + false + ${project.artifactId} + + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/docker/Dockerfile b/ruoyi-segchk-web/src/main/docker/Dockerfile new file mode 100644 index 0000000..184bcc2 --- /dev/null +++ b/ruoyi-segchk-web/src/main/docker/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8-jre +VOLUME /tmp +ADD lecshop_web_applets-3.0.0-SNAPSHOT.jar app.jar +ENTRYPOINT ["java","-Duser.timezone=GMT+08","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=prod"] \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/AppletsAppApplication.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/AppletsAppApplication.java new file mode 100644 index 0000000..a92a839 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/AppletsAppApplication.java @@ -0,0 +1,83 @@ +package com.ruoyi; + + +import com.ruoyi.util.QrCodeController; +import com.ruoyi.common.utils.SnowflakeIdWorker; +import com.ruoyi.util.RedisCacheErrorHandler; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Created by 魔金商城 on 2019/5/1. + * 小程序app后端启动类 + */ +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@EnableTransactionManagement +public class AppletsAppApplication { + + public static void main(String[] args) throws UnknownHostException { + System.out.println("start-------------"); + // SpringApplication.run(MallPortalApplication.class, args); + ConfigurableApplicationContext application = SpringApplication.run(AppletsAppApplication.class, args); + Environment env = application.getEnvironment(); + String ip = InetAddress.getLocalHost().getHostAddress(); + String port = env.getProperty("server.port"); + + System.out.println("\n----------------------------------------------------------\n\t" + + "Application mallplus-Boot is running! Access URLs:\n\t" + + "Local: \t\thttp://localhost:" + port + "/\n\t" + + "External: \thttp://" + ip + ":" + port + "/\n\t" + + "swagger-ui: \thttp://" + ip + ":" + port + "/swagger-ui.html\n\t" + + "https://gitee.com/zscat/mallplus/wikis/pages/preview?sort_id=2168368&doc_id=326093"+ + "-----------------页面请部署 mallplus-admin-web-----------------------------------------"); + } + /** + * redis 异常处理 + */ + @Bean + public CacheErrorHandler errorHandler() { + return new RedisCacheErrorHandler(); + } + + /** + * 序列号生成器 + */ + @Bean + public SnowflakeIdWorker snowflakeIdWorker() { + SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 1); + return snowflakeIdWorker; + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); // 允许cookies跨域 + config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin + config.addAllowedHeader("*");// #允许访问的头信息,*表示全部 + config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 + config.addAllowedMethod("OPTIONS");// 允许提交请求的方法,*表示全部允许 + config.addAllowedMethod("HEAD"); + config.addAllowedMethod("GET");// 允许Get的请求方法 + config.addAllowedMethod("PUT"); + config.addAllowedMethod("POST"); + config.addAllowedMethod("DELETE"); + config.addAllowedMethod("PATCH"); + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } + + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/AppletsLoginUtils.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/AppletsLoginUtils.java new file mode 100644 index 0000000..4b2bbfd --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/AppletsLoginUtils.java @@ -0,0 +1,97 @@ +package com.ruoyi.appletsutil; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.interceptor.AuthorityInterceptor; +import com.ruoyi.util.Claims; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.Objects; + +/** + * 小程序登录工具类 + * + * @author SK + * @since 2018/6/13 + */ +public class AppletsLoginUtils { + private static AppletsLoginUtils ourInstance = new AppletsLoginUtils(); + + private static final Logger log = LoggerFactory.getLogger(AppletsLoginUtils.class); + + private AppletsLoginUtils() { + } + + public static AppletsLoginUtils getInstance() { + return ourInstance; + } + + /** + * 获得用户id + * + * @return 返回用户id + */ + public long getCustomerId(HttpServletRequest request) { + long customerId = 0; + if (!ObjectUtils.isEmpty(getClaims(getToken(request)))) { + customerId = getClaims(getToken(request)).getUserId(); + } + return customerId; + } + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + log.debug("request.header--->{}", request.getHeaderNames().toString()); + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + return authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); + } + /** + * 获取openId + * + * @return 返回openId + */ + public String getOpenId(HttpServletRequest request) { + return ((Claims) request.getAttribute("claims")).getOpenId(); + } + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + String claims = SpringUtils.getBean(RedisCache.class).getCacheObject(token); + return StringUtils.isEmpty(claims) ? null : JSONObject.parseObject(claims, Claims.class); + } + /** + * 获取unionId + * + * @return 返回unionId + */ + public String getUnionId(HttpServletRequest request) { + return ((Claims) request.getAttribute("claims")).getUnionId(); + } + + /** + * 获取小程序凭证实体 + * + * @return 小程序凭证实体 + */ + public Claims getClaims(HttpServletRequest request) { + return ((Claims) request.getAttribute("claims")); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/BaseResponse.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/BaseResponse.java new file mode 100644 index 0000000..1976a13 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/BaseResponse.java @@ -0,0 +1,56 @@ +package com.ruoyi.appletsutil; + + +import com.ruoyi.util.md5.MessageSourceUtil; + +import java.io.Serializable; + +/** + * 基础返回 + * Created by 魔金商城 on 17/7/10. + */ +public class BaseResponse implements Serializable { + + /** + * 结果码 + */ + private String code; + /** + * 消息内容 + */ + private String message; + + public BaseResponse(String code) { + this.code = code; + this.message = MessageSourceUtil.getMessage(code); + } + + public BaseResponse(String code, String message) { + this.code = code; + this.message = message; + } + + public static BaseResponse SUCCESSFUL() { + return new BaseResponse(ResultCode.SUCCESSFUL); + } + + public static BaseResponse FAILED() { + return new BaseResponse(ResultCode.FAILED); + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ErrorController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ErrorController.java new file mode 100644 index 0000000..fa84563 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ErrorController.java @@ -0,0 +1,39 @@ +package com.ruoyi.appletsutil; + + +import com.ruoyi.common.annotation.UnAuth; +import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * Created by 魔金商城 on 2019/5/25. + * 错误控制器 + */ +@RestController +public class ErrorController extends AbstractErrorController { + + /** + * 错误地址 + */ + private static final String ERROR_PATH = "/error"; + + public ErrorController(ErrorAttributes errorAttributes) { + super(errorAttributes); + } + + @Override + public String getErrorPath() { + return ERROR_PATH; + } + + @RequestMapping(ERROR_PATH) + @UnAuth + public Map handleError(HttpServletRequest request) { + return getErrorAttributes(request, true); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/GlobalWebExceptionHandler.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/GlobalWebExceptionHandler.java new file mode 100644 index 0000000..723c041 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/GlobalWebExceptionHandler.java @@ -0,0 +1,59 @@ +package com.ruoyi.appletsutil; + +import com.ruoyi.common.exception.ServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import javax.servlet.http.HttpServletRequest; + +/** + * Created by 魔金商城 on 17/7/10. + * 全局异常 + */ +@ControllerAdvice +public class GlobalWebExceptionHandler { + + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(GlobalWebExceptionHandler.class); + + /** + * 未认证异常(有可能是未关联用户 也有可能是微信未授权根据返回码判断) + */ + @ResponseStatus(HttpStatus.UNAUTHORIZED) + @ExceptionHandler(UnAuthorizedException.class) + @ResponseBody + public BaseResponse signatureExceptionHandler(HttpServletRequest request, UnAuthorizedException ex) { + logger.error("do [{}] on [{}] failed. exMsg:{}", request.getMethod(), request.getRequestURL(), + ex.getLocalizedMessage()); + logger.error("queryString:{}, parameterMap: {}", request.getQueryString(), request.getParameterMap(), ex); + + return new BaseResponse(ex.getErrorCode(), ex.getLocalizedMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(value = ServiceException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public BaseResponse serviceExceptionHandler(HttpServletRequest request, ServiceException ex) throws Exception { + if (AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class) != null) + throw ex; + + logger.error("do [{}] on [{}] failed. exMsg:{}", request.getMethod(), request.getRequestURL(), + ex.getLocalizedMessage()); + if (logger.isDebugEnabled()) { + logger.error("queryString:{}, parameterMap: {}", request.getQueryString(), request.getParameterMap(), ex); + } + + return new BaseResponse(ex.getMessage(), ex.getLocalizedMessage()); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ResultCode.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ResultCode.java new file mode 100644 index 0000000..9855a31 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/ResultCode.java @@ -0,0 +1,34 @@ +package com.ruoyi.appletsutil; + +/** + * Created by 魔金商城 on 17/7/10. + * 结果返回吗 + */ +public interface ResultCode { + + /** + * 操作成功; + */ + String SUCCESSFUL = "R-00000"; + + /** + * 操作失败; + */ + String FAILED = "R-00001"; + + /** + * 微信未授权 + */ + String WX_NOT_AUTHORIZED = "R-00002"; + + /** + * 微信未关联用户 + */ + String WX_NOT_LINKD = "R-00003"; + + /** + * 小程序账号已绑定错误 + */ + String WX_ALREADY_BIND_ERROR = "R-00004"; + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/UnAuthorizedException.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/UnAuthorizedException.java new file mode 100644 index 0000000..15b2018 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/appletsutil/UnAuthorizedException.java @@ -0,0 +1,33 @@ +package com.ruoyi.appletsutil; + +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.util.md5.MessageSourceUtil; + +/** + * Created by 魔金商城 on 2018/6/13. + * 微信小程序未授权异常 + */ +public class UnAuthorizedException extends ServiceException { + + /** + * 错误code + */ + private String errorCode; + + public UnAuthorizedException(String errorCode) { + this(errorCode, MessageSourceUtil.getMessage(errorCode)); + } + + public UnAuthorizedException(String errorCode, String message) { + super(message == null ? errorCode : message); + this.errorCode = errorCode; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/config/SecurityConfig.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/config/SecurityConfig.java new file mode 100644 index 0000000..92fb81e --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/config/SecurityConfig.java @@ -0,0 +1,94 @@ +package com.ruoyi.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * spring security配置 + * + * @author ruoyi + */ +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + + /** + * 解决 无法直接注入 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 | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * + * @ss.hasPermi | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + httpSecurity + // CRSF禁用,因为不使用session + .csrf().disable() + + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 验证码captchaImage 允许匿名访问 + .antMatchers("/login", "/captchaImage", "/baseinfoset","/infoset/**","/aliyun/oss/**").anonymous() + .antMatchers( + HttpMethod.GET, + "/*.html", + "/**/*.html", + "/**/*.css", + "/**/*.js" + ).permitAll() + .antMatchers("/**/**").anonymous() + .antMatchers("/common/download**").anonymous() + .antMatchers("/common/download/resource**").anonymous() + .antMatchers("/swagger-ui.html").anonymous() + .antMatchers("/swagger-resources/**").anonymous() + .antMatchers("/webjars/**").anonymous() + .antMatchers("/*/api-docs").anonymous() + .antMatchers("/druid/**").anonymous() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + + } + + + /** + * 强散列哈希加密实现 + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/config/WebConfigurer.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/config/WebConfigurer.java new file mode 100644 index 0000000..f85642c --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/config/WebConfigurer.java @@ -0,0 +1,26 @@ +package com.ruoyi.config; + +import com.ruoyi.interceptor.AuthorityInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Created by 魔金商城 on 2019/5/13. + * 拦截器配置 + */ +@Configuration +public class WebConfigurer implements WebMvcConfigurer { + + /** + * 注入登录拦截器 + */ + @Autowired + private AuthorityInterceptor authorityInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authorityInterceptor).excludePathPatterns("/**/**", "/v2/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**"); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/interceptor/AuthorityInterceptor.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/interceptor/AuthorityInterceptor.java new file mode 100644 index 0000000..ca4d164 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/interceptor/AuthorityInterceptor.java @@ -0,0 +1,170 @@ +package com.ruoyi.interceptor; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.appletsutil.AppletsLoginUtils; +import com.ruoyi.util.Claims; +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import com.ruoyi.member.service.WeChatCustomerLinkService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; + +/** + * Created by 魔金商城 on 2018/6/13. + * 访问拦截器 + */ +@Component +public class AuthorityInterceptor extends HandlerInterceptorAdapter { + + private static final Logger log = LoggerFactory.getLogger(AuthorityInterceptor.class); + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + /** + * 注入微信用户关联服务 + */ + @Autowired + @Lazy + private WeChatCustomerLinkService weChatCustomerLinkService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String requestType = ((HttpServletRequest) request).getMethod(); + String fullUrl = ((HttpServletRequest) request).getRequestURL().toString(); + log.debug("fullUrl--->{}", fullUrl); + int startIntercept = fullUrl.replace("//", "a").indexOf("/") + 1; + String interfaceName = fullUrl.substring(startIntercept, fullUrl.length()); + if (!"OPTIONS".equals(requestType) && !interfaceName.contains("webjars") + && !interfaceName.contains("api-docs")) { + log.info(formMapKey(AppletsLoginUtils.getInstance().getCustomerId(request), fullUrl, requestType, + IpUtils.getIpAddr((HttpServletRequest) request), null, null) + + ",\"cost\":\""); + } + + // 如果不需要拦截 则直接返回 + if (!isNeedFilter(handler)) { + log.debug("Donot need authority....."); + return true; + } + + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer ")) { + log.info("AuthorityInterceptor preHandle fail...."); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + + // 获得凭证 + Claims claims = getAppletsClaimsFromRedis(authHeader.substring(7)); + + // 没有凭证 直接返回 + if (Objects.isNull(claims)) { + log.info("AuthorityInterceptor preHandle fail...."); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + + // 校验有没有uid 如果没有uid 则直接返回 + if (!claims.hasCustomerId()) { + log.error("applets has not authorized"); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + + // 如果没有会员id 则从数据库查询 是否有会员id + /*if (!claims.hasCustomerId()) { + // 小程序没有关联用户则提示用户去关联用户 + WeChatCustomerLink weChatCustomerLink = queryWeChatCustomerLinkByUnionId(claims.getUnionId()); + if (Objects.isNull(weChatCustomerLink)) { + log.error("applets has not linked member...."); + throw new UnAuthorizedException(ResultCode.WX_NOT_LINKD); + } else { + log.info("applets has unionId and has member...."); + // 将凭证信息返回redis + putClaimsToRedis(weChatCustomerLink, claims, authHeader.substring(7)); + //如果没有小程序的openId,则更新关联信息 + if (!weChatCustomerLink.hasAppletOpenId()) { + weChatCustomerLink.setAppletOpenId(claims.getOpenId()); + weChatCustomerLinkService.updateWeChatCustomerLink(weChatCustomerLink); + } + } + }*/ + + request.setAttribute("claims", claims); + + return true; + } + + private String formMapKey(Object userId, String mothedName, String requestType, + String ip, String params, String token) { + return "\"time\"" + ":\"" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) + + "\",\"name\"" + ":\"" + mothedName + "\",\"uid\":\"" + userId + + "\",\"type\":\"" + requestType + "\",\"ip\":\"" + ip + + "\",\"token\":\"" + token + "\",\"params\":\"" + params + "\""; + } + /** + * 将凭证放入redis + * + * @param weChatCustomerLink 会员和小程序的绑定关系 + * @param claims 凭证 + * @param token token + */ + /*private void putClaimsToRedis(WeChatCustomerLink weChatCustomerLink, Claims claims, String token) { + claims.setUserId(weChatCustomerLink.); + redisService.putToRedis(token, JSON.toJSONString(claims)); + }*/ + + /** + * 根据unionId查询会员和小程序的绑定关系 + * + * @param unionId 小程序唯一id + * @return 返回会员和小程序的绑定关系 + */ + private WeChatCustomerLink queryWeChatCustomerLinkByUnionId(String unionId) { + return weChatCustomerLinkService.queryWeChatCustomerLinkByUnionId(unionId); + } + + + /** + * 根据token从redis 获取uid和customerId + * + * @param token token + * @return 返回uid和customerId + */ + private Claims getAppletsClaimsFromRedis(String token) { + String claims = redisService.getCacheObject(token); + return StringUtils.isEmpty(claims) ? null : JSONObject.parseObject(redisService.getCacheObject(token), Claims.class); + } + + + /** + * 判断是否需要拦截 + */ + private boolean isNeedFilter(Object handler) { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + return handlerMethod.getMethod().getAnnotation(UnAuth.class) == null; + } + return false; + } + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/login/OssController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/login/OssController.java new file mode 100644 index 0000000..e3044a3 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/login/OssController.java @@ -0,0 +1,128 @@ +package com.ruoyi.login; + + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.setting.bean.OssSetting; +import com.ruoyi.setting.bean.UploadData; +import com.ruoyi.setting.service.OssService; +import com.ruoyi.util.CommonConstant; +import io.swagger.annotations.*; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.Objects; + +/** + * Oss相关操作接口 + * https://github.com/shenzhuan/mallplus on 2018/4/26. + */ +@RestController +@Api(tags = "OssController", description = "Oss管理") +@RequestMapping("/aliyun/oss") +public class OssController { + @Resource + private OssService ossService; + + + /** + * 上传图片 + * + * @param name 上传文件的name 默认为image + * @param type 上传文件的类型 默认为图片 0 图片 1 视频 + * @return 返回图片在腾讯云的地址 + * @throws Exception + */ + @PostMapping("uploadToQqOSSYun") + @ApiOperation(value = "上传图片", notes = "上传图片(不需要认证)") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "String", name = "name", value = "上传文件的name 默认为image"), + @ApiImplicitParam(paramType = "form", dataType = "String", name = "type", value = "上传文件的类型 默认为图片 0 图片 1 视频"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "返回图片在腾讯云的地址", response = String.class) + }) + public AjaxResult uploadToQqOSSYun(@RequestParam("file") MultipartFile multipartFile,MultipartHttpServletRequest request, String name, String type) throws Exception { + if (StringUtils.isEmpty(name)) { + name = "image"; + } + + // 默认上传图片 + if (StringUtils.isEmpty(type)) { + type = CommonConstant.UPLOAD_PIC; + } + if (Objects.isNull(multipartFile)) { + return AjaxResult.error(); + } + return AjaxResult.success(ossService.uploadToQqOss(Arrays.asList(UploadData.build(multipartFile.getInputStream(), multipartFile.getBytes(), multipartFile.getOriginalFilename(), type, multipartFile))).stream().findFirst().orElse("")); + } + + /** + * 上传图片 + * + * @param name 上传文件的name 默认为image + * @param type 上传文件的类型 默认为图片 0 图片 1 视频 + * @return 返回图片在阿里云的地址 + * @throws Exception + */ + @PostMapping("uploadToAliOss") + @ApiOperation(value = "上传图片", notes = "上传图片(不需要认证)") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "String", name = "name", value = "上传文件的name 默认为image"), + @ApiImplicitParam(paramType = "form", dataType = "String", name = "type", value = "上传文件的类型 默认为图片 0 图片 1 视频"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "返回图片在阿里云的地址", response = String.class) + }) + public AjaxResult uploadToOSSYun(@RequestParam("file") MultipartFile multipartFile, String name, String type) throws Exception { + if (StringUtils.isEmpty(name)) { + name = "image"; + } + + // 默认上传图片 + if (StringUtils.isEmpty(type)) { + type = CommonConstant.UPLOAD_PIC; + } + + if (Objects.isNull(multipartFile)) { + return AjaxResult.error(); + } + return AjaxResult.success(ossService.uploadToOss(Arrays.asList(UploadData.build(multipartFile.getInputStream(), multipartFile.getBytes(), multipartFile.getOriginalFilename(), type, multipartFile))).stream().findFirst().orElse("")); + } + + + /** + * 查询云存储设置 + * + * @return 云存储设置信息 + */ + @GetMapping("/oss") + @PreAuthorize("@ss.hasPermi('setting:ossSetting:list')") + @ApiOperation(value = "查询阿里云存储设置", notes = "查询阿里云存储设置(需要认证)") + @ApiResponses({ + @ApiResponse(code = 200, message = "又拍云设置信息", response = OssSetting.class) + }) + public OssSetting queryUpYunSet() { + return ossService.queryOssSetting(); + } + + /** + * 修改又拍云设置 + * + * @param ossSetting 又拍云设置信息 + * @return 成功1 否则失败 + */ + @PutMapping("/oss") + @ApiOperation(value = "修改阿里云存储设置", notes = "修改阿里云存储设置(需要认证)") + @ApiResponses({ + @ApiResponse(code = 200, message = "成功1 否则失败", response = Integer.class) + }) + public int updateOss(@RequestBody OssSetting ossSetting) { + return ossService.updateOss(ossSetting); + } + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/login/SegChkLoginController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/login/SegChkLoginController.java new file mode 100644 index 0000000..08215ba --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/login/SegChkLoginController.java @@ -0,0 +1,759 @@ +package com.ruoyi.login; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.segchk.domain.SegchkUserWebReq; +import com.ruoyi.util.*; +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.SnowflakeIdWorker; +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.member.service.*; +import com.ruoyi.member.vo.BindParams; +import com.ruoyi.setting.bean.WechatPaySet; +import com.ruoyi.setting.service.ILsPaySettingService; +import com.ruoyi.util.bean.SegUserProfile; +import com.ruoyi.util.bean.UserInfoProfile; +import io.swagger.annotations.*; +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.Controller; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; +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.ResponseBody; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * 登录控制器 + * + * @author SK + * @since 2018/6/13 + */ +@Controller +@Api(description = "登录接口") +//@RequestMapping("/default/login") +public class SegChkLoginController { + + private static final Logger logger = LoggerFactory.getLogger(SegChkLoginController.class); + /** + * 注入微信小程序登录服务 + */ +// @Autowired +// private WeChatAppletLoginService weChatAppletLoginService; + + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + /** + * jwt密钥 + */ + @Value("${token.secret}") + private String jwtSecretKey; + +// 登录超时时长,单位天,-1永久有效 + @Value("${yzytest.login.loginexpire:#{1}}") + private Integer loginexpire; + + /** + * 注入登录处理service + */ + @Resource(name = "loginService") + private LoginService loginService; + + /** + * 注入注册服务 + */ + @Autowired + private RegisterService registerService; + + /** + * 注入注册聚合服务 + */ + @Autowired + private RegisterServiceApi registerServiceApi; + + /** + * 注入微信用户关联服务 + */ + @Autowired + private WeChatCustomerLinkService weChatCustomerLinkService; + /** + * 注入随机数生成器 + */ + @Autowired + private SnowflakeIdWorker snowflakeIdWorker; + /** + * 注入支付设置服务 + */ + @Autowired + private ILsPaySettingService paySetService; + /** + * 会员登录 + * + * + * @return -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + */ + @PostMapping("/login") + @UnAuth + @ResponseBody + @ApiOperation(value = "会员登录", notes = "会员登录(不需要认证)") + public AjaxResult login(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) { + Long userId = 0L; + if(!ObjectUtils.isEmpty(segchkUserWebReq) && "999999".equals(segchkUserWebReq.getRemark())){ + return loginService.login(segchkUserWebReq); + } +// Object cacheObject = redisService.getCacheObject(String.format("%s", "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUipPTc5ILMnJT8")); +// logger.warn(ObjectUtils.nullSafeToString(cacheObject)); + try { + if (ObjectUtils.isEmpty(getClaims(getToken(request)))) { +// 如果用户未登录,则要求用户使用手机号登录注册 + userId = getClaims(getToken(request)).getUserId(); + return AjaxResult.error(300, "请先登录注册"); + } + } + catch (Exception e){ + return AjaxResult.error(300, "请先登录注册"); + } + + Claims claims = getClaims(getToken(request)); + SegchkUserWebReq segchkUserWebReq1 = new SegchkUserWebReq(); + segchkUserWebReq1.setUserId(claims.getUserId()); + segchkUserWebReq1.setProviderId(claims.getProviderId()); + segchkUserWebReq1.setUserLevel(claims.getUserLevel()); + + AjaxResult login = loginService.login(segchkUserWebReq1); + login.put("token", getToken(request)); + + return login; + } + + /** + * 发送短信验证码 + * r + * + * @param mobile 手机号码 + * @return 0 成功 1 失败 -1 手机号码已经存在 + */ + @UnAuth + @RequestMapping(value = "/sendmobilecode") + @ResponseBody + @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "mobile", value = "手机号码"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "0 成功 1 失败 -1 手机号码已经存在", response = Integer.class) + }) + public AjaxResult sendSmsCode(String mobile) { +// 发送短信验证码 + logger.debug("sendmobilecode ---> phone:{}", mobile); + int ret = registerService.sendRegisterSmsCodeFortest(mobile, code -> redisService.setCacheObject(String.format("%s_%s", CommonConstant.APPLET_REGISTER_CODE_KEY, mobile), code, 5, TimeUnit.MINUTES)); + + if(ret != 0 ){ + return AjaxResult.error("500", "验证码发送失败,请稍后重试"); + } + return AjaxResult.success("验证码发送成功"); + + } + + /** + * 发送短信验证码测试 + * r + * + * @param mobile 手机号码 + * @return 0 成功 1 失败 -1 手机号码已经存在 + */ + @UnAuth + @RequestMapping(value = "/sendmobilecodetest") + @ResponseBody + @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "mobile", value = "手机号码"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "0 成功 1 失败 -1 手机号码已经存在", response = Integer.class) + }) + public AjaxResult sendmobilecodetest(String mobile) { +// 发送短信验证码 + logger.debug("sendmobilecode ---> phone:{}", mobile); + int ret = registerService.sendRegisterSmsCodeFortest(mobile, code -> redisService.setCacheObject(String.format("%s_%s", CommonConstant.SMS_TEST_KEY, mobile), code, 5, TimeUnit.MINUTES)); + + if(ret != 0 ){ + return AjaxResult.error("500", "验证码发送失败,请稍后重试"); + } + return AjaxResult.success("验证码发送成功"); + + } + + /** + * 用户注册 + * + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + @UnAuth + @RequestMapping("/register") + @ResponseBody + @ApiOperation(value = "用户注册", notes = "用户注册(不需要认证)", httpMethod = "POST") + + @ApiResponses({ + @ApiResponse(code = 200, message = "-1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在", response = Integer.class) + }) + public AjaxResult register(@RequestBody SegChkLoginController.RegisterData registerData) { + AjaxResult res = null; + logger.debug("register with---{}", registerData.toString()); + try { + res = registerServiceApi.registerCustomer(registerData.getMobile(), registerData.getCode() + , redisService.getCacheObject(String.format("%s_%s", CommonConstant.APPLET_REGISTER_CODE_KEY, registerData.getMobile())), registerData.getRecommendId(), registerData.getRecommendLevel(), registerData.getProviderId(), registerData.getRemark()); + + } catch (Exception e) { + e.printStackTrace(); + return res; + } +// 如果返回结果中不存在token,说明没有进行微信绑定 + return res; + } + + @UnAuth + @ResponseBody + @RequestMapping("/bindaccount") + @ApiOperation(value = "小程序获取登录信息", notes = "小程序获取登录信息(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "code", value = "用户登录凭证"), + }) + public AjaxResult bindaccount(@RequestBody BindParams bindParams , HttpServletRequest request) { + logger.debug("bindaccount with: {}", bindParams.toString()); + WechatPaySet wechatAppletPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + WechatSetting wechatSetting = new WechatSetting(); + if(!StringUtils.isEmpty(bindParams.getRemark())){ + wechatSetting.setType(999999); + } + wechatSetting.setAppId(wechatAppletPaySet.getAppId()); +// wechatSetting.setAppId(appId); + wechatSetting.setAppSecret(wechatAppletPaySet.getAppSecret()); +// wechatSetting.setAppSecret(appSecrt); + if (!wechatSetting.checkAppletOAuthParams()) { +// log.error("getLoginInfo fail:checkAppletOAuthParams fail"); + return AjaxResult.error("getLoginInfo fail:checkAppletOAuthParams fail"); + } + + WeChatAppletLoginResponse weChatAppletLoginResponse = WeChatAppletUtils.getLoginInfo(bindParams.getCode(), wechatSetting); + if (Objects.isNull(weChatAppletLoginResponse)) { +// log.error("getLoginInfo fail: getLoginInfo fail"); + return AjaxResult.error("获取微信信息失败,请联系客服人员"); + } + Claims claims = null; + try { + claims = getClaims(getToken(request)); + } + catch (Exception e) { + e.printStackTrace(); + claims = null; + } + SegchkUserWechat segchkUserWechat = new SegchkUserWechat(); + segchkUserWechat.setUserId(Long.valueOf(bindParams.getUserId())); + segchkUserWechat.setOpenid(weChatAppletLoginResponse.getOpenid()); + segchkUserWechat.setUnionId(weChatAppletLoginResponse.getUnionid()); + segchkUserWechat.setProviderId(Long.valueOf(bindParams.getProviderId())); + segchkUserWechat.setNickName(bindParams.getNickName()); + + segchkUserWechat.setIconUrl(bindParams.getAvatar()); +// 将用户与微信openid绑定 + int ret = weChatCustomerLinkService.addSegchkUserWechat(segchkUserWechat, bindParams.getUserLevel()); + if(ret < 1){ + return AjaxResult.error(500, "微信绑定失败!"); + } +// 产生token + String token = registerServiceApi.createToke(CommonConstant.APPLET_LOGIN_KEY, Long.valueOf(bindParams.getUserId()), Long.valueOf(bindParams.getProviderId()), Integer.valueOf(bindParams.getUserLevel())); +// String token = snowflakeIdWorker.nextId()+""; + if(claims == null) { + claims = new Claims(); + claims.setUserId(Long.valueOf(bindParams.getUserId())); + claims.setOpenId(weChatAppletLoginResponse.getOpenid()); + claims.setProviderId(Long.valueOf(bindParams.getProviderId())); + claims.setUserLevel(Integer.valueOf(bindParams.getUserLevel())); + } +// 将用户的token进行缓存 + if(loginexpire == -1) { + redisService.setCacheObject(token, claims); + } + else{ + redisService.setCacheObject(token, claims, loginexpire, TimeUnit.HOURS); + } + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_BIND_OPENID).append("-").append(token); + redisService.setCacheObject(sb.toString(), segchkUserWechat, 7200, TimeUnit.SECONDS); + + +// 测试,解析getuserprofile返回结果 + + try { + if(!ObjectUtils.isEmpty(bindParams.getProfileRes())) { + SegUserProfile segUserProfile = JSON.parseObject(bindParams.getProfileRes(), SegUserProfile.class); + logger.info("getUserProfile info is: ({})", segUserProfile.toString()); + UserInfoProfile userInfoProfile = JSON.parseObject(segUserProfile.getUserInfo(), UserInfoProfile.class); + logger.info("getUserInfo from userProfile is: ({})", userInfoProfile.toString()); + String decryptres = WeChatAppletUtils.getUserInfoFromUserProfile(weChatAppletLoginResponse.getSession_key(), segUserProfile); + logger.debug("getUserProfile decrypt res: ({})", decryptres); + } + } catch (Exception e){ + logger.error("getUserProfile wrong! {}", e.getMessage()); + e.printStackTrace(); + } + + return AjaxResult.success("绑定成功", token); + } + + /** + * 用户注册实体 + */ + @ApiModel(description = "用户注册实体") + private static class RegisterData extends BaseEntity { + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码") + private String mobile; + + + /** + * 手机验证码 + */ + @ApiModelProperty(value = "手机验证码") + private String code; + + /** + * 推荐码 + */ + @ApiModelProperty(value = "推荐码") + private String recommendId; + + /** + * 推荐码 + */ + @ApiModelProperty(value = "推荐人角色") + private String recommendLevel; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private String providerId; + + /** + * 授权code + */ + @ApiModelProperty(value = "授权code") + private String wechatCode; + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getRecommendId() { + return recommendId; + } + + public void setRecommendId(String recommendId) { + this.recommendId = recommendId; + } + + public String getRecommendLevel() { + return recommendLevel; + } + + public void setRecommendLevel(String recommendLevel) { + this.recommendLevel = recommendLevel; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public String getWechatCode() { + return wechatCode; + } + + public void setWechatCode(String wechatCode) { + this.wechatCode = wechatCode; + } + + @Override + public String toString() { + return "RegisterData{" + + "mobile='" + mobile + '\'' + + ", code='" + code + '\'' + + ", recommendId='" + recommendId + '\'' + + ", recommendLevel='" + recommendLevel + '\'' + + ", providerId='" + providerId + '\'' + + ", wechatCode='" + wechatCode + '\'' + + '}'; + } + } + + /** + * 注册登录 + * + * @param loginParams 登录参数 + * @return -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + */ + /*@PostMapping("/logout") + @UnAuth + @ResponseBody + @ApiOperation(value = "会员登录", notes = "会员登录(不需要认证)") + @ApiResponses({ + @ApiResponse(code = 200, message = "result: -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 token:放登录成功后的token", response = Map.class) + }) + public AjaxResult logout(@RequestBody LoginParams loginParams, HttpServletRequest request)*/ + + /** + * 会员登录 + * + * @param loginParams 登录参数 + * @return -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + */ + /*@PostMapping("/logout") + @UnAuth + @ResponseBody + @ApiOperation(value = "会员登录", notes = "会员登录(不需要认证)") + @ApiResponses({ + @ApiResponse(code = 200, message = "result: -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 token:放登录成功后的token", response = Map.class) + }) + public AjaxResult logout(@RequestBody LoginParams loginParams, HttpServletRequest request) { + AppletLoginRedisParamResponse appletLoginRedisParamResponse = JSON.parseObject(redisService.getValue(getToken(request)),AppletLoginRedisParamResponse.class) ; + redisService.deleteObject(getToken(request)); + // redisService.deleteObject(appletLoginRedisParamResponse.); + return AjaxResult.success(); + }*/ + /** + * 小程序获取登录信息 + * + * @param 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息 + * @return 登录信息 + */ + /*@UnAuth + @ResponseBody + @RequestMapping("/getOpenId") + @ApiOperation(value = "小程序获取登录信息", notes = "小程序获取登录信息(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "code", value = "用户登录凭证"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "登录信息", response = AppletLoginInfo.class) + }) + public AjaxResult getOpenId(@RequestBody AppletLoginRedisParamResponse appletLoginRedisParamResponse , HttpServletRequest request) { + + WechatPaySet wechatAppletPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + WechatSetting wechatSetting = new WechatSetting(); + wechatSetting.setAppId(wechatAppletPaySet.getAppId()); + wechatSetting.setAppSecret(wechatAppletPaySet.getAppSecret()); + if (!wechatSetting.checkAppletOAuthParams()) { + log.error("getLoginInfo fail:checkAppletOAuthParams fail"); + return AjaxResult.error("getLoginInfo fail:checkAppletOAuthParams fail"); + } + WeChatAppletLoginResponse weChatAppletLoginResponse = WeChatAppletUtils.getLoginInfo(appletLoginRedisParamResponse.getCode(), wechatSetting); + if (Objects.isNull(weChatAppletLoginResponse)) { + log.error("getLoginInfo fail: getLoginInfo fail"); + return AjaxResult.error("getLoginInfo fail: getLoginInfo fail"); + } + UmsMember member = new UmsMember(); + member.setAppletOpenId(weChatAppletLoginResponse.getOpenid()); + long customerId = 0; + if (!ObjectUtils.isEmpty(getClaims(getToken(request)))) { + customerId = getClaims(getToken(request)).getCustomerId(); + } + member.setId(customerId); + return AjaxResult.success(memberService.updateUmsMember(member)); + }*/ + /** + * 小程序获取登录信息 + * + * @param 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息 + * @return 登录信息 + */ + /*@UnAuth + @ResponseBody + @RequestMapping("/mpWechatLogin") + @ApiOperation(value = "小程序获取登录信息", notes = "小程序获取登录信息(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "code", value = "用户登录凭证"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "登录信息", response = AppletLoginInfo.class) + }) + public AjaxResult mpWechatLogin(@RequestBody AppletLoginRedisParamResponse appletLoginRedisParamResponse , HttpServletRequest request) { + final StringBuilder sb = new StringBuilder(); + Map res = new HashMap<>(); + String token = snowflakeIdWorker.nextId() + ""; + appletLoginRedisParamResponse.setToken(token); + WechatPaySet wechatAppletPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + WechatSetting wechatSetting = new WechatSetting(); + wechatSetting.setAppId(wechatAppletPaySet.getAppId()); + wechatSetting.setAppSecret(wechatAppletPaySet.getAppSecret()); + if (!wechatSetting.checkAppletOAuthParams()) { + log.error("getLoginInfo fail:checkAppletOAuthParams fail"); + return AjaxResult.error("getLoginInfo fail:checkAppletOAuthParams fail"); + } + WeChatAppletLoginResponse weChatAppletLoginResponse = WeChatAppletUtils.getLoginInfo(appletLoginRedisParamResponse.getCode(), wechatSetting); + if (Objects.isNull(weChatAppletLoginResponse)) { + log.error("getLoginInfo fail: getLoginInfo fail"); + return AjaxResult.error("getLoginInfo fail: getLoginInfo fail"); + } + appletLoginRedisParamResponse.setSessionKey(weChatAppletLoginResponse.getSession_key()); + appletLoginRedisParamResponse.setOpenId(weChatAppletLoginResponse.getOpenid()); + UmsMember member =memberService.queryCustomerByappletOpenId(weChatAppletLoginResponse.getOpenid()); + if (member!=null){ + appletLoginRedisParamResponse.setCustomerId(member.getId()); + appletLoginRedisParamResponse.setToken(sb.toString()); + redisService.putToRedis(sb.toString(), JSON.toJSONString(appletLoginRedisParamResponse)); + // redisService.putToRedis(loginParams.getMobile(), sb.toString()); + res.put("access_token", sb.toString()); + res.put("refresh_token", sb.toString()); + res.put("member", member); + }else { + member = new UmsMember(); + member.setSource("5"); + member.setMobile("123456789"); + member.setAppletOpenId(weChatAppletLoginResponse.getOpenid()); + member.setPassword("123456"); + memberService.addCustomer(member); + redisService.putToRedis(sb.toString(), JSON.toJSONString(appletLoginRedisParamResponse)); + // redisService.putToRedis(loginParams.getMobile(), sb.toString()); + res.put("access_token", sb.toString()); + res.put("refresh_token", sb.toString()); + res.put("member", member); + } + return AjaxResult.success(res); + + }*/ + /** + * 小程序获取登录信息 + * + * @param code 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息 + * @return 登录信息 + */ + /*@UnAuth + @ResponseBody + @RequestMapping("/getlogininfo") + @ApiOperation(value = "小程序获取登录信息", notes = "小程序获取登录信息(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "code", value = "用户登录凭证"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "登录信息", response = AppletLoginInfo.class) + }) + public AppletLoginInfo getLoginInfo(String code, HttpServletRequest request) { + String unionId = null; + if (!StringUtils.isEmpty(getToken(request))) { + unionId = Objects.isNull(getClaims(getToken(request))) ? null : getClaims(getToken(request)).getUnionId(); + redisService.delValue(getToken(request)); + } + return weChatAppletLoginService.getLoginInfo(code, unionId, appletLoginRedisParamResponse -> { + redisService.putToRedis(appletLoginRedisParamResponse.getToken(), JSON.toJSONString(appletLoginRedisParamResponse)); + if (appletLoginRedisParamResponse.hasUnionId()) { + redisService.putToRedis(appletLoginRedisParamResponse.getUnionId(), appletLoginRedisParamResponse.getToken()); + } + }); + }*/ + + /** + * 处理用户信息 + * + * @param weChatAppletUserInfo 小程序用户信息实体 + * @return 登录信息 + */ + /*@UnAuth + @ResponseBody + @RequestMapping("/dealuserinfo") + @ApiOperation(value = "处理用户信息", notes = "处理用户信息(不需要认证)", httpMethod = "POST") + public AppletLoginInfo dealUserInfo(WeChatAppletUserInfo weChatAppletUserInfo, HttpServletRequest request) { + String token = getToken(request); + Claims claims = getClaims(token); + return weChatAppletLoginService.dealUserInfo(weChatAppletUserInfo, claims.getOpenId(), claims.getSessionKey(), appletLoginRedisParamResponse -> afterDealUserInfo(claims, appletLoginRedisParamResponse, token)); + }*/ + + /** + * 绑定账号 + * + * @param loginParams 登录参数 + */ + /*@RequestMapping("/bindaccount") + @ResponseBody + @UnAuth + @ApiOperation(value = "绑定账号", notes = "绑定账号(不需要认证)", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "string", name = "username", value = "用户名"), + @ApiImplicitParam(paramType = "form", dataType = "string", name = "password", value = "密码"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "返回码 -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误", response = Integer.class) + }) + public AjaxResult bindAccount(@ApiIgnore LoginParams loginParams, HttpServletRequest request) { + //回调 + loginParams.setConsumer(customer -> + alterLoginSuccess(customer.getId(), request) + ); + return AjaxResult.success(loginService.login(loginParams)); + }*/ + + + /** + * 解绑账号 + * + * @return 1成功 + */ + /*@RequestMapping("/unbindaccount") + @ResponseBody + @ApiOperation(value = "解绑账号", notes = "解绑账号(需要认证)", httpMethod = "POST") + @ApiResponses({ + @ApiResponse(code = 200, message = "1成功", response = Integer.class) + }) + public int unbindAccount(HttpServletRequest request) { + weChatAppletLoginService.unbindAccount(AppletsLoginUtils.getInstance().getCustomerId(request), AppletsLoginUtils.getInstance().getUnionId(request)); + Claims claims = AppletsLoginUtils.getInstance().getClaims(request); + claims.setCustomerId(CommonConstant.NO_CUSTOMER_ID); + redisService.putToRedis(getToken(request), JSONObject.toJSONString(claims)); + return 1; + }*/ + + + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + logger.info("getClaims fail :Authorization fail "); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + String token = authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); +// logger.warn("get toke info from {}---{}({})", authHeader, token, token.length()); + return token; + } + + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + + Object claims = redisService.getCacheObject(token); + logger.debug("getClaims---token:{} Claims:{}", token, claims); + return ObjectUtils.isEmpty(claims) ? null : (Claims) claims; + } + + private SegchkUserWechat getSegchkUserWechat(String token) { + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_BIND_OPENID).append("-").append(token); + Object segchkUserWechat = redisService.getCacheObject(sb.toString()); + + return ObjectUtils.isEmpty(segchkUserWechat) ? null : (SegchkUserWechat) segchkUserWechat; + } + + /** + * 处理小程序凭证信息 + * + * @param claims 小程序凭证实体 + * @param appletLoginRedisParamResponse 小程序redis参数返回实体 + * @param token token + */ + /*private void afterDealUserInfo(Claims claims, AppletLoginRedisParamResponse appletLoginRedisParamResponse, String token) { + if (Objects.nonNull(appletLoginRedisParamResponse)) { + claims.setCustomerId(appletLoginRedisParamResponse.getCustomerId()); + claims.setUnionId(appletLoginRedisParamResponse.getUnionId()); + redisService.putToRedis(token, JSON.toJSONString(claims)); + if (appletLoginRedisParamResponse.hasUnionId()) { + redisService.putToRedis(appletLoginRedisParamResponse.getUnionId(), token); + } + } else { + log.error("afterDealUserInfo fail:appletLoginRedisParamResponse is null"); + } + }*/ + + /** + * 登录成功后处理的事 + * + * @param customerId 用户id + */ + /*private void alterLoginSuccess(long customerId, HttpServletRequest request) { + if (!ObjectUtils.isEmpty(customerId)) { + Claims claims = getClaims(getToken(request)); + // 校验有没有uid 如果没有uid 则直接返回 + if (!claims.hasUnionId()) { + log.error("applets has not authorized"); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + //绑定账号 + try { + weChatAppletLoginService.bindAccount(claims.getOpenId(), claims.getUnionId(), customerId); + } catch (ServiceException e) { + throw e; + } catch (Exception e) { + //捕获异常,可能已经绑定过账号 + WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByUnionId(claims.getUnionId()); + if (Objects.nonNull(weChatCustomerLink)) { + customerId = weChatCustomerLink.getCustomerId(); + } else { + customerId = CommonConstant.NO_CUSTOMER_ID; + } + } + if (customerId == CommonConstant.NO_CUSTOMER_ID) { + claims.setCustomerId(customerId); + redisService.putToRedis(getToken(request), JSONObject.toJSONString(claims)); + } + } + }*/ + + /** + * token测试方法 + * + * @param token token + */ + @UnAuth + @ResponseBody + @RequestMapping("/tokentest") + @ApiOperation(value = "处理用户信息", notes = "处理用户信息(不需要认证)", httpMethod = "GET") + public AjaxResult token_test(@RequestBody String token, HttpServletRequest request) { + Object cacheObject = redisService.getCacheObject(token); + logger.warn("get token: {} for value: {}", token, cacheObject); + logger.warn("tokentest get claim: {}", getClaims(token).toString()); + return AjaxResult.success(cacheObject); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultIndexController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultIndexController.java new file mode 100644 index 0000000..f7e68cb --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultIndexController.java @@ -0,0 +1,511 @@ +package com.ruoyi.segchk; + +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.service.ISegchkStoreIndexService; +import com.ruoyi.util.Claims; +import io.swagger.annotations.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +import static com.ruoyi.common.core.domain.AjaxResult.CODE_TAG; +import static com.ruoyi.common.core.domain.AjaxResult.DATA_TAG; + +/** + * seg首页推荐商户Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/default/index") +@Api("商城开放接口") +public class SegchkDefaultIndexController extends BaseController +{ +// private static final Logger logger = LoggerFactory.getLogger(SegchkDefaultIndexController.class); + + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + + @Value("${segchk.share.title:#{卡乐分享}}") + private String shareTitle; + + @Value("${segchk.share.desc:#{卡乐无限享受}}") + private String shareDesc; + + @Value("${segchk.recommendstore.distince:#{null}}") + private BigDecimal recomDist; + + @Value("${segchk.startid:#{null}}") + private Integer startid; + + @Value("${segchk.default_district:#{110100}}") + private Long defaultDistrict; + /** + * 根据用户当前所在地市行政id,返回运营商id 尹志颖 + * { + * "adcode": 110000 + * } + */ + @UnAuth + @GetMapping("/getProviderByadcode") + @ApiOperation(value = "查询运营商id", notes = "根据用户当前位置所在行政区代码或用户选择的行政区代码") + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "Long", name = "adcode", value = "行政区代码"), + }) + @ApiResponses({ + @ApiResponse(code = 200, message = "拼团促销图片信息", response = Long.class) + }) + public AjaxResult get_provider_byadcode(Long adcode) + { + logger.debug("get_provider_byadcode with: {}", adcode); + AjaxResult ajax = new AjaxResult(); + HashMap paramsMap = new HashMap<>(); + paramsMap.put("districtId", adcode); + paramsMap.put("defaultDistrict", defaultDistrict); + HashMap provider = segchkStoreIndexService.getProvider(paramsMap); + ajax.put(CODE_TAG, 200); + PrvoiderDistrict prvoiderDistrict = new PrvoiderDistrict(); + prvoiderDistrict.setProvFlag((Integer) provider.get("provFlag")); + prvoiderDistrict.setProviderId((Long) provider.get("providerId")); + prvoiderDistrict.setPhoneNo((String) provider.get("phoneNo")); + prvoiderDistrict.setWechatId((String) provider.get("wechatId")); + if(prvoiderDistrict.getProvFlag() == 1){ +// 说明返回默认地区运营商 + prvoiderDistrict.setDistName(String.valueOf(provider.get("provName"))); + } + ajax.put(DATA_TAG, prvoiderDistrict); + logger.debug("getProviderByadcode res --- {}", ajax.toString()); + return ajax; + } + + /** + * 搜索商户,根据名称,标签,充值卡等 尹志颖 + * { + * { + * "providerId": 0,* + * "sortType": 0,* + * "storeId": 0, + * "storeName": "demoData",* + * "lableId": 0, + * "lableName": "demoData",* + * "typeId": 0, + * "userLon": 114.123456,* + * "userLat": 43.123456* + * } + * } + */ + @UnAuth + @RequestMapping(value = "/StoreSearch",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "搜索商户", notes = "搜索商户(不需要认证)", httpMethod = "POST") + public TableDataInfo store_search(@RequestBody SegchkStoreWebReq segchkStoreWebReq) + { + logger.debug("store_search with: {}", segchkStoreWebReq.toString()); + startPage(); + segchkStoreWebReq.setUserDist(recomDist); + List list = segchkStoreIndexService.selectSegchkStoreSearch(segchkStoreWebReq); + return getDataTable(list); + } + + /** + * 查询seg标签列表 尹志颖 + * { + * "providerId": 4 + * } + */ + @UnAuth + @GetMapping("/lableListByProvider") + @ResponseBody + public TableDataInfo lable_list_by_provider(Long providerId) + { + logger.debug("lableListByProvider with: {}", providerId); + startPage(); + List list = segchkStoreIndexService.selectSegchkRecommendLableList(providerId); + return getDataTable(list); + } + + /** + * 查询seg标签列表 尹志颖 + * { + * "providerId": 4 + * } + */ + @UnAuth + @GetMapping("/lableListByProviderAll") + @ResponseBody + public TableDataInfo lable_list_by_provider_all(Long providerId) + { + logger.debug("lableListByProviderAll with: {}", providerId); + startPage(); + List list = segchkStoreIndexService.selectSegchkLableList(providerId); + return getDataTable(list); + } + + /** + * 根据运营商id查询seg首页推荐商户列表 尹志颖 + * { + * "providerId": 4, + * "sortType": 1, + * "userLon": 114.123456, + * "userLat": 43.123456 + * } + */ + @UnAuth + @RequestMapping(value = "/listByProvider",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "根据运营商id查询seg首页推荐商户列表", notes = "不需要鉴权") + public TableDataInfo list_by_provider(@RequestBody SegchkRecommenderStoreWebReq segchkRecommenderStoreWebReq) + { + segchkRecommenderStoreWebReq.setUserDist(recomDist); + logger.debug("list_by_provider with: {}", segchkRecommenderStoreWebReq.toString()); + startPage(); + List list = segchkStoreIndexService.selectSegchkRecommenderStoreListByProvider(segchkRecommenderStoreWebReq); + System.out.println(list.size()); + return getDataTable(list); + } + + + /** + * 根据标签id,搜索商户列表 尹志颖 + * { + * "providerId": 2, + * "sortType": 0, + * "lableId": 1, + * "typeId": 2, + * "cardId": 2, 可选项,当用户在商户列表中,点选某个具体会员卡时才有效 + * "userLon": 116.25849, + * "userLat": 39.684333 + * } + */ + @UnAuth + @PostMapping("/listByProviderwithLable") + @ResponseBody + @ApiOperation(value = "根据标签id,搜索商户列表", notes = "不需要鉴权") + public TableDataInfo list_by_providerwith_lable(@RequestBody SegchkStoreWebReq segchkStoreWebReq) + { + + logger.debug("list_by_providerwith_lable with: {}", segchkStoreWebReq.toString()); + startPage(); + segchkStoreWebReq.setUserDist(recomDist); + List list = segchkStoreIndexService.selectSegchkStoreList(segchkStoreWebReq); + return getDataTable(list); + } + + /** + * 根据运营商id,返回轮播图列表 尹志颖 + * { + * "providerId": 3 + * } + */ + @UnAuth + @PostMapping("/getBannersByProvider") + @ResponseBody + @ApiOperation(value = "根据运营商id,返回轮播图列表", notes = "不需要鉴权") + public TableDataInfo get_banners_by_provider(Long providerId) + { + logger.debug("get_banners_by_provider with: {}", providerId); +// AjaxResult ajax = new AjaxResult(); + startPage(); + List segchkCarouseMgtList = segchkStoreIndexService.getBanners(providerId); +// ajax.put(CODE_TAG, 200); +// ajax.put(DATA_TAG, segchkCarouseMgtList); + return getDataTable(segchkCarouseMgtList); +// return ajax; + } + + + /** + * 根据运营商,商户id,查询商户详情 尹志颖 + * { + * "providerId": 4, + * "storeId": 124 + * } + */ + @UnAuth + @PostMapping("/storeDetails") + @ResponseBody + @ApiOperation(value = "根据运营商,商户id,查询商户详情", notes = "不需要鉴权") + public AjaxResult store_details(@RequestBody SegchkStoreWebReq segchkStoreWebReq, String recommenderId, String recommenderLevel, HttpServletRequest request) + { + logger.debug("store_details with: {}---{}---{}", segchkStoreWebReq.toString(), recommenderId, recommenderLevel); +// startPage(); + SegchkStoreBasicInfoWebResp segchkStoreBasicInfoWebResp = segchkStoreIndexService.selectSegchkStoreDetails(segchkStoreWebReq); + try { + Claims claims = getClaims(getToken(request)); + if (!ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 +// userId = getClaims(getToken(request)).getUserId(); + segchkStoreBasicInfoWebResp.setIsCollect(segchkStoreIndexService.isCollectByUser(segchkStoreWebReq.getProviderId(), Long.valueOf(segchkStoreWebReq.getStoreId()), getClaims(getToken(request)).getUserId())); + } + }catch (Exception e){ + e.printStackTrace(); + logger.error("storeDetails without user"); + } + + AjaxResult ajax = AjaxResult.success("获取成功", segchkStoreBasicInfoWebResp); + if(!StringUtils.isEmpty(recommenderId) && !StringUtils.isEmpty(recommenderLevel)){ + logger.debug("store_details recommender with: {}---{}", recommenderId, recommenderLevel); + int ret = segchkStoreIndexService.recommenderIsExit(recommenderId, recommenderLevel, segchkStoreWebReq.getProviderId().toString()); + if(ret > 1){ + ajax.put("recommenderId", recommenderId); + ajax.put("recommenderLevel", recommenderLevel); + } + logger.warn("store_details the recommender: ({}{}) is {} {} curprov({})", recommenderId, recommenderLevel, ret < 1 ? "not exit" : "exit", ret == 1 ? "with same provider" : "different with provider"); + } + return ajax; + } + + /** + * 查询seg商户评价列表 尹志颖 + */ + @UnAuth + @PostMapping("/storeCommentList") + @ResponseBody + @ApiOperation(value = "查询seg商户评价列表", notes = "不需要鉴权") + public TableDataInfo store_comment_list(@RequestBody SegchkStoreWebReq segchkStoreWebReq) + { + logger.debug("store_comment_list with: {}", segchkStoreWebReq.toString()); + startPage(); + List segchkServiceCommentWebRespList = segchkStoreIndexService.selectSegchkStoreComments(segchkStoreWebReq); + return getDataTable(segchkServiceCommentWebRespList); + } + + /** + * 查询seg商户评价列表 尹志颖 + */ + @UnAuth + @PostMapping("/shareInfo") + @ResponseBody + @ApiOperation(value = "查询seg商户评价列表", notes = "不需要鉴权") + public AjaxResult share_info(String page, String storeId, String providerId, String remark, HttpServletRequest request) + { + logger.debug("shareInfo page: {}", page); + ShareInfo shareInfo = new ShareInfo(); + shareInfo.setTitle(shareTitle); + shareInfo.setDesc(shareDesc); + StringBuilder sb = new StringBuilder(page); + if(!StringUtils.isEmpty(remark)){ + shareInfo.setPage(sb.append("?remark=").append(remark).toString()); + } + else { + Claims claims = null; + try { + claims = getClaims(getToken(request)); + sb.append("?&recC=").append(claims.getUserId()) + .append("&recV=").append(claims.getUserLevel()) + .append("&prov=").append(claims.getProviderId()) + .append((StringUtils.isEmpty(storeId) ? "" : "&store=" + storeId)); + shareInfo.setPage(sb.toString()); + } catch (Exception e) { + e.printStackTrace(); + sb.append("?") + .append((StringUtils.isEmpty(storeId) ? "" : "&store=" + storeId)) + .append((StringUtils.isEmpty(providerId) ? "" : "&prov=" + providerId)); + } + } + logger.debug("shareInfo res: {}", shareInfo.toString()); + return AjaxResult.success(shareInfo); + } + + /** + * 查询客服 尹志颖 + */ + @UnAuth + @PostMapping("/customService") + @ResponseBody + @ApiOperation(value = "查询客服", notes = "不需要鉴权") + public AjaxResult custom_service(Long providerId, HttpServletRequest request) + { + logger.debug("customService with: {}", providerId); + HashMap provider = segchkStoreIndexService.getCustomService(providerId); + CustomService customService = new CustomService(); + customService.setPhoneNo((String)provider.get("phoneNo")); + customService.setWechatId((String)provider.get("wechatId")); + logger.debug("customService res: {}", customService.toString()); + return AjaxResult.success(customService); + } + + + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + + Object claims = redisService.getCacheObject(token); + logger.debug("getClaims---token:{} Claims:{}", token, claims); + return ObjectUtils.isEmpty(claims) ? null : (Claims) claims; + } + + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + logger.info("getClaims fail :Authorization fail "); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + return authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); + } + + + private class ShareInfo extends BaseEntity { + private String title; + private String desc; + private String page; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + @Override + public String toString() { + return "ShareInfo{" + + "title='" + title + '\'' + + ", desc='" + desc + '\'' + + ", page='" + page + '\'' + + '}'; + } + } + + private class PrvoiderDistrict extends BaseEntity { + private Integer provFlag; + private Long providerId; + private String distName; + private String wechatId; + private String phoneNo; + + public Integer getProvFlag() { + return provFlag; + } + + public void setProvFlag(Integer provFlag) { + this.provFlag = provFlag; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public String getDistName() { + + return distName; + } + + public void setDistName(String distName) { + this.distName = distName; + } + + public String getWechatId() { + return wechatId; + } + + public void setWechatId(String wechatId) { + this.wechatId = wechatId; + } + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + @Override + public String toString() { + return "PrvoiderDistrict{" + + "provFlag=" + provFlag + + ", providerId=" + providerId + + ", distName='" + distName + '\'' + + ", wechatId='" + wechatId + '\'' + + ", phoneNo='" + phoneNo + '\'' + + '}'; + } + } + + private class CustomService extends BaseEntity { + private String phoneNo; + private String wechatId; + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public String getWechatId() { + return wechatId; + } + + public void setWechatId(String wechatId) { + this.wechatId = wechatId; + } + + @Override + public String toString() { + return "CustomService{" + + "phoneNo='" + phoneNo + '\'' + + ", wechatId='" + wechatId + '\'' + + '}'; + } + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultProviderController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultProviderController.java new file mode 100644 index 0000000..cdcd67a --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultProviderController.java @@ -0,0 +1,207 @@ +package com.ruoyi.segchk; + +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +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.login.SegChkLoginController; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.service.*; +import com.ruoyi.util.Claims; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +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.util.ObjectUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * seg首页推荐商户Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/default/provider") +@Api("运营商小程序接口") +public class SegchkDefaultProviderController extends BaseController +{ + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + @Autowired + private RedisCache redisService; + + + // 登录超时时长,单位天,-1永久有效 + @Value("${yzytest.login.loginexpire:#{1}}") + private Integer loginexpire; + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + /** + * 查询seg用户中心信息 尹志颖 + * { + * "userId": 240,//* + * "providerId": 4,//* + * "userLevel": 2//* 0运营商,1商户,2用户 + * } + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:provider_info:query')") + @PostMapping("/storeUserInfo") + @ResponseBody + @ApiOperation(value = "查询seg运营商中心信息", notes = "需要鉴权") + public AjaxResult storeUserInfo(SegchkUserWebReq segchkUserWebReq) + { +// startPage(); + AjaxResult ajax = new AjaxResult(); + + ajax.put("code", 200); + + SegchkUserWebResp segchkUserWebResp = segchkUserWebReq.getUserLevel() == 2 ? + segchkUserIndexService.selectSegchkUserWebInfo(segchkUserWebReq) + : (segchkUserWebReq.getUserLevel() == 1 ? + segchkStoreIndexService.selectSegchkStoreWebInfo(segchkUserWebReq) : segchkProviderIndexService.selectSegchkProviderWebInfo(segchkUserWebReq)); + ajax.put("value", segchkUserWebResp); + return ajax; + } + + + /** + * 根据运营商id,角色等级,返回运营商下所有核消统计或售卡统计 尹志颖 + * { + * "providerId": 4,//* + * "staticMonth": "10",,//测试 + * "srcFlag": 0//*0核消汇总1售卡汇总 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:provider_service_sale:list')") + @PostMapping("/providerServiceAndSaleList") + @ResponseBody + @ApiOperation(value = "根据运营商id,角色等级,返回运营商下所有核消统计或售卡统计", notes = "需要鉴权") + public TableDataInfo providerServiceAndSaleList(@RequestBody SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkServiceAndSaleWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceAndSaleWebReq.setProviderId(claims.getUserId()); + } + logger.debug("providerServiceAndSaleList with: {}", segchkServiceAndSaleWebReq.toString()); + startPage(); + List segchkServiceAndSaleWebRespList = segchkProviderIndexService.selectProviderServiceAndSaleList(segchkServiceAndSaleWebReq); + return getDataTable(segchkServiceAndSaleWebRespList); + } + + /** + * 根据运营商id,角色等级,返回运营商下核消统计或售卡统计 尹志颖 + * { + * "providerId": 4,//* + * "staticMonth": "2021-06-01",//* + * "srcFlag": 0//*0核消详情1售卡详情 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:provider_service_sale:query')") + @PostMapping("/providerServiceAndSaleDetails") + @ResponseBody + @ApiOperation(value = "根据运营商id,角色等级,返回运营商下核消统计或售卡统计", notes = "需要鉴权") + public TableDataInfo providerServiceAndSaleDetails(@RequestBody SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkServiceAndSaleWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceAndSaleWebReq.setProviderId(claims.getUserId()); + } + logger.warn("providerServiceAndSaleDetails with: {}", segchkServiceAndSaleWebReq.toString()); + startPage(); + List segchkServiceAndSaleDetailWebRespList = segchkProviderIndexService.selectProviderServiceAndSaleDetails(segchkServiceAndSaleWebReq); + return getDataTable(segchkServiceAndSaleDetailWebRespList); + } + + + // 返回注册登录提示 + private AjaxResult LoginRequireAjax() { + return AjaxResult.error(300, "请先登录注册"); + } + + private TableDataInfo LoginRequireTableInfo() { + TableDataInfo tableDataInfo = new TableDataInfo(); + tableDataInfo.setCode(300); + tableDataInfo.setMsg("请先登录注册"); + return tableDataInfo; + } + + // 获取登录信息 + private Claims getLoing(HttpServletRequest request){ + String token = null; + try { + token = getToken(request); + }catch (Exception e){ + e.printStackTrace(); + return null; + } + Claims claims = getClaims(token); + if(!ObjectUtils.isEmpty(claims)){ + if(loginexpire == -1){ + redisService.setCacheObject(token, claims); + } + else { + redisService.setCacheObject(token, claims, loginexpire, TimeUnit.DAYS); + } + } + return claims; + } + + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + logger.info("getClaims fail :Authorization fail "); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + String token = authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); +// logger.warn("get toke info from {}---{}({})", authHeader, token, token.length()); + return token; + } + + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + + Object claims = redisService.getCacheObject(token); + logger.debug("getClaims---token:{} Claims:{}", token, claims); + return ObjectUtils.isEmpty(claims) ? null : (Claims) claims; + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultStoreController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultStoreController.java new file mode 100644 index 0000000..76240bd --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultStoreController.java @@ -0,0 +1,589 @@ +package com.ruoyi.segchk; + +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.BaseEntity; +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.file.FileUtils; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.service.*; +import com.ruoyi.util.Claims; +import com.ruoyi.util.CommonConstant; +import com.ruoyi.util.QRCodeUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +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.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static com.ruoyi.common.core.domain.AjaxResult.*; + +/** + * seg首页推荐商户Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/default/store") +@Api("商家小程序接口") +public class SegchkDefaultStoreController extends BaseController +{ + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + // 核消二维码保存路径 + @Value("${segchk.store_qr_path:#{null}}") + private String qrPath; + + // 核消二维码背景图片 + @Value("${segchk.store_poster_path:#{null}}") + private String posterPath; + + @Value("${segchk.storeurl:#{null}}") + private String SEGCHK_ST_URL; + + + @Value("${segchk.sto_height:#{200}}") + private Integer stoHeight; + + @Value("${segchk.sto_weight:#{200}}") + private Integer stoWeight; + + // 登录超时时长,单位天,-1永久有效 + @Value("${yzytest.login.loginexpire:#{1}}") + private Integer loginexpire; + +// 如果是一张新会员卡,在第一次核消是是否给商家返利 + @Value("${segchk.servicecheck.storereward.enable:false}") + private Boolean stoRewardWithChk; + + /** + * 查询seg用户中心信息 尹志颖 + * { + * "userId": 240,//* + * "providerId": 4,//* + * "userLevel": 2//* 0运营商,1商户,2用户 + * } + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:store_info:query')") + @PostMapping("/storeUserInfo") + @ResponseBody + @ApiOperation(value = "查询seg商家中心信息", notes = "需要鉴权") + public AjaxResult store_user_info(SegchkUserWebReq segchkUserWebReq) + { +// startPage(); + AjaxResult ajax = new AjaxResult(); + + ajax.put("code", 200); + + SegchkUserWebResp segchkUserWebResp = segchkUserWebReq.getUserLevel() == 2 ? + segchkUserIndexService.selectSegchkUserWebInfo(segchkUserWebReq) + : (segchkUserWebReq.getUserLevel() == 1 ? + segchkStoreIndexService.selectSegchkStoreWebInfo(segchkUserWebReq) : segchkProviderIndexService.selectSegchkProviderWebInfo(segchkUserWebReq)); + ajax.put("value", segchkUserWebResp); + return ajax; +// return getDataTable(segchkServiceCommentWebRespList); + } + + + + /** + * 根据商家id,运营商id,角色等级,返回核消统计或售卡统计 尹志颖 + * { + * "providerId": 4,//* + * "storeId": 123,//* + * "staticMonth": "6",//查询最近几个月汇总 + * "userLevel": 1,//测试 + * "srcFlag": 0//*0核消汇总1售卡汇总 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:store_service_sale:list')") + @PostMapping("/storeServiceAndSaleList") + @ResponseBody + @ApiOperation(value = "根据商家id,运营商id,角色等级,返回核消统计或售卡统计", notes = "需要鉴权") + public TableDataInfo store_service_and_sale_list(@RequestBody SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkServiceAndSaleWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceAndSaleWebReq.setStoreId(claims.getUserId()); + segchkServiceAndSaleWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("store_service_and_sale_list with: {}", segchkServiceAndSaleWebReq.toString()); + startPage(); + List segchkServiceAndSaleWebRespList = segchkStoreIndexService.selectStoreServiceAndSaleList(segchkServiceAndSaleWebReq); + return getDataTable(segchkServiceAndSaleWebRespList); + } + + /** + * 根据商家id,运营商id,角色等级,返回核消统计或售卡统计 尹志颖 + * { + * "providerId": 4, + * "storeId": 123, + * "staticMonth": "2021-06-01", + * "srcFlag": 0 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:store_service_sale:query')") + @PostMapping("/storeServiceAndSaleDetails") + @ResponseBody + @ApiOperation(value = "根据商家id,运营商id,角色等级,返回核消统计或售卡统计", notes = "需要鉴权") + public TableDataInfo store_service_and_sale_details(@RequestBody SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkServiceAndSaleWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceAndSaleWebReq.setStoreId(claims.getUserId()); + segchkServiceAndSaleWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("store_service_and_sale_details with: {}", segchkServiceAndSaleWebReq.toString()); + startPage(); + List segchkServiceAndSaleDetailWebRespList = segchkStoreIndexService.selectStoreServiceAndSaleDetails(segchkServiceAndSaleWebReq); + return getDataTable(segchkServiceAndSaleDetailWebRespList); + } + + + /** + * 根据商家id,运营商id,返回针对该商家的预约列表 尹志颖 + * { + * "providerId": 4,//* + * "storeId": 123,//* + * "staticMonth": "60"//测试 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:store_likego:list')") + @PostMapping("/storeUserLikeGoList") + @ResponseBody + @ApiOperation(value = "根据商家id,运营商id,返回针对该商家的预约列表", notes = "需要鉴权") + public TableDataInfo store_user_like_go_list(@RequestBody SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkServiceAndSaleWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceAndSaleWebReq.setStoreId(claims.getUserId()); + segchkServiceAndSaleWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("store_user_like_go_list with: {}", segchkServiceAndSaleWebReq.toString()); + startPage(); + List segchkUserLikeGoWebRespList = segchkStoreIndexService.selectStoreUserLikeGoList(segchkServiceAndSaleWebReq); + return getDataTable(segchkUserLikeGoWebRespList); + } + + + /** + * 根据用户id,运营商id,查询seg商户提现列表 尹志颖 + * { + * "userId": 84,//* + * "phoneNo": "demoData",//测试 + * "providerId": 3//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:store_cash:list')") + @PostMapping("/storeCashList") + @ResponseBody + @ApiOperation(value = "根据用户id,运营商id,查询seg商户提现列表", notes = "需要鉴权") + public TableDataInfo store_cash_list(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("store_cash_list with: {}", segchkUserWebReq.toString()); + startPage(); + List segchkUserWebSCRespList = segchkStoreIndexService.selectStoreCashList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据二维码参数,解析出预约卡信息及商家id,进行对比确认,如果不可核 消返回失败原因,如果成功返回成功信息 + * { + * "likegoId": 0,//*二维码中携带 + * "storeId": "demoData"//*提交请求时携带 + * } + */ + @RepeatSubmit + @ApiOperation(value = "商家核消操作", notes = "需要鉴权") +// @PreAuthorize("@ss.hasPermi('segchk:store_check:update')") + @PostMapping( "/ServiceCheckTest") + @ResponseBody + @Transactional(propagation = Propagation.REQUIRED) + public AjaxResult service_check_test(Long likegoId, String storeId, String remark, HttpServletRequest request) + { + + if(StringUtils.isEmpty(remark)){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + if(!storeId.equals(String.valueOf(claims.getUserId()))){ + logger.warn("ServiceCheckTest---storeid: {} is not then token: {}", storeId, claims); + return AjaxResult.error(300, "请先登录注册"); + } + } + AjaxResult ajax = new AjaxResult(); + logger.debug("ServiceCheckTest with: {}---{}---{}", likegoId.toString(), storeId, remark); + SegchkServiceOrderChkTestResp segchkServiceOrderChkTestResp = segchkUserIndexService.selectUserOrderPredInfo(likegoId); + segchkServiceOrderChkTestResp.setLikegoId(likegoId); + logger.debug("ServiceCheckTest check with: {}", segchkServiceOrderChkTestResp.toString()); + if(segchkServiceOrderChkTestResp.getStoreId()!= Long.parseLong(storeId)){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "预约单商家非本店商家!"); + } + else if(segchkServiceOrderChkTestResp.getMgtState() != 0){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, segchkServiceOrderChkTestResp.getMgtState() == 1 ? "该预约单所用卡已失效" : "该预约单所用卡已使用"); + } + else if(segchkServiceOrderChkTestResp.getIsExpire() == 1){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "该预约单所用卡已失效"); + } + else if(segchkServiceOrderChkTestResp.getCardStatus() != 0){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "该预约单所用卡已失效"); + } + else if(segchkServiceOrderChkTestResp.getTotalCount() == 0){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "本店已不支持该类型卡"); + } + else if(segchkServiceOrderChkTestResp.getHasLeftCount() <= 0){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "该预约单在本店已无可用权益次数"); + } + else if(segchkServiceOrderChkTestResp.getCanFree() == 1){ + int ret = segchkUserIndexService.OrderCheckTransaction(segchkServiceOrderChkTestResp, likegoId, stoRewardWithChk); + ajax.put(CODE_TAG, "200"); + + segchkServiceOrderChkTestResp.setSegchkRecommenderStoreLableWebList(null); + ajax.put(DATA_TAG, segchkServiceOrderChkTestResp); + + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_SERVICE_CHK).append(":").append(storeId).append("-").append(segchkServiceOrderChkTestResp.getUserId()); + logger.debug("ServiceCheckTest will store likego : {}:{}", sb.toString(), likegoId); + redisService.setCacheObject(sb.toString(), likegoId, 5, TimeUnit.MINUTES); + } + else { + int ret = segchkUserIndexService.OrderCheckTransaction(segchkServiceOrderChkTestResp, likegoId, stoRewardWithChk); + + if(ret != 3){ + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "核消失败"); + } + else{ + ajax.put(CODE_TAG, "200"); + ajax.put(MSG_TAG, "核消成功"); + List lables = segchkServiceOrderChkTestResp.getSegchkRecommenderStoreLableWebList(); + SegchkRecommenderStoreLableWeb lable = new SegchkRecommenderStoreLableWeb(); + lable.setLableId(0); + lable.setLableTypeId(1); + lable.setLableName("本店尊享"); + lables.add(lable); + segchkServiceOrderChkTestResp.setSegchkRecommenderStoreLableWebList(lables); + ajax.put(DATA_TAG, segchkServiceOrderChkTestResp); + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_SERVICE_CHK).append(":").append(storeId).append("-").append(segchkServiceOrderChkTestResp.getUserId()); + logger.debug("ServiceCheckTest will store likego : {}:{}", sb.toString(), likegoId); + redisService.setCacheObject(sb.toString(), likegoId, 5, TimeUnit.MINUTES); + } + } + return ajax; + } + + @PostMapping("giveFreeCard") + @ResponseBody + @ApiOperation(value = "商家赠卡接口", notes = "需要鉴权") + public AjaxResult giveFreeCard(@RequestBody StoreSelfCard storeSelfCard, HttpServletRequest request) + { + logger.debug("giveFreeCard with --- {}", storeSelfCard.toString()); + SegchkStoreSelfMgt segchkStoreSelfMgt = new SegchkStoreSelfMgt(); + segchkStoreSelfMgt.setStoreId(storeSelfCard.getStoreId()); + if(StringUtils.isEmpty(storeSelfCard.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkStoreSelfMgt.setProviderId(claims.getProviderId()); + segchkStoreSelfMgt.setStoreId(claims.getUserId()); + } + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_SERVICE_CHK).append(":").append(segchkStoreSelfMgt.getStoreId()).append("-").append(storeSelfCard.getUserId()); + Long likegoId = redisService.getCacheObject(sb.toString()); + if(likegoId == null){ + logger.warn("giveFreeCard cannot get likegoId from redis for ({}:{})", segchkStoreSelfMgt.getStoreId(), storeSelfCard.getUserId()); + return AjaxResult.error(500, "赠卡失败"); + } + Long cardId = segchkStoreIndexService.getVipCardFromLikego(likegoId); + segchkStoreSelfMgt.setCardId(cardId); + segchkStoreSelfMgt.setUserId(storeSelfCard.getUserId()); + segchkStoreSelfMgt.setTypeId(storeSelfCard.getTypeId()); + segchkStoreSelfMgt.setFreeCount(storeSelfCard.getTotalCount()); + segchkStoreSelfMgt.setLableId(storeSelfCard.getTypeId() == 2 ? storeSelfCard.getLableId() : 0L); + segchkStoreSelfMgt.setFreeName(storeSelfCard.getTypeId() == 2 ? null : "赠卡"); + segchkStoreSelfMgt.setFreeContent(storeSelfCard.getFreeContent()); + segchkStoreSelfMgt.setLeftCount(storeSelfCard.getTotalCount()); + logger.debug("giveFreeCard with --- {}", segchkStoreSelfMgt.toString()); + Integer ret = segchkStoreIndexService.addStoreSelfCard(segchkStoreSelfMgt); + if(ret == 0){ + logger.error("giveFreeCard failed with --- {}", segchkStoreSelfMgt.toString()); + } + redisService.deleteObject(sb.toString()); + return ret > 0 ? AjaxResult.success("赠卡成功") : AjaxResult.error(500, "赠卡失败"); + } + /** + * 提现结果回调接口,接口微信的支付结果,更新充值结果, ret 0成功,其他失败 未测试 + * { + * "chargeId": "45435", + * "userLevel": "1/2/0", + * "ret": 1 + * } + */ +// @Log(title = "seg提现结果回调", businessType = BusinessType.UPDATE) + @PostMapping("/userCashResult") + @ResponseBody + @ApiOperation(value = "提现结果回调接口", notes = "需要鉴权") + public void userCashResult(String chargeId, int userLevel, int ret) + { + if(userLevel == 1) { + segchkStoreIndexService.cashRet(chargeId, ret); + } + else if(userLevel == 2){ + segchkUserIndexService.cashRet(chargeId, ret); + } + } + + + /** + * 根据信息,生成商户推广二维码 尹志颖 + * { + * "userId": 234,//* + * "providerId": 4,//* + * "userLevel": 0//测试用 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_likego:list')") + @UnAuth + @GetMapping("/storeShareQr") + @ResponseBody + @ApiOperation(value = "商户推广二维码", notes = "需要鉴权") + public AjaxResult store_share_qr(String storeId, String providerId, String remark, Integer qrw, Integer qrh, HttpServletRequest request, HttpServletResponse response) + { + if(StringUtils.isEmpty(remark)){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + storeId = String.valueOf(claims.getUserId()); + providerId = String.valueOf(claims.getProviderId()); + } + String urlstr = String.format(SEGCHK_ST_URL, storeId, "1") + (StringUtils.isEmpty(remark) ? "" : "&remark=" + remark); + logger.debug("storeShareQr with: prov:{}---store:{}---url:{}", storeId, providerId, urlstr); + createQRImg(response, urlstr, storeId, providerId, (ObjectUtils.isEmpty(qrw) ? stoWeight : qrw), (ObjectUtils.isEmpty(qrh) ? stoHeight : qrh)); + return AjaxResult.success("生成成功"); + } + + @UnAuth + @GetMapping("/storerecommend") + @ResponseBody + @ApiOperation(value = "商户推广二维码", notes = "需要鉴权") + public AjaxResult storerecommend(String recC, String recV, String prov, HttpServletRequest request, HttpServletResponse response) + { + + StoreRecommend storeRecommend = new StoreRecommend(); + storeRecommend.setProviderId(prov); + storeRecommend.setRecommendId(recC); + storeRecommend.setRecommendLevel(recV); + logger.debug("storerecommend res: {}", storeRecommend.toString()); + return AjaxResult.success("生成成功", storeRecommend); + } + + + + // 返回注册登录提示 + private AjaxResult LoginRequireAjax() { + return AjaxResult.error(300, "请先登录注册"); + } + + private TableDataInfo LoginRequireTableInfo() { + TableDataInfo tableDataInfo = new TableDataInfo(); + tableDataInfo.setCode(300); + tableDataInfo.setMsg("请先登录注册"); + return tableDataInfo; + } + + // 获取登录信息 + private Claims getLoing(HttpServletRequest request){ + String token = null; + try { + token = getToken(request); + }catch (Exception e){ + e.printStackTrace(); + return null; + } + Claims claims = getClaims(token); + if(!ObjectUtils.isEmpty(claims)){ + if(loginexpire == -1){ + redisService.setCacheObject(token, claims); + } + else { + redisService.setCacheObject(token, claims, loginexpire, TimeUnit.HOURS); + } + } + return claims; + } + + + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + + Object claims = redisService.getCacheObject(token); + logger.debug("getClaims---token:{} Claims:{}", token, claims); + return ObjectUtils.isEmpty(claims) ? null : (Claims) claims; + } + + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + logger.info("getClaims fail :Authorization fail "); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + return authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); + } + + /** + * 创建二维码图片 + * + * @param url 链接地址 + * @param width 宽 + * @param height 高 + */ + private void createQRImg(HttpServletResponse response, String url, String storeId, String providerId, Integer width, Integer height) { + logger.debug("createQRImg with: {}---w:{}---h:{}", url, width, height); + OutputStream outputStream = null; + try { + outputStream = response.getOutputStream(); + StringBuilder qrsb = new StringBuilder(qrPath); + qrsb.append(File.separator).append(providerId).append("_").append(storeId).append("qr.jpg"); + QRCodeUtils.createQrCode(url, width, height, "jpg", outputStream, qrsb.toString(), posterPath); + logger.debug("createQRImg qrPath: {}, posterPath: {}", qrPath, posterPath); + outputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + private class StoreRecommend extends BaseEntity { + private String recommendId; + private String recommendLevel; + private String providerId; + + public String getRecommendId() { + return recommendId; + } + + public void setRecommendId(String recommendId) { + this.recommendId = recommendId; + } + + public String getRecommendLevel() { + return recommendLevel; + } + + public void setRecommendLevel(String recommendLevel) { + this.recommendLevel = recommendLevel; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + @Override + public String toString() { + return "StoreRecommend{" + + "recommendId='" + recommendId + '\'' + + ", recommendLevel='" + recommendLevel + '\'' + + ", providerId='" + providerId + '\'' + + '}'; + } + } + + +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultUserController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultUserController.java new file mode 100644 index 0000000..c65e830 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/segchk/SegchkDefaultUserController.java @@ -0,0 +1,1111 @@ +package com.ruoyi.segchk; + +import com.ruoyi.appletsutil.ResultCode; +import com.ruoyi.appletsutil.UnAuthorizedException; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.member.service.WeChatCustomerLinkService; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.service.*; +import com.ruoyi.setting.bean.WechatPaySet; +import com.ruoyi.setting.service.ILsPaySettingService; +import com.ruoyi.util.*; +import com.ruoyi.util.bean.PrepayResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import springfox.documentation.annotations.ApiIgnore; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static com.ruoyi.common.core.domain.AjaxResult.*; +import static com.ruoyi.common.utils.ip.IpUtils.getIpAddr; + +/** + * seg首页推荐商户Controller + * + * @author yinzhiying + * @date 2021-08-23 + */ +@RestController +@RequestMapping("/default/user") +@Api("用户小程序接口") +public class SegchkDefaultUserController extends BaseController +{ + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + @Autowired + private ISegchkUserCollectService segchkUserCollectService; + + @Autowired + private ISegchkUserLikegoService segchkUserLikegoService; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + + @Autowired + private ISegchkUserChargeService segchkUserChargeService; + + /** + * 注入支付设置服务 + */ + @Autowired + private ILsPaySettingService paySetService; + + /** + * 注入微信用户关联服务 + */ + @Autowired + private WeChatCustomerLinkService weChatCustomerLinkService; + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + + // 核消二维码保存路径 + @Value("${segchk.check_qr_path:#{null}}") + private String qrPath; + + // 核消二维码背景图片 + @Value("${segchk.check_poster_path:#{null}}") + private String posterPath; + + @Value("${segchk.chkurl:#{null}}") + private String SEGCHK_SC_URL; + + @Value("${segchk.chk_height:#{200}}") + private Integer chkHeight; + + @Value("${segchk.chk_weight:#{200}}") + private Integer chkWeight; + + // 登录超时时长,单位天,-1永久有效 + @Value("${yzytest.login.loginexpire:#{1}}") + private Integer loginexpire; + /** + * 新增保存seg用户收藏记录 + * { + * "collectType": "1",//* + * "providerId": 0,//* + * "userId": 0,//* + * "storeId": 0,//* + * "modTime": "2021-08-16 13:43:43", + * "mgtState": 0//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_collect:add')") + @UnAuth +// @Log(title = "seg用户收藏记录", businessType = BusinessType.INSERT) + @RepeatSubmit + @PostMapping("/addUserCollect") + @ResponseBody + @ApiOperation(value = "添加seg用户收藏记录", notes = "需要鉴权") + public AjaxResult add_user_collect(@RequestBody SegchkUserCollect segchkUserCollect, HttpServletRequest request) + { + if(!StringUtils.isEmpty(segchkUserCollect.getRemark())){ +// 测试 + if(!segchkUserCollect.isValid()){ + return AjaxResult.error("400", "请求信息异常"); + } + logger.debug("add_user_collect with: {}", segchkUserCollect.toString()); + return toAjax(segchkUserCollectService.insertSegchkUserCollect(segchkUserCollect)); + } + + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + if (claims.getUserLevel() != 2){ + return AjaxResult.error(400, "非会员用户不可以收藏"); + } + segchkUserCollect.setUserId(claims.getUserId()); + segchkUserCollect.setProviderId(claims.getProviderId()); + logger.debug("add_user_collect with: {}", segchkUserCollect.toString()); + return toAjax(segchkUserCollectService.insertSegchkUserCollect(segchkUserCollect)); + } + + + /** + * 删除seg用户收藏记录 + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_collect:remove')") + @UnAuth +// @Log(title = "删除seg用户收藏记录", businessType = BusinessType.DELETE) + @PostMapping( "/removeUserCollect") + @ResponseBody + @ApiOperation(value = "删除seg用户收藏记录", notes = "需要鉴权") + public AjaxResult removeUserCollect(@RequestBody RemoveIds removeIds, HttpServletRequest request) + { + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + logger.debug("removeUserCollect with: {}", removeIds.toString()); + return toAjax(segchkUserCollectService.deleteSegchkUserCollectByIds(removeIds.getIds())); + } + + /** + * 根据运营商id,用户id,商户id,查询该用户在该商户可使用的会员卡或优惠券 尹志颖 + * { + * "providerId": 4, + * "storeId": 128, + * "userId": 245 + * } + */ + @UnAuth +// @Log(title = "查询该用户在该商户可使用的会员卡或优惠券", businessType = BusinessType.GENCODE) + @PostMapping("/userOrderPredList") + @ResponseBody + public TableDataInfo UserOrderPredList(@RequestBody SegchkServiceOrderWebReq segchkServiceOrderWebReq, HttpServletRequest request) + { + startPage(); + if(!StringUtils.isEmpty(segchkServiceOrderWebReq.getRemark())){ + List segchkServiceOrderWebReqList = segchkUserIndexService.selectUserOrderPredCardListWebInfo(segchkServiceOrderWebReq); + return getDataTable(segchkServiceOrderWebReqList); + } + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkServiceOrderWebReq.setUserId(claims.getUserId()); + List segchkServiceOrderWebReqList = segchkUserIndexService.selectUserOrderPredCardListWebInfo(segchkServiceOrderWebReq); +// boolean anyMatch = segchkServiceOrderWebReqList.parallelStream().anyMatch(v -> v.getTypeId() == 0); + return getDataTable(segchkServiceOrderWebReqList); + } + + /** + * 新增保存seg用户想去记录 + * { + * "providerId": 4,//* + * "userId": 231,//* + * "storeId": 128,//* + * "cardId": 230,//* + * "cardType": 0 //* 0充值卡2优惠券1赠卡 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_likego:add')") + @UnAuth +// @Log(title = "seg用户想去记录", businessType = BusinessType.INSERT) + @RepeatSubmit + @PostMapping("/addOrderUserLikego") + @ResponseBody + @ApiOperation(value = "添加seg用户想去记录", notes = "需要鉴权") + public AjaxResult add_order_user_likego(@RequestBody SegchkUserLikego segchkUserLikego, HttpServletRequest request) + { + Long userId = 0L; + + if(StringUtils.isEmpty(segchkUserLikego.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + if(claims.getUserLevel() != 2){ + return AjaxResult.error(400, "未会员用户不允许预约!"); + } + segchkUserLikego.setUserId(claims.getUserId()); + segchkUserLikego.setProviderId(claims.getProviderId()); + } + logger.debug("add_order_user_likego with: {}", segchkUserLikego.toString()); + return toAjax(segchkUserLikegoService.insertSegchkUserLikego(segchkUserLikego)); + } + + + /** + * 根据预约id,返回预约单二维码 尹志颖 + * { + * "userId": 234,//* + * "providerId": 4,//* + * "userLevel": 0//测试用 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_likego:list')") + @UnAuth + @PostMapping("/userLikeGoQr") + @ResponseBody + @ApiOperation(value = "查询seg用户预约单列表", notes = "需要鉴权") + public AjaxResult user_like_go_qr(String likegoId, String remark, Integer qrw, Integer qrh, HttpServletRequest request, HttpServletResponse response) + { + SegchkUserLikego segchkUserLikego = new SegchkUserLikego(); + segchkUserLikego.setLikegoId(Long.valueOf(likegoId)); + if(StringUtils.isEmpty(remark)){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkUserLikego.setUserId(claims.getUserId()); + segchkUserLikego.setProviderId(claims.getProviderId()); + } + startPage(); + logger.debug("userLikeGoQr with: {}", segchkUserLikego.toString()); + SegchkUserLikego segchkUserLikego1 = segchkUserIndexService.selectUserLikeGo(segchkUserLikego); + createQRImg(response, String.format(SEGCHK_SC_URL, likegoId, segchkUserLikego1.getStoreId()) + (StringUtils.isEmpty(remark) ? "" : "&remark=" + remark), (ObjectUtils.isEmpty(qrw) ? chkWeight : qrw), (ObjectUtils.isEmpty(qrh) ? chkHeight : qrh)); + return AjaxResult.success("生成成功"); + } + + /** + * 查询seg用户中心信息 尹志颖 + * { + * "userId": 240,//* + * "providerId": 4,//* + * "userLevel": 2//* 0运营商,1商户,2用户 + * } + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_info:query')") + @UnAuth + @PostMapping("/storeUserInfo") + @ResponseBody + @ApiOperation(value = "查询seg用户中心信息", notes = "需要鉴权") + public AjaxResult store_user_info(SegchkUserWebReq segchkUserWebReq) + { +// startPage(); + AjaxResult ajax = new AjaxResult(); + + ajax.put("code", 200); + + SegchkUserWebResp segchkUserWebResp = segchkUserWebReq.getUserLevel() == 2 ? + segchkUserIndexService.selectSegchkUserWebInfo(segchkUserWebReq) + : (segchkUserWebReq.getUserLevel() == 1 ? + segchkStoreIndexService.selectSegchkStoreWebInfo(segchkUserWebReq) : segchkProviderIndexService.selectSegchkProviderWebInfo(segchkUserWebReq)); + ajax.put("value", segchkUserWebResp); + return ajax; +// return getDataTable(segchkServiceCommentWebRespList); + } + + + /** + * 根据用户id,运营商id,查询seg用户核消列表 尹志颖 + * { + * "userId": 245,//* + * "providerId": 4//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_check:list')") + @UnAuth + @PostMapping("/storeServiceCheckList") + @ResponseBody + @ApiOperation(value = "查询seg用户核消列表", notes = "需要鉴权") + public TableDataInfo store_service_check_list(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + startPage(); + logger.debug("store_service_check_list with: {}", segchkUserWebReq.toString()); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserServiceCHKList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据用户id,运营商id,查询seg用户可用会员卡列表或者优惠券列表 尹志颖 + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_card:list')") + @UnAuth + @PostMapping("/userCardList") + @ResponseBody + @ApiOperation(value = "查询seg用户可用会员卡列表或者优惠券列表", notes = "需要鉴权") + public TableDataInfo user_card_list(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + startPage(); + logger.debug("user_card_list with: {}", segchkUserWebReq.toString()); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserCardList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据用户id,运营商id,查询seg用户收藏列表 尹志颖 + * { + * "userId": 439,//* + * "providerId": 4//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_collect:list')") + @UnAuth + @PostMapping("/userCollectList") + @ResponseBody + @ApiOperation(value = "查询seg用户收藏列表", notes = "需要鉴权") + public TableDataInfo user_collect_list(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + startPage(); + logger.debug("user_collect_list with: {}", segchkUserWebReq.toString()); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserCollectList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据用户id,运营商id,查询seg用户预约单列表 尹志颖 + * { + * "userId": 234,//* + * "providerId": 4,//* + * "userLevel": 0//测试用 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_likego:list')") + @UnAuth + @PostMapping("/userLikeGOList") + @ResponseBody + @ApiOperation(value = "查询seg用户预约单列表", notes = "需要鉴权") + public TableDataInfo userLikeGOList(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + startPage(); + logger.debug("userLikeGOList with: {}", segchkUserWebReq.toString()); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserLikGoList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 删除seg用户想去记录 + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_likego:remove')") +// @Log(title = "seg用户想去记录", businessType = BusinessType.DELETE) + @PostMapping( "/removeOrderUserLikego") + @ResponseBody + @ApiOperation(value = "删除seg用户想去记录", notes = "需要鉴权") + public AjaxResult removeOrderUserLikego(@RequestBody RemoveIds removeIds, HttpServletRequest request) + { + + if(StringUtils.isEmpty(removeIds.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + removeIds.setUserId(claims.getUserId()); + } + logger.debug("removeOrderUserLikego with: {}", removeIds.toString()); + return toAjax(segchkUserLikegoService.deleteSegchkUserLikegoByLikegoIds(Convert.toLongArray(removeIds.getIds()))); + } + + /** + * seg服务评价查询 + * { + * "commentId": 3//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_comment:query')") +// @Log(title = "seg服务评价查看", businessType = BusinessType.OTHER) + @PostMapping( "/getComment") + @ResponseBody + @ApiOperation(value = "seg服务评价查询", notes = "需要鉴权") + public AjaxResult get_comment(@RequestBody SegchkServiceCommentUserReq segchkServiceCommentUserReq, HttpServletRequest request) + { + if(StringUtils.isEmpty(segchkServiceCommentUserReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + } + logger.debug("get_comment with: {}", segchkServiceCommentUserReq.toString()); + AjaxResult ajax = new AjaxResult(); + SegchkServiceComment segchkServiceComment = segchkUserIndexService.selectSegchkServiceComment(segchkServiceCommentUserReq); + if(segchkServiceComment == null){ + ajax.put(CODE_TAG, "300"); + ajax.put(MSG_TAG, "未查到相关评价"); + } + else{ + ajax.put(CODE_TAG, "200"); + ajax.put(DATA_TAG, segchkServiceComment); + } + return ajax; + } + + + /** + * seg服务评价提交 + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_comment:add')") +// @Log(title = "seg服务评价提交", businessType = BusinessType.INSERT) + @PostMapping( "/addComment") + @ResponseBody + @ApiOperation(value = "seg服务评价提交", notes = "需要鉴权") + public AjaxResult addComment(@RequestBody SegchkServiceCommentUserReq segchkServiceCommentUserReq, HttpServletRequest request) + { + if(StringUtils.isEmpty(segchkServiceCommentUserReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + if (claims.getUserLevel() != 2){ + return AjaxResult.error(400, "非会员用户不允许提交评价"); + } + } + logger.debug("addComment with: {}", segchkServiceCommentUserReq.toString()); + return toAjax(segchkUserIndexService.insertSegchkServiceComment(segchkServiceCommentUserReq)); + } + + + /** + * 根据用户id,运营商id,查询seg用户充值列表 尹志颖 + * { + * "userId": 34,//* + * "providerId": 2//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_charge:list')") + @PostMapping("/userChargeList") + @ResponseBody + @ApiOperation(value = "查询seg用户充值列表", notes = "需要鉴权") + public TableDataInfo userChargeList(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("userChargeList with: {}", segchkUserWebReq.toString()); + startPage(); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserChargeList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据用户id,运营商id,查询seg用户提现列表 尹志颖 + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_cash:list')") + @PostMapping("/userCashList") + @ResponseBody + @ApiOperation(value = "查询seg用户提现列表", notes = "需要鉴权") + public TableDataInfo userCashList(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("userCashList with: {}", segchkUserWebReq.toString()); + startPage(); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserCashList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 根据用户id,运营商id,角色等级查询seg用户消息列表 尹志颖 + * { + * "userId": 392,//* + * "providerId": 4,//* + * "userLevel": 2,//* + * "phoneNo": 1//测试 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_msg:list')") + @PostMapping("/userMsgList") + @ResponseBody + @ApiOperation(value = "查询seg用户消息列表", notes = "需要鉴权") + public TableDataInfo userMsgList(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireTableInfo(); + } + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + } + logger.debug("userMsgList with: {}", segchkUserWebReq.toString()); + startPage(); + List segchkUserWebSCRespList = segchkUserIndexService.selectUserMsgList(segchkUserWebReq); + return getDataTable(segchkUserWebSCRespList); + } + + + /** + * 用户进入余额充值页面时,根据用户id,运营商id查询可充值 的卡 + * { + * "userId": 465, + * "providerId": 4 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_charge:add')") + @PostMapping( "/userChargePre") + @ResponseBody + @ApiOperation(value = "查询seg用户可充值列表", notes = "需要鉴权") + public AjaxResult userChargePre(@RequestBody SegchkUserWebReq segchkUserWebReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserWebReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + if(!claims.getProviderId().equals(segchkUserWebReq.getProviderId())){ + logger.warn("userChargePre can not charg for user({}), because login prov({}) is not register prov({})", claims.getUserId(), segchkUserWebReq.getProviderId(), claims.getProviderId()); + return AjaxResult.error(400, "用户在漫游地区充值!"); + } + segchkUserWebReq.setUserLevel(claims.getUserLevel()); + segchkUserWebReq.setUserId(claims.getUserId()); + segchkUserWebReq.setProviderId(claims.getProviderId()); + + } + logger.debug("userChargePre with: {}", segchkUserWebReq.toString()); + List segchkUserChargeCards = segchkUserIndexService.SegchkUserChargePre(segchkUserWebReq); + AjaxResult ajax = new AjaxResult(); + + if(segchkUserChargeCards == null){ + ajax.put(CODE_TAG, "400"); + } + else{ + ajax.put(CODE_TAG, "200"); + ajax.put(DATA_TAG, segchkUserChargeCards); + } + return ajax; + } + + /** + * 用户进入余额充值页面时,根据用户id,运营商id查询可充值的卡,生成充值记录 未测试 + * { + * "userId": 465, + * "charge": 299.0, + * "accountUsed": 10.0, + * "cardTypeId": 1, + * "providerId": 4 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_charge:pre')") + @RepeatSubmit + @PostMapping( "/userChargeReq") + @ResponseBody + @ApiOperation(value = "seg用户可充值", notes = "需要鉴权") + public AjaxResult userChargeReq(@RequestBody SegchkUserCharge segchkUserCharge, HttpServletRequest request) + { + Claims claims = getLoing(request); + if(StringUtils.isEmpty(segchkUserCharge.getRemark())){ +// Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkUserCharge.setUserId(claims.getUserId()); + segchkUserCharge.setProviderId(claims.getProviderId()); + } + else { + claims = new Claims(); + claims.setUserId(segchkUserCharge.getUserId()); + claims.setUserLevel(2); + claims.setProviderId(segchkUserCharge.getProviderId()); + } + logger.debug("userChargeReq with: {}", segchkUserCharge.toString()); + int ret_flag = 0;//未完成,1成功,2失败 + AjaxResult ajax = new AjaxResult(); + if(segchkUserCharge.getAccountUsed() != null && segchkUserCharge.getAccountUsed().compareTo(new BigDecimal(0.0)) == 1) { +// 用户选择使用余额买卡 + BigDecimal user_account = segchkUserIndexService.getAccount(segchkUserCharge); + if(user_account == null || user_account.compareTo(segchkUserCharge.getAccountUsed()) == -1){ +// 用户余额不足 + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "余额不足!"); + return ajax; + } + if(user_account.compareTo(segchkUserCharge.getCharge()) > -1){ +// 用户余额大于充值额度,用户可以直接使用 + segchkUserCharge.setAccountUsed(segchkUserCharge.getCharge()); + segchkUserCharge.setCharge(new BigDecimal(0.0)); + ret_flag = 1; + logger.warn("userChargeReq useraccount({}) is big than charge({}) ", user_account, segchkUserCharge.getCharge()); + } + else { +// 用户余额小于充值金额 + segchkUserCharge.setAccountUsed(user_account); + segchkUserCharge.setCharge(segchkUserCharge.getCharge().subtract(user_account)); + } + + } + segchkUserCharge.setRetFlag(ret_flag); +// 生成充值订单 + int ret = segchkUserIndexService.insertSegchkUserCharge(segchkUserCharge); + if(ret < 1){ +// 生成失败。返回提示 + ajax.put(CODE_TAG, "500"); + ajax.put(MSG_TAG, "充值失败!"); + } + else{ +// 生成订单成功 + SegchkUserWechat segchkUserWechat = null; + if(!StringUtils.isEmpty(segchkUserCharge.getCharge())){ +// 如果待生成订单需要用户调起支付时 + + segchkUserWechat = getSegchkUserWechat(request, segchkUserCharge.getSearchValue(), claims); + + if(ObjectUtils.isEmpty(segchkUserWechat)){ + return AjaxResult.error(500, "微信绑定失败!"); + } + } + if(ret_flag == 1){ + return AjaxResult.error(201, "充值成功"); + } + String ipAddr = getIpAddr(request); + CommonResponse prepayResultCommonResponse = segchkUserIndexService.wechatAppletPay( + segchkUserCharge.getChargeId().toString() + , segchkUserCharge.getUserId() + , segchkUserCharge.getProviderId() + , (StringUtils.isEmpty(ipAddr) ? ipAddr : ipAddr.split(",")[0].trim()), 2); + switch (prepayResultCommonResponse.getFlag()){ + case -1: return AjaxResult.error(500, "用户不存在"); + case -5: return AjaxResult.error(500, "微信生成订单出错"); + case -7: return AjaxResult.error(500, "没有设置网站地址"); + case -8: return AjaxResult.error(500, "缺少配置"); + case -10: return AjaxResult.error(500, "没有绑定微信"); + case 1: { + /*WechatApletPrepayResult wechatApletPrepayResult = new WechatApletPrepayResult(); + wechatApletPrepayResult.setAppId(prepayResultCommonResponse.getData().getAppid()); + wechatApletPrepayResult.setPaySign(prepayResultCommonResponse.getData().getPay_sign()); + wechatApletPrepayResult.setPackage_(prepayResultCommonResponse.getData().getPackage_()); + wechatApletPrepayResult.setNonceStr(prepayResultCommonResponse.getData().getNonce_str()); + wechatApletPrepayResult.setTimeStamp(prepayResultCommonResponse.getData().getTime_stamp());*/ + + return AjaxResult.success("充值成功", prepayResultCommonResponse); + } + default: return AjaxResult.error(600, "未知错误"); + } +// ajax.put(CODE_TAG, "200"); +// ajax.put(MSG_TAG, "充值成功!"); +// ajax.put(DATA_TAG, prepayResultCommonResponse); + } + return ajax; + } + + /** + * 充值结果回调接口,接口微信的支付结果,更新充值结果, ret 0成功,其他失败 + * { + * "chargeId": "demoData",//* + * "ret": 0//*0成功,其他失败 + * } + */ +// @Log(title = "seg用户充值结果回调", businessType = BusinessType.UPDATE) + @PostMapping( "/userChargeResult") + @ResponseBody + @ApiOperation(value = "seg用户充值结果回调", notes = "需要鉴权") + public void userChargeResult(String chargeId, int ret, HttpServletRequest request) + { + + segchkUserIndexService.chargeRet(chargeId, ret); + } + + /** + * 微信支付回调 + */ + @RequestMapping("/wechatnotify") + @UnAuth + @ApiIgnore + public void weChatNotify(HttpServletRequest request, HttpServletResponse response) throws IOException { + if (segchkUserIndexService.weChatAppletNotify(request.getInputStream()) > 0) { + sendMessage(response, WechatUtils.SUCCESS_RETURN); + } + } + + /** + * 用户点击提现时的反应 未测试 + * { + * "userId": 459, + * "cash": 5.6, + * "providerId": 4, + * "userLevel": 2 + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_cash:add')") + @PostMapping( "/userCashReq") + @ResponseBody + @ApiOperation(value = "seg用户提现请求", notes = "需要鉴权") + public AjaxResult userCashReq(@RequestBody SegchkUserCashOpsReq segchkUserCashOpsReq, HttpServletRequest request) + { + Claims claims = getLoing(request); + if(StringUtils.isEmpty(segchkUserCashOpsReq.getRemark())){ + + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkUserCashOpsReq.setUserId(claims.getUserId()); + segchkUserCashOpsReq.setProviderId(claims.getProviderId()); + segchkUserCashOpsReq.setUserLevel(claims.getUserLevel()); + } + else { + claims = new Claims(); + claims.setUserLevel(segchkUserCashOpsReq.getUserLevel()); + claims.setUserId(segchkUserCashOpsReq.getUserId()); + claims.setProviderId(segchkUserCashOpsReq.getProviderId()); + } + logger.debug("userCashReq with: {}", segchkUserCashOpsReq.toString()); + AjaxResult ajax = new AjaxResult(); + if(segchkUserCashOpsReq.getUserLevel() == 0){ + return AjaxResult.error(301, "运营商无法线上提现"); + } + SegchkUserWechat segchkUserWechat = null; + segchkUserWechat = getSegchkUserWechat(request, segchkUserCashOpsReq.getSearchValue(), claims); + + if(ObjectUtils.isEmpty(segchkUserWechat)){ + return AjaxResult.error(500, "微信绑定失败!"); + } +// segchkUserCashOpsReq.setUserLevel(2); + segchkUserCashOpsReq.setSearchValue(segchkUserWechat.getOpenid()); + String ipAddr = getIpAddr(request); + int ret = segchkUserIndexService.getAccountForCash(segchkUserCashOpsReq, (StringUtils.isEmpty(ipAddr) ? ipAddr : ipAddr.split(",")[0].trim())); + switch (ret){ + case -1: return AjaxResult.error(401, "无余额信息"); + case -2: return AjaxResult.error(402, "无余额信息"); + case -3: return AjaxResult.error(403, "提现受限"); + case -4: return AjaxResult.error(404, "余额不足"); + case -5: + case -8: + case -11: + case -12: + case -9: return AjaxResult.error(405, "提现异常,请联系平台客服"); + case -10: return AjaxResult.error(410, "微信未绑定"); + case 1: { + return AjaxResult.error(200, "提现成功"); + } + default: ajax.put(CODE_TAG, "500");ajax.put(MSG_TAG, "未知错误");break; + } + return ajax; + } + + /** + * 设置用户信息 未测试 + * { + * "userId": 43,//* + * "passwd": "sfsdfds",//* + * "providerId": 2,//* + * "userLevel": 2//* + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_set:add')") +// @Log(title = "seg设置用户信息", businessType = BusinessType.UPDATE) + @PostMapping( "/SetInfo") + @ResponseBody + @ApiOperation(value = "seg设置用户信息", notes = "需要鉴权") + public AjaxResult SetInfo(@RequestBody SegchkUserSetInfoReq segchkUserSetInfoReq, HttpServletRequest request) + { + + if(StringUtils.isEmpty(segchkUserSetInfoReq.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkUserSetInfoReq.setUserId(claims.getUserId()); + segchkUserSetInfoReq.setProviderId(claims.getProviderId()); + segchkUserSetInfoReq.setUserLevel(claims.getUserLevel()); + } + logger.debug("SetInfo with: {}", segchkUserSetInfoReq.toString()); + int ret = 0; + if(segchkUserSetInfoReq.getUserLevel() == 2) { + ret = segchkUserIndexService.updateUserInfo(segchkUserSetInfoReq); + } + else if(segchkUserSetInfoReq.getUserLevel() == 1){ + ret = segchkStoreIndexService.updateUserInfo(segchkUserSetInfoReq); + } + return toAjax(ret); + } + + + /** + * seg设置用户实名信息 未测试 + * { + * "userName": "demoData", + * "userId": 0, + * "providerId": 0, + * "IDcard": "demoData", + * "card1": "demoData", + * "card2": "demoData" + * } + */ +// @PreAuthorize("@ss.hasPermi('segchk:user_certicify:add')") +// @Log(title = "seg设置用户实名信息", businessType = BusinessType.UPDATE) + @PostMapping( "/userCerticify") + @ResponseBody + @ApiOperation(value = "seg设置用户实名信息", notes = "需要鉴权") + public AjaxResult user_certicify(@RequestBody SegchkUserCertificationInfo segchkUserCertificationInfo, HttpServletRequest request) + { + int ret = 0; + + if(StringUtils.isEmpty(segchkUserCertificationInfo.getRemark())){ + Claims claims = getLoing(request); + if (ObjectUtils.isEmpty(claims)) { +// 如果用户未登录,则要求用户使用手机号登录注册 + return LoginRequireAjax(); + } + segchkUserCertificationInfo.setUserId(claims.getUserId()); + segchkUserCertificationInfo.setProviderId(claims.getProviderId()); +// segchkUserCertificationInfo.setUserLevel(claims.getUserLevel()); + } + logger.debug("user_certicify with: {}", segchkUserCertificationInfo.toString()); + ret = segchkUserIndexService.userCerticify(segchkUserCertificationInfo); + return toAjax(ret); + } + + + /** + * 提现结果回调接口,接口微信的支付结果,更新充值结果, ret 0成功,其他失败 + * { + * "chargeId": "45435", + * "userLevel": "1/2/0", + * "ret": 1 + * } + */ +// @Log(title = "seg提现结果回调", businessType = BusinessType.UPDATE) + @PostMapping( "/userCashResult") + @ResponseBody + @ApiOperation(value = "seg提现结果回调", notes = "需要鉴权") + public void userCashResult(String chargeId, int userLevel, int ret, HttpServletRequest request) + { + if(userLevel == 1) { + segchkStoreIndexService.cashRet(chargeId, ret); + } + else if(userLevel == 2){ + segchkUserIndexService.cashRet(chargeId, ret); + } + } + +// 返回注册登录提示 + private AjaxResult LoginRequireAjax() { + return AjaxResult.error(300, "请先登录注册"); + } + + private TableDataInfo LoginRequireTableInfo() { + TableDataInfo tableDataInfo = new TableDataInfo(); + tableDataInfo.setCode(300); + tableDataInfo.setMsg("请先登录注册"); + return tableDataInfo; + } + +// 获取登录信息 + private Claims getLoing(HttpServletRequest request){ + String token = null; + try { + token = getToken(request); + }catch (Exception e){ + e.printStackTrace(); + return null; + } + Claims claims = getClaims(token); + if(!ObjectUtils.isEmpty(claims)){ + if(loginexpire == -1){ + redisService.setCacheObject(token, claims); + } + else { + redisService.setCacheObject(token, claims, loginexpire, TimeUnit.HOURS); + } + } + return claims; + } + + /** + * 获取小程序凭证实体 + * + * @param token token + * @return 小程序凭证实体 + */ + private Claims getClaims(String token) { + + Object claims = redisService.getCacheObject(token); + logger.debug("getClaims---token:{} Claims:{}", token, claims); + return ObjectUtils.isEmpty(claims) ? null : (Claims) claims; + } + + private SegchkUserWechat getSegchkUserWechat(HttpServletRequest request, String code, Claims claims) { + String token = getToken(request); + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_BIND_OPENID).append("-").append(token); +// SegchkUserWechat segchkUserWechat = redisService.getCacheObject(sb.toString()); + SegchkUserWechat segchkUserWechat = weChatCustomerLinkService.getSegchkUserWechat(claims, sb.toString()); +// 暂时未解决重复获取openid问题 +// segchkUserWechat = null; + if(ObjectUtils.isEmpty(segchkUserWechat) || ObjectUtils.isEmpty(segchkUserWechat.getOpenid())){ +// redis没有用户微信openid时,重新获取 + segchkUserWechat = new SegchkUserWechat(); + WechatPaySet wechatAppletPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + WechatSetting wechatSetting = new WechatSetting(); + wechatSetting.setAppId(wechatAppletPaySet.getAppId()); + wechatSetting.setAppSecret(wechatAppletPaySet.getAppSecret()); + if (!wechatSetting.checkAppletOAuthParams()) { + logger.error("getLoginInfo fail:checkAppletOAuthParams fail"); + return null; + } + WeChatAppletLoginResponse weChatAppletLoginResponse = WeChatAppletUtils.getLoginInfo(code, wechatSetting); + if (Objects.isNull(weChatAppletLoginResponse)) { + logger.error("getLoginInfo fail: getLoginInfo fail"); + return null; + } + segchkUserWechat.setOpenid(weChatAppletLoginResponse.getOpenid()); + segchkUserWechat.setUnionId(weChatAppletLoginResponse.getUnionid()); +// redisService.setCacheObject(sb.toString(), segchkUserWechat, 7200, TimeUnit.SECONDS); + segchkUserWechat.setUserId(claims.getUserId()); + segchkUserWechat.setProviderId(claims.getProviderId()); + int ret = weChatCustomerLinkService.addSegchkUserWechat(segchkUserWechat, String.valueOf(claims.getUserLevel()), sb.toString()); + if(ret < 1){ + logger.error("addSegchkUserWechat failed with ({}) --- ({})", segchkUserWechat.toString(), claims); + } + logger.debug("getSegchkUserWechat update user wechat with ({})---({})", segchkUserWechat.toString(), claims); + } + logger.debug("getSegchkUserWechat get res ({})", ObjectUtils.isEmpty(segchkUserWechat) ? null : segchkUserWechat.toString()); + return ObjectUtils.isEmpty(segchkUserWechat) ? null : (SegchkUserWechat) segchkUserWechat; + + + } + /** + * 获取token + * + * @param request request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer")) { + logger.info("getClaims fail :Authorization fail "); + throw new UnAuthorizedException(ResultCode.WX_NOT_AUTHORIZED); + } + return authHeader.length() >= 7 ? authHeader.substring(7) : authHeader.substring(6); + } + + /** + * 回传信息 + * + * @param message 信息 + */ + private void sendMessage(HttpServletResponse response, String message) { + logger.debug("sendMessage with: {}", message); + PrintWriter out = null; + try { + out = response.getWriter(); + out.println(message); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + out.close(); + } + + } + + private static class RemoveIds extends BaseEntity { + private Long userId; + private String ids; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getIds() { + return ids; + } + + public void setIds(String ids) { + this.ids = ids; + } + } + + /** + * 创建二维码图片 + * + * @param url 链接地址 + * @param width 宽 + * @param height 高 + */ + private void createQRImg(HttpServletResponse response, String url, Integer width, Integer height) { + logger.debug("createQRImg with: {}---w:{}---h:{}", url, width, height); + OutputStream outputStream = null; + try { + outputStream = response.getOutputStream(); + QRCodeUtils.createQrCode(url, width, height, "jpg", outputStream, qrPath, posterPath); + logger.debug("createQRImg qrPath: {}, posterPath: {}", qrPath, posterPath); + outputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/util/CommonController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/CommonController.java new file mode 100644 index 0000000..21fe1d9 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/CommonController.java @@ -0,0 +1,158 @@ +package com.ruoyi.util; + +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; +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 javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 通用请求处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/default/common") +public class CommonController +{ + private static final Logger log = LoggerFactory.getLogger(CommonController.class); + + @Autowired + private ServerConfig serverConfig; + + /** + * 通用下载请求 + * + * @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 + { + if(file == null) { + log.warn("upload file is null!!!"); + return AjaxResult.error(500, "文件为空!"); + } + try + { + log.debug("upload with: {}", file.getOriginalFilename()); + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + // 上传并返回新文件名称 + + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + + /** + * 上传用户身份证照片 + */ + @PostMapping("/user_cert") + public AjaxResult userCert(MultipartFile file) throws Exception + { + if(file == null) { + log.warn("upload file is null!!!"); + return AjaxResult.error(500, "文件为空!"); + } + try + { + log.debug("upload userCert with: {}", file.getOriginalFilename()); + // 上传文件路径 + String filePath = RuoYiConfig.getProfile() + "/user_cert"; + // 上传并返回新文件名称 + + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + 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-segchk-web/src/main/java/com/ruoyi/util/HtmlController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/HtmlController.java new file mode 100644 index 0000000..38d0773 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/HtmlController.java @@ -0,0 +1,90 @@ +package com.ruoyi.util; + + +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.segchk.service.ISegchkSystemSettingService; +import com.ruoyi.setting.service.BaseInfoSetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.HttpServletResponse; + +/** + * Created by 魔金商城 on 17/7/14. + * 生成html的控制器 + */ +@Api(description = "生成html接口") +@Controller +@RequestMapping("/default/html") +public class HtmlController { + + + /** + * 协议模版 + */ + private static final String PROTOCOL_TEMPLATE = "template"; + + + /** + * 注入基本信息服务接口 + */ +// @Autowired +// private BaseInfoSetService baseInfoSetService; + + @Autowired + private ISegchkSystemSettingService segchkSystemSettingService; + + /** + * 获取注册协议 + * + * @throws Exception 异常 + */ + @ApiOperation(value = "获取注册协议", notes = "获取注册协议(不需要认证)") + @RequestMapping(value = "/registerProtocol", method = RequestMethod.GET) + @UnAuth + public void register_protocol(HttpServletResponse response) throws Exception { + response.setContentType("text/html; charset=UTF-8"); + response.getWriter().print(createHtml(PROTOCOL_TEMPLATE, segchkSystemSettingService.queryBaseInfoSet().getSiteRegisterProtocol())); + } + + /** + * 获取隐私协议 + * + * @throws Exception 异常 + */ + @ApiOperation(value = "获取隐私协议", notes = "获取隐私协议(不需要认证)") + @RequestMapping(value = "/userPrivacyAgreement", method = RequestMethod.GET) + @UnAuth + public void user_privacy_agreement(HttpServletResponse response) throws Exception { + response.setContentType("text/html; charset=UTF-8"); + response.getWriter().print(createHtml(PROTOCOL_TEMPLATE, segchkSystemSettingService.queryBaseInfoSet().getUserPrivacyAgreement())); + } + + + /** + * 获取会员服务协议 + * + * @throws Exception 异常 + */ + @ApiOperation(value = "获取会员服务协议", notes = "获取会员服务协议(不需要认证)") + @RequestMapping(value = "/vipServiceAgreement", method = RequestMethod.GET) + @UnAuth + public void vip_service_agreement(HttpServletResponse response) throws Exception { + response.setContentType("text/html; charset=UTF-8"); + response.getWriter().print(createHtml(PROTOCOL_TEMPLATE, segchkSystemSettingService.queryBaseInfoSet().getVipServiceAgreement())); + } + + /** + * 生成html + * + * @param html 要替换的内容 + * @return 返回html + */ + private String createHtml(String template, String html) { + return template.replaceAll("template", html); + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/util/IndexController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/IndexController.java new file mode 100644 index 0000000..dcb9fa9 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/IndexController.java @@ -0,0 +1,33 @@ +package com.ruoyi.util; + +import com.ruoyi.common.core.controller.BaseController; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class IndexController extends BaseController { + + @Value("${segchk.wxchecktxt:#{null}}") + private String wxchecktxt; + + @RequestMapping("PwPaX4PqzG.txt") + public String wxPrivateKey(){ + //直接返回你下载的授权文件里的内容就好 + logger.debug("wxPrivateKey with: {}", wxchecktxt); + return wxchecktxt; + } + + @RequestMapping("/default/PwPaX4PqzG.txt") + public String defaultwxPrivateKey(){ + //直接返回你下载的授权文件里的内容就好 + logger.debug("wxPrivateKey with: {}", wxchecktxt); + return wxchecktxt; + } + + @GetMapping("getWxAccessToken") + public String getWxAccessToken(){ + return null; + } +} diff --git a/ruoyi-segchk-web/src/main/java/com/ruoyi/util/QrCodeController.java b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/QrCodeController.java new file mode 100644 index 0000000..528ce25 --- /dev/null +++ b/ruoyi-segchk-web/src/main/java/com/ruoyi/util/QrCodeController.java @@ -0,0 +1,118 @@ +package com.ruoyi.util; + +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.annotation.UnAuth; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.login.SegChkLoginController; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import springfox.documentation.annotations.ApiIgnore; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; + +/** + * 二维码控制器 + * + * @author 魔金商城 created on 2020/6/23 + */ +@Controller +@Api(description = "二维码接口") +public class QrCodeController { + + private static final Logger logger = LoggerFactory.getLogger(QrCodeController.class); + + @Value("${segchk.qr_path}") + private String qrPath; + + @Value("${segchk.poster_path}") + private String posterPath; + + /** + * 创建二维码图片 + * + * @param url 地址 + * @param w 宽 + * @param h 高 + */ + @RepeatSubmit + @RequestMapping("/createqrcode") + @ResponseBody + @UnAuth + @ApiIgnore + @ApiImplicitParams({ + @ApiImplicitParam(paramType = "form", dataType = "String", name = "url", value = "地址"), + @ApiImplicitParam(paramType = "form", dataType = "Integer", name = "w", value = "宽"), + @ApiImplicitParam(paramType = "form", dataType = "Integer", name = "h", value = "高"), + }) + public AjaxResult createQrCode(HttpServletResponse response, String url, Integer w, Integer h) { + createQRImg(response, url, w, h); + return AjaxResult.error(500,"ok"); + } + + + @PostMapping("qRCode") + public void qRCode(HttpServletResponse response, String savePath) { + + try { + PosterUtils.createPoster("标题", "recm=1&recV=2", "100.0", null, qrPath, savePath, "/pages/dfsdf"); + } catch (Exception e) { + e.printStackTrace(); + } + //获取生成海报的图片路径 +// qRCodeNew(storeId, response); + } + + /*private void qRCodeNew(String storeId, HttpServletResponse response) { + OutputStream outputStream = null; + try { + outputStream = response.getOutputStream(); + QRCodeUtils.qRCode(storeId, "jpg", qrPath, posterPath, outputStream); + outputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }*/ + + /** + * 创建二维码图片 + * + * @param url 链接地址 + * @param width 宽 + * @param height 高 + */ + private void createQRImg(HttpServletResponse response, String url, Integer width, Integer height) { + OutputStream outputStream = null; + try { + logger.debug("createQRImg qrPath: {}, posterPath: {}", qrPath, posterPath); + outputStream = response.getOutputStream(); + QRCodeUtils.createQrCode(url, width, height, "jpg", outputStream, qrPath, posterPath); + + outputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } +} diff --git a/ruoyi-segchk-web/src/main/resources/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/application-dev.yml b/ruoyi-segchk-web/src/main/resources/application-dev.yml new file mode 100644 index 0000000..7288d34 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/application-dev.yml @@ -0,0 +1,156 @@ +# 项目相关配置 商城端 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.0.0 + # 版权年份 + copyrightYear: 2019 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置F:\ideaproj\RuoYi-Vue\uploadPath + #,Linux配置 /root/yzychk_vue/uploadPath) + profile: F:\ideaproj\RuoYi-Vue\uploadPath\applet + # 获取ip地址开关 + addressEnabled: false + +server: + # 服务器的HTTP端口,默认为 8091 测试 9092 + port: 8091 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 数据源配置 +spring: + # 文件上传 + servlet: + multipart: + # 单个文件大小 + max-file-size: 10MB + # 设置总上传的文件大小 + max-request-size: 20MB + # 服务模块 + devtools: + restart: + # 热部署开关 + enabled: true + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.30:8306/segchksaas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: kaletest_yinzy + password: XMG2-Rel.2 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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: + login-password: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + # redis 配置 + redis: + # 地址 + host: 192.168.2.40 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 3 + # 密码 + password: seg_123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms +yzytest: + login: + smshost: http://api.ksd106.com:8088/SMSSend.aspx + smssign: + smstest: true + smsplatid: 3 +# 登录超时时长,单位天, -1永久有效 + loginexpire: 8 + +segchk: + # 提现额度 + cash: + # 商户提现额度 + store_threshold: 300.0 + # 用户提现额度 + user_threshold: 10.0 + sandbox: 1 + default_district: 140100 + recommendstore: + distince: 50 + qr_path: C:\Users\Public\Desktop\dome.jpg + poster_path: F:\ideaproj\RuoYi-Vue\ruoyi-segchk\src\main\resources\templates\posters\bg.jpg +# 核消二维码保存路径,测试使用。正常不打开 + check_qr_path: C:\Users\Public\Desktop\checkqr.jpg +# 核消二维码背景路径,可有,可无 +# check_poster_path: F:\ideaproj\RuoYi-Vue\ruoyi-segchk\src\main\resources\templates\posters\bg.jpg + + chkurl: '127.0.0.1:8091/default/store/ServiceCheckTest?likegoId=%s&storeId=%s' + chk_height: 350 + chk_weight: 350 + wxchecktxt: 1bc40f067f30d2f520200d504238a620 + + share: + title: 卡乐分享 + desc: 卡乐svip无限享受 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/application-prod.yml b/ruoyi-segchk-web/src/main/resources/application-prod.yml new file mode 100644 index 0000000..84ca494 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/application-prod.yml @@ -0,0 +1,159 @@ +# 项目相关配置 商城端 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.0.0 + # 版权年份 + copyrightYear: 2019 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置F:\ideaproj\RuoYi-Vue\uploadPath + #,Linux配置 /root/yzychk_vue/uploadPath) + profile: /home/seg_yinzy/data/applet + # 获取ip地址开关 + addressEnabled: false + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为 8091 测试 9092 + port: 9092 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.30:8306/segchksaas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: segchksaas + password: 2wsx@WSX + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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: + login-password: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + # redis 配置 + redis: + # 地址 + host: 192.168.2.40 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 2 + # 密码 + password: seg_123456 + # 连接超时时间 + timeout: 1000 + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 8 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 2 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: 300 + + +yzytest: + login: + smshost: http://api.ksd106.com:8088/SMSSend.aspx + smssign: + smstest: false + smsplatid: 3 + # 登录超时时长,单位天, -1永久有效 + loginexpire: 8 + +segchk: + # 提现额度 + cash: + # 商户提现额度 + store_threshold: 300.0 + # 用户提现额度 + user_threshold: 10.0 + sandbox: 1 + default_district: 410100 + recommendstore: + distince: 50 + qr_path: /home/seg_yinzy/data/applet/poster/dome.jpg + poster_path: /home/seg_yinzy/data/applet/poster/bg1.jpg + # 核消二维码保存路径,测试使用。正常不打开 + check_qr_path: /home/seg_yinzy/data/applet/poster/checkqr.jpg + # 核消二维码背景路径,可有,可无 + # check_poster_path: /home/segchk/data/resources/check/poster/bg1.jpg + + + chkurl: '/default/store/ServiceCheckTest?likegoId=%s&storeId=%s' + chk_height: 400 + chk_weight: 400 + + + + # 商户推广二维码 + store_qr_path: /home/seg_yinzy/data/applet/poster/storeqr + # 商户推广二维码背景路径,可有,可无 + store_poster_path: /home/seg_yinzy/data/applet/poster/bg1.jpg + + sto_height: 350 + sto_weight: 350 + storeurl: 'https://kale.segsvip.com/prod-wechat/default/store/storerecommend?recC=%s&recV=%s' + wxchecktxt: 1bc40f067f30d2f520200d504238a620 + + share: + title: 卡乐分享 + desc: 卡乐svip无限享受 diff --git a/ruoyi-segchk-web/src/main/resources/application-test.yml b/ruoyi-segchk-web/src/main/resources/application-test.yml new file mode 100644 index 0000000..da8389c --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/application-test.yml @@ -0,0 +1,158 @@ +# 项目相关配置 商城端 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 3.0.0 + # 版权年份 + copyrightYear: 2019 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置F:\ideaproj\RuoYi-Vue\uploadPath + #,Linux配置 /root/yzychk_vue/uploadPath) + profile: /home/seg_yinzy/data/applet + # 获取ip地址开关 + addressEnabled: false + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为 8091 测试 9092 + port: 9192 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + min-spare-threads: 30 + +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.30:8306/kaletest?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: segchksaas + password: 2wsx@WSX + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 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: + login-password: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + # redis 配置 + redis: + # 地址 + host: 192.168.2.40 + # 端口,默认为6379 + port: 63795 + # 数据库索引 + database: 2 + # 密码 + password: seg_123456 + # 连接超时时间 + timeout: 1000 + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 8 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 2 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: 300 + + +yzytest: + login: + smshost: http://api.ksd106.com:8088/SMSSend.aspx + smssign: + smstest: true + smsplatid: 3 +# 登录超时时长,单位天, -1永久有效 + loginexpire: 8 + +segchk: +# 提现额度 + cash: +# 商户提现额度 + store_threshold: 300.0 +# 用户提现额度 + user_threshold: 10.0 + default_district: 410100 + recommendstore: + distince: 50 + qr_path: /home/seg_yinzy/data/applet/poster/dome.jpg + poster_path: /home/seg_yinzy/data/applet/poster/bg1.jpg + # 核消二维码保存路径,测试使用。正常不打开 + check_qr_path: /home/seg_yinzy/data/applet/poster/checkqr.jpg + # 核消二维码背景路径,可有,可无 +# check_poster_path: /home/segchk/data/resources/check/poster/bg1.jpg + + + chkurl: '/default/store/ServiceCheckTest?likegoId=%s&storeId=%s' + chk_height: 400 + chk_weight: 400 + + + + # 商户推广二维码 + store_qr_path: /home/seg_yinzy/data/applet/poster/storeqr + # 商户推广二维码背景路径,可有,可无 + store_poster_path: /home/seg_yinzy/data/applet/poster/bg1.jpg + + sto_height: 350 + sto_weight: 350 + storeurl: 'https://kaletest.segsvip.com/prod-wechat/default/store/storerecommend?recC=%s&recV=%s' + wxchecktxt: 1bc40f067f30d2f520200d504238a620 + + share: + title: 卡乐分享 + desc: 卡乐svip无限享受 diff --git a/ruoyi-segchk-web/src/main/resources/application-uat.yml b/ruoyi-segchk-web/src/main/resources/application-uat.yml new file mode 100644 index 0000000..46af5b0 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/application-uat.yml @@ -0,0 +1,71 @@ +#配置数据源 +spring: + datasource: + druid: + master: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.jdbc.Driver + url: jdbc:mysql://172.22.4.2:3306/wsfmall_uat?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull + username: root + password: oywkpjEi9MW4NL9mR88YTydj9wHE5E + # 初始化连接大小 + initial-size: 5 + # 最小空闲连接数 + min-idle: 5 + max-active: 20 + max-wait: 30000 + # 可关闭的空闲连接间隔时间 + time-between-eviction-runs-millis: 60000 + # 配置连接在池中的最小生存时间 + min-evictable-idle-time-millis: 300000 + validation-query: select '1' from dual + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 打开PSCache,并且指定每个连接上PSCache的大小 + pool-prepared-statements: true + max-open-prepared-statements: 20 + max-pool-prepared-statement-per-connection-size: 20 + slave1: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.jdbc.Driver + url: jdbc:mysql://172.22.4.2:3306/wsfmall_uat?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull + username: root + password: oywkpjEi9MW4NL9mR88YTydj9wHE5E + # 初始化连接大小 + initial-size: 5 + # 最小空闲连接数 + min-idle: 5 + max-active: 20 + max-wait: 30000 + # 可关闭的空闲连接间隔时间 + time-between-eviction-runs-millis: 60000 + # 配置连接在池中的最小生存时间 + min-evictable-idle-time-millis: 300000 + validation-query: select '1' from dual + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 打开PSCache,并且指定每个连接上PSCache的大小 + pool-prepared-statements: true + max-open-prepared-statements: 20 + max-pool-prepared-statement-per-connection-size: 20 + redis: + host: 172.22.0.4 + port: 6379 + timeout: 100 + lettuce: + pool: + max-active: 8 + max-idle: 8 + min-idle: 2 + max-wait: 300 + password: sfakjfiju99jjf87LJSDDU8 + data: + elasticsearch: + cluster-nodes: 172.22.0.4:9300 + messages: + basename: messages/messages + servlet: + multipart: + max-file-size: 15MB \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/application.yml b/ruoyi-segchk-web/src/main/resources/application.yml new file mode 100644 index 0000000..50dc9d1 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/application.yml @@ -0,0 +1,121 @@ +# 项目相关配置 商城端 +#ruoyi: +# # 名称 +# name: RuoYi +# # 版本 +# version: 3.0.0 +# # 版权年份 +# copyrightYear: 2019 +# # 实例演示开关 +# demoEnabled: true +# # 文件路径 示例( Windows配置F:\ideaproj\RuoYi-Vue\uploadPath +# #,Linux配置 /root/yzychk_vue/uploadPath) +# profile: F:\ideaproj\RuoYi-Vue\uploadPath +# # 获取ip地址开关 +# addressEnabled: false + +# 开发环境配置 +#server: +# # 服务器的HTTP端口,默认为 8091 测试 9092 +# port: 8091 +# servlet: +# # 应用的访问路径 +# context-path: / +# tomcat: +# # tomcat的URI编码 +# uri-encoding: UTF-8 +# # tomcat最大线程数,默认为200 +# max-threads: 800 +# # Tomcat启动初始化的线程数,默认值25 +# min-spare-threads: 30 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + +# Spring配置 +spring: + # 资源信息 + messages: + # 国际化资源文件路径 + basename: i18n/messages + profiles: + active: kaleprod +# # 文件上传 +# servlet: +# multipart: +# # 单个文件大小 +# max-file-size: 10MB +# # 设置总上传的文件大小 +# max-request-size: 20MB +# # 服务模块 +# devtools: +# restart: +# # 热部署开关 +# enabled: true +# # redis 配置 +# redis: +# # 地址 +# host: 10.1.192.113 +# # 端口,默认为6379 +# port: 63795 +# # 数据库索引 +# database: 0 +# # 密码 +# password: retinabd@2020 +# # 连接超时时间 +# timeout: 10s +# lettuce: +# pool: +# # 连接池中的最小空闲连接 +# min-idle: 0 +# # 连接池中的最大空闲连接 +# max-idle: 8 +# # 连接池的最大数据库连接数 +# max-active: 8 +# # #连接池最大阻塞等待时间(使用负值表示没有限制) +# max-wait: -1ms + +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 3000 + +# MyBatis配置 +mybatis: + # 搜索指定包别名 + typeAliasesPackage: com.ruoyi.**.domain + # 配置mapper的扫描,找到所有的mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的配置文件 + configLocation: classpath:mybatis/mybatis-config.xml + +# PageHelper分页插件 +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +# Swagger配置 +swagger: + # 是否开启swagger + enabled: true + # 请求前缀 + pathMapping: /dev-api + +# 防止XSS攻击 +xss: + # 过滤开关 + enabled: true + # 排除链接(多个用逗号分隔) + excludes: /system/notice/* + # 匹配链接 + urlPatterns: /system/*,/monitor/*,/tool/* + diff --git a/ruoyi-segchk-web/src/main/resources/http-client.private.env.json b/ruoyi-segchk-web/src/main/resources/http-client.private.env.json new file mode 100644 index 0000000..542be06 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/http-client.private.env.json @@ -0,0 +1,60 @@ +{ + "dev": { + "name": "value", + "host": "http://localhost:8091", + "bindtoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0tDCwtLDQUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVhNTC4taAAAAAP__.diChD7JjY3y8SBNTBE8ACoNWWIuz-r-mHESPfL73eZI", + "bindtoken1": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzYyNDQwNDLVUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVmNzI9NaAAAAAP__.Y5uJzL55q9baNor4ScWmVg9UZyfHkTxZ0Oz79guiXXg", +// "token2": "APPLET_LOGIN_KEY_885553054366171136abcdefghijklmnopqrstuvwxyz", + "token3": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUipPTc5ILMnJT8_MU9JRykwsUbIyNDM2NDQ3sDAx0VEqLU4t8kxRsjLWUSooyi_LTIFwjSAyPqllqTlgXmpFAUyjCRDUAgAAAP__.5qRMCYs8YUoFJdSo_XSZiGlqJ13LGa20qJAT8GoiMHg", + "providertoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0MjC1MDTWUSotTi3yTFGyMtJRKijKL8tMgXNBMj6pZak5SlYGOkqpFQUwjZYmhsa1AAAAAP__.DkyBrM5f7G0eLi7DnYpgAqGTYnLaWRrpD3xemTa1s3k", + "store_search": + { + "providerId": 2, + "sortType": 0, + "storeName": "99", + "lableName": "99", + "typeId": 1, + "userLon": 114.123456, + "userLat": 43.123456 + } + }, + "prod-test": { + "name": "value", + "host": "https://kaletest.segsvip.com/prod-wechat", + "bindtoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0tDCwtLDQUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVhNTC4taAAAAAP__.diChD7JjY3y8SBNTBE8ACoNWWIuz-r-mHESPfL73eZI", + "bindtoken1": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzYyNDQwNDLVUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVmNzI9NaAAAAAP__.Y5uJzL55q9baNor4ScWmVg9UZyfHkTxZ0Oz79guiXXg", +// "token2": "APPLET_LOGIN_KEY_885553054366171136abcdefghijklmnopqrstuvwxyz", + "token3": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUipPTc5ILMnJT8_MU9JRykwsUbIyNDM2NDQ3sDAx0VEqLU4t8kxRsjLWUSooyi_LTIFwjSAyPqllqTlgXmpFAUyjCRDUAgAAAP__.5qRMCYs8YUoFJdSo_XSZiGlqJ13LGa20qJAT8GoiMHg", + "providertoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0MjC1MDTWUSotTi3yTFGyMtJRKijKL8tMgXNBMj6pZak5SlYGOkqpFQUwjZYmhsa1AAAAAP__.DkyBrM5f7G0eLi7DnYpgAqGTYnLaWRrpD3xemTa1s3k", + "store_search": + { + "providerId": 2, + "sortType": 0, + "storeName": "99", + "lableName": "99", + "typeId": 1, + "userLon": 114.123456, + "userLat": 43.123456 + } + }, + "prod": { + "name": "value", + "host": "https://kale.segsvip.com/prod-wechat", + "hostbak": "https://kale.segsvip.com/prod-api", + "bindtoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0tDCwtLDQUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVhNTC4taAAAAAP__.diChD7JjY3y8SBNTBE8ACoNWWIuz-r-mHESPfL73eZI", + "bindtoken1": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzYyNDQwNDLVUSotTi3yTFGyMjUw1lEqKMovy0yBCBhB5HxSy1JzwLzUigKYVmNzI9NaAAAAAP__.Y5uJzL55q9baNor4ScWmVg9UZyfHkTxZ0Oz79guiXXg", + // "token2": "APPLET_LOGIN_KEY_885553054366171136abcdefghijklmnopqrstuvwxyz", + "token3": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUipPTc5ILMnJT8_MU9JRykwsUbIyNDM2NDQ3sDAx0VEqLU4t8kxRsjLWUSooyi_LTIFwjSAyPqllqTlgXmpFAUyjCRDUAgAAAP__.5qRMCYs8YUoFJdSo_XSZiGlqJ13LGa20qJAT8GoiMHg", + "providertoken": "eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUnIMCPBxDYn38Xf39Iv3do1U0lHKTCxRsjI0MzY0MjC1MDTWUSotTi3yTFGyMtJRKijKL8tMgXNBMj6pZak5SlYGOkqpFQUwjZYmhsa1AAAAAP__.DkyBrM5f7G0eLi7DnYpgAqGTYnLaWRrpD3xemTa1s3k", + "store_search": + { + "providerId": 2, + "sortType": 0, + "storeName": "99", + "lableName": "99", + "typeId": 1, + "userLon": 114.123456, + "userLat": 43.123456 + } + } +} \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/logback-spring.xml b/ruoyi-segchk-web/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..a3cd82a --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/logback-spring.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + + + + ${INFO_LOG_FILE_NAME_PATTERN} + + 14 + + 30GB + + + 50MB + + + + ${FILE_LOG_PATTERN} + + + + + + + + ${ERROR_LOG_FILE_NAME_PATTERN} + + 30 + + 1GB + + + 10MB + + + + ${FILE_LOG_PATTERN} + + + + error + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/messages/messages.properties b/ruoyi-segchk-web/src/main/resources/messages/messages.properties new file mode 100644 index 0000000..e9a2292 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/messages/messages.properties @@ -0,0 +1,6 @@ +#################################### +## \u7ED3\u679C\u7801\u4FE1\u606F\u5B9A\u4E49 ## +##################################### +R-00002=\u5C0F\u7A0B\u5E8F\u672A\u6388\u6743 +R-00003=\u5C0F\u7A0B\u5E8F\u672A\u548C\u7528\u6237\u7ED1\u5B9A +R-00004=\u7528\u6237\u7ED1\u5B9A\u5931\u8D25\uFF0C\u5DF2\u7ED1\u5B9A\u5176\u4ED6\u8D26\u6237 diff --git a/ruoyi-segchk-web/src/main/resources/messages/messages_en_US.properties b/ruoyi-segchk-web/src/main/resources/messages/messages_en_US.properties new file mode 100644 index 0000000..2d0dda9 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/messages/messages_en_US.properties @@ -0,0 +1,5 @@ +#################################### +## \u7ED3\u679C\u7801\u4FE1\u606F\u5B9A\u4E49 ## +##################################### +R-00002=\u5C0F\u7A0B\u5E8F\u672A\u6388\u6743 +R-00003=\u5C0F\u7A0B\u5E8F\u672A\u548C\u7528\u6237\u7ED1\u5B9A diff --git a/ruoyi-segchk-web/src/main/resources/messages/messages_zh_CN.properties b/ruoyi-segchk-web/src/main/resources/messages/messages_zh_CN.properties new file mode 100644 index 0000000..2d0dda9 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/messages/messages_zh_CN.properties @@ -0,0 +1,5 @@ +#################################### +## \u7ED3\u679C\u7801\u4FE1\u606F\u5B9A\u4E49 ## +##################################### +R-00002=\u5C0F\u7A0B\u5E8F\u672A\u6388\u6743 +R-00003=\u5C0F\u7A0B\u5E8F\u672A\u548C\u7528\u6237\u7ED1\u5B9A diff --git a/ruoyi-segchk-web/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-segchk-web/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..5500599 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/ruoyi-segchk-web/src/main/resources/static/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/common/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/common/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/common/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/index/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/index/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/index/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/provider/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/provider/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/provider/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/store/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/store/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/store/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/default/user/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/default/user/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/default/user/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/static/img/bg.jpg b/ruoyi-segchk-web/src/main/resources/static/img/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aaadb86de7a66923a4b9ac25f27a81edd7ee135e GIT binary patch literal 722686 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%0Df~05M}2fYY~Maqd;hVZ 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

    PNq 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

    M;suPlW@HtnC#&o)lgH!yP0te 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 Y0B*3QbIN+QT>t<807*qoM6N<$f*x&?!2kdN literal 0 HcmV?d00001 diff --git a/ruoyi-segchk-web/src/main/resources/static/wxpk/PwPaX4PqzG.txt b/ruoyi-segchk-web/src/main/resources/static/wxpk/PwPaX4PqzG.txt new file mode 100644 index 0000000..436687d --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/static/wxpk/PwPaX4PqzG.txt @@ -0,0 +1 @@ +1bc40f067f30d2f520200d504238a620 \ No newline at end of file diff --git a/ruoyi-segchk-web/src/main/resources/templates/posters/bg.jpg b/ruoyi-segchk-web/src/main/resources/templates/posters/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aaadb86de7a66923a4b9ac25f27a81edd7ee135e GIT binary patch literal 722686 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%0Df~05M}2fYY~Maqd;hVZ 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

    PNq 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

    M;suPlW@HtnC#&o)lgH!yP0te zA+(~#Q_{l_ zCqjldc4jA#*%2U;Spxir8V@faj*DmIu4LwI(oOes(Hv4g!y16GMzmE#L5SmxKvY`x zr~r~`NE3nBec#wwDe_bsN}FzBYF;^Mt9Lx#!DNp>U}t(qT8zC^Zc@rTajurQ_OADy zIcI2zVV3cxkS#RCH5&R?3OMo9bJWGRa(>kvoEEX%y!R@HQCb+tG#~~#RAARo50Ogr zc6zU6ZcUrDWx;No?G|=l;*F7_Y-KF8kmF#QIQ-NBs)Nf?iBcKXL1Ig_{{SBG2i>ks z**(hU)aF}BB(T+PvC6tt+Ezkz$WEXX=pjghp~*2B}_xohUP#K8GofuA*v&iW=%Vns$+uUy0+A z9v9M1k0r+<{=?jz?ZWbRHFD22ZM*EveYS28T&lEdMleW{g{W+5)1;ajSBF^_&wt;G z&tBnsf6w0EbAR32VQydFwmZ8AXm>lbkv^&yf!qhTWpJVODpe|0ny6|DUU%b`Zjoec zR&yU-kuJDaraFpL{{T4iktx?Wc?66|KcsyK_t5cFdHuUuAkAT>q@5K^Gl25bGz!Ga zEiBu0*h?G!#l@#}Wi7WX#k zExo`nNm?Enj}9k4ZF=@NMJLWhpZ%oPHC;A1V;Q`TV;538I!i)Qyb;3IoUN&!Hc;qZjepruR1U z-P=Q_HvE5ek<0EHd@kLp(JrWV?Q5B$o}n92b;8j3OoSVF;s=jq(OONucM!vvoS7>D7G1niAKrYlO5T0Qxt{{RX+_#MzEA+&livwtji_B>Ay{A1?+1J$(o z3o>cQ_Eut^XRhE+bQ=5)9Rr} zA+O`h9Q;~Wf%6q2mB{N<{{WXC&mZTf%Js?MVc*d77g|?|>BnDmi`H%FYBAGlQ%AUW z?9x8;&+Cb_N~uvrM=uBMl#BZi$72G4tZQ#m{%#!(_CId9V`6olJ3k)m8ta$3hx#k< zjPSuD*Q$P&Nop!8D(YsMrmn75p02X0X=-Zf=W}=Ad7YSm0;xAX{73+jan`tG z@aoupG5-K0f95Olg>m_8H%V6YF2=4AOgHCw%_m;t-i|;Y?y-Afx(PS7WHc?VBOX3F zdDrw!&$1iNX4!1XM!Z*-_*1*~k%9YvE{ksWYdb|GlO%)ipsD@52kq-&PmEvinO}~( z8S&YVlii`bJKu0XVw$sQZ6vAdF1J~h#p$Q2rkZ{Co1|jA6|2R!;OZQE4PSGO!zubW zRTtFvH~j!Rm}Wap-l~ zn{OY7$X62|j!ANPbcM4SN{WU5066p1O7b3Dl5gxGb-Y~NKB?v|-!os?<c+pzfcaCQR-x15Yqf=kKkNHSZgtd?np5`l*UpP5}P^ zm+a_4VahGKD%{`6;Mr3(_?RD&;qoS)pmkm!B7c}K!{3b0TAk0|yBiI-=*tOu`)AfJ z_TPqOO-oGsUuv9{Rw`*zglvqIaj_QH?TC4EoB4s7L1`z2A*rwFrw%zFANbMr=xw)K z?Av-n7TIbT#pfd2qS_BGmlrc~1=?Rubp1Y=j^S*X95Q_+mqGs<&t{{WQ- z^UHrR)g%0Z{${^7eoBhU9>ec#&5GLfn$`9Z7)Vf{NSEXA$g{~SJ zwJHESA7Bd^nmy}vi2O~F`)mGQrVZBL#^t?+;YAe%56iT#_(w)?D2+;($E`FKI(Tq- zfp3)>07E}^Q zfeWNnWfjt10#qnd!=GV`@cVV&?-pqUD$y9Cv`7QPk`KH8i*w6=h>_i zEyAp@Fl9cU!10XXZFvP_x@|<$1v@CbPXh)txtth_=~X$r{_~aUbWfpe)!#; z`MvA6CVL@QPlkot`?6 z>h$6Y}C+$98 zvw-Lk%Uf45^LI0Be4)!0GGFrsYAYK4~*)|+BsuAgr0z|9mH86tZrt*b)P7O*6-Z}m19ZjwQ?*{?6{#9)S<#}|L$ z6!Hfj%h#{7FYf63o9w>Edug!mH}DxZc@?EcaaNXhP_o{&MM4b6XrG24AL45CVdLEt z+iMW2p&qQpe@H;BI~Qh=%8=T;mLPt9p2*?aq`8$t)|Joszt#5j(>a6|YST*C`Q(~# z1ERmZH||1gtu{X&N0HpyyE!R~Z|!_&mU`;xW+g>UQp5YS)M`n&^!W!Lrsvq^&uoPu zC5p#vgT2lG9*gRF#&3MR{{ZC=Xtpcu{{WfySYj~5T_ch~8Y&EU)43odVBuHekoKS_ zqs`ZU04uft*&UnmEaG>*cYE#n4e!_VSh|y6*Vz0_(g><3Y+;Hz&C|9sFiS;|rj;~O z)WxRGtd7C%V&+Sz)+-&EOj~rZ>Jkr%LBXhajV7Uo#1EkB<}2@o{ox+rd!f25mm}}8 z+j5oEAE$V|jXE(ePU z=(Cua<&ro;vlgQ^mTD}3fIb!>Sou^F#GaZd@)-<$Tp3C#+RSc3f@ta}vN-AFr>mx^ zj?EQBGeYsr6!9PJsUH0nlw}c8zd!YP`hSz6^xU^wD~PvPFQ&EJEu;+;*6db9Z~<3R zq%yi!;{=R{p|a+B~cN&-uFQWz<6VWJ~n_0CTOIy!n;IKH3Tq`Sgm-ZTT~ODcl`>RT9Zv zx8}{sNf35ag^rPPV&xW3P~hei~c{QzoGYmcGluOT0p7(eRX0u zf>Z(1uHD?#TUR2v7z7eT=wPa*sybk*ftVi|dxIQ`!sx@5Kj2TXS1<3EyuW<6wjeVV z(&~6R@u8+csHi?iqP_cIv*tSnu)5R;I+2&+M&VKFJcvAhXGY(wac|v2IS$d=^^(_M zG1U1iy*#o~h}H^>Q{j+91kgw&@MktZMQpDgX?0 zfUQs%ljT5Znstmm;91)HXg1logLa5oUCPnKz%e?Nb)9QMQ~|`)iqKZQVcZ>MK00@& z$zrF+)kHxM)>Az@t0?2esAzJ){tq|yD7gLMw#s1KEoFvJM^Y>H6NC8^(JhAWWw}G+ z?YHqmWgPP2u?jU6#dE3nXvN|y)7mQ!P_en2dz=t1`Edx`BCdyfeqfatBRd94 z;*>S~=}*tgq^WWWY6KM{jcO0rN3TH4T`T>}%t5#*5>!fcs)nOfTI6V|Rg}}T#W;eV zNX461CxSkQ*nixu(jC{4H`{BVDyotpttjg2LICoRAvG;+J%8F$Mp$YNDS&n)1yjlTdm8c=C~v&wzNX)?K&8<_( zi3lsH&*$2rtjB=k(hb9!HqKFuZu^^^Dj88%<9QiKP@~inQceIBC!pT}-_T?vT6fu* zN;*iqYO*bIPdi4RxcGGunc3Gs828h z@Jdsg{ym>_mCMJn%MdgYI;ZV5{{RB@9Q$QtmmJXy?kdqoB!m6uNd9e(k-aCkpxgTz zk0fJ3licP^t!#x<%l0>DadhGB=!t32%Wum`e`NfVMpw#{Q42| zt^Avg_bshY(^}CKd22K-erBXE%7khi(ED*Bmrjzi>+) zml7^IDL-ilv(CysfRAO{?(ZFheT;lps9%?>eqZ6}d+kpl{{UO}g>Atpvf7ntxcBF> z5PzjgvGP!TM_m3mcQ?tM?bUmJlL^=Rdv;B>Ba>}pdkcAP=EeU29;u?!_R>p>rGgr% zE2!w*5~;&!m8@5tUgds3=3V1?M2bogUl%vBZ<$iO#7$pud=+e z&DZxF!OnN~GG6}xj3tGopp?R_POsH+P$Y~AjcHXHfySPXCeX?6EQUS`_e11`y` zbj0Q3%j0j&m1cB?q8XakG1@@4{b$^rYjbeXr;h+bPbR4J`*`(?+{t0fR(G=wSKlSP z+kv1m!eNv40#uLbRZ0F4(!hH)LscCHPeCVQ(Zz-EZmKvTgvnVH8P5tNa@MrSl=Rh; zA4<=W&`d|z;cYFap4 zsFOn$I!CA~yR3^Gaa#b_Qe+Q7=Eu^WhpDfYy{_ALfx2@aH{G?DBW>T>$iE!Y;+D{V z6EPq&t#s4?Dsj(ld~=s{d2-#k+dYxKHx5F1Wvisa?rQC?w|u$GEHwJj zNh_;Ua6Z1wZLAFc0I7Rj-z3Go&@b>=zZoRzOHm#Zz0Um2)y19^W zFEo@RaMI+TrtHCln5Lz zrsQ0ki|nEn(W1j7g(!PjtNRWJGOGDri8|Pa!mf1^)6)JCz3Nc zi*1aNKz=jlpHH@lUUXh*Gwk4~>h7WzFt*|gAv zMz5~3>0JGv>~spS``G*Xw;nvZ#@z7|D-p4bFU3jRI`I&Z}N1*yob#C6i+Bs^D$L+j)U2RdmaC?5UAlp{~O9cM_bC=KNXzAwu83hJE zB{VqLgjYA0G%LWq=8XDdq=7334Zpx&3oK_E1Y&G=7Rm+bsN-n-WYv8ZaKrK!nC^JJj`co5on}K#PFc`@XyQk)2=&hT(@`3 zJDt6pDf>=Nj+wNCsGNI&g^x_(!QW2KF)7Bk7e2sVOhkosHT|vvIh$MBABVJ zO?cC+pEFrqT5Wr6wU7I$+fc=C2p$}2EBcej#-XO2z-Mr-`aqx>nyF5=={=R#ba0wl zFXMZGBP~_Bvq-gB0VUYDqDIvQE(B&eRuv7W>csnv_kLpBcSmz9#yexeH8fxL$BPr^ zTzUc4yfnDO#-!4VR6Y!_xH+-xaU76Rp7d1eMe~zjDYn z=G@6DvqJ=wwYAokx(AsVZwfddU;2Advhtq)0KSy^J-NIRg_W9tY3eJ-K7C6(k?iL@ zbD|5~qh^tI$yZX(Dez*Fl>&vbR<#|fM?%)}{#f5JHg-CElpTAD-SE;Y8L9Se=f>r- z4GOA}Ej0}7MNwETP0<06Y2|qrU3Kk`Ion3_9k5EPli{#qPf#&m%RLNtf4ld(TSd3j zL$XD76l6m(yHm=F+F6IlXB;U?k#5D=+uN=4((Nw6+WEbgxZ#32qm0kvYG@~Vca3F+ zcp6Z#PaKGNXxZ0`8y{h(+HW@Lj5pSjM<}ILg$)m%43D#{edkE`je`01J@Ud!9nn)* zSz~1s6d-~~1fRo7jC2~wR~(K|$jaLEvZ+gwcxP2>1`B?9AMAaqOLs*Npb<*c*Y;QZ zALQyTy56nsZVjv4xRYLztEQy+xKoA;#i~U(07$1y`-dArn4yy$UmR6beln&yn9vxd zJo%z#9*F}E3Y&xML(06vz4Er}Z@ug{(^_tb;D?EbBno!5J|*>51RqY4?stu7(JXgh z+r+v`xCy0=YHRS2eF6FOR`7iXzjvQu{{V72(-3zKLav&lBTq*qeGW9qkEUR1V-r_R zPP0ow4ec2+TIBx#QPgi{e)D?<=eI*QINU9!_X_xP0Hu=VHX2!#R2mX8Q^@2RbT8yh zt9$3WyK5d^v@&lg`ii=iGg#=_l(PX&9(ATb!RYOF2T^tB#a*{axIRpLg6f{1n<2Mo z@?YI*>gjhT_O7c~ylX**+IxLw+%@$x)2PyX0w-a_hTizK%)fRXao>5Tm<_h)XBO6P zZe+KRYayX&NUO2DZTI!Q)#U)-VX7u~FK2Jd;lZ`{C_m(LkU(kRL-V4AaQ za!FpXPX;v1ZF`u-lVGm8wQFQU*#sHL5i6-CQ2 z3ZM_kCcpvhS4+A*zZid(f6i~16H-ml-yS!{Q*2cpIh+sUIIjdn>gTQ?j>B8OTnJa~!LW#L}{nc&eBX zeS+`#`HfR;v#0c=&+Ji;+E3ZhRNLV-7Vy*N-{v3X{he%G@tgU1{4V%^Nlc#~{ypp+ zpPQ#x!|$wyG;Yqus+Kj-Dret2nX-F=8i!sTsilBFp;Gdh;L~hUQTZ#IX#YmbT&ZqSw&$BCy({wtpJsR!Ii|_(#l-GyJ;O%f9~r znSahtl0SJ#*#7__ceN(ktTG4LJ%3nw>u4-8me)@vGijW3^{~ksX_0CsnPwlXF(=r! zY2{6WWdrDTeofbT|wQXFoR29dUO)Mx-AQo!vpyrTy!pCpl`Q~o>&uN2pUusD|64|>2GTy8kAS!uOCWv9N)@3 zX9MAU_D?8n>C zosn4Djz^76olJ_y^;s;@x8RjFWpv@hO=|& zU>;@{1gRmd{VnWc_Wh2Sz(z-l?@2=K7Z=->IUI@SD~q)tfi-|ifU5`KIJs ztM)HnQteFkPZ_qicJi!j#@zdvmWlrWf>6g-M*_~J%|vEui}>X%Y`>B8bCWjMZf~~( z4RnZbyh4^dbMhX1E7l4B0D0du?=bsE$lR=~L_41ACywh-(noI&rAE_ADQ5)Jj**I2 zs@23{0WM+JicF-&#$Ea0PcGGi%ER2d&}+)&n$b5%7>() zjc;P-^kG0nMEikVZq?M5)EL%!nMP@_w9(5xkyk8XY3bBk!%VtVXiz;1roami@b*i$ z*-3LDxGURSdj9~XKQq_U-QDG$(QOwM4a_2KJ?2U_t ztlb;;D+@^uCm#gWFzxyt1eu)t(WA$W$5RFl@=8)Q9I*iMJ-6Cz_UlHx+!(3_)x$LP zBZ&DAKCp}LDfg`9Z)Z7Un0bS9-6Dx>U}u&?-yN{v3n;IM}7wZw+67adn^9{4PG=pPB6Y>uadvKSKj&l_Z-)MuyZE!cd>G--WJ>D zc?^(EC^SR6BClYV9t$BUY6z;Dmg?pD{{Z4wXYNmr{{SMsI(7!utjG2@P35tD$#M+Lp;u=$kjx?T@$|waNQ_&Cgr?hWE_BMzGx7+CwF@cM_#hXAnxxV`&zRC=OS| z)XPO60(seg&Hn(g=j;vlCrR~Y+fKgStu+(}vLMONoXt>#dP!?mml-uU!OKvRT~hOS z?gNs2ikFpao(uH8yCmEpR|r;$3eyM7{{V-nJ7xB|+TIP0UB>=j-nOo?DUY=(tQv-( zmH>(qLGtJi%kRF=%58diV%w2yoW)fnvsYe4$W22m;2H?&mUz`ErEtT`9EkEmeLS9h z`@S1E1V&BXhr?)#O3xbUM3;Q|N6;uSS&a2g7!89tq5#rL^;oz0wZ*jg>U&Yt&T z9M{W0APn(3fg{KsJrr%tl()ERkPaM zTi!uz_Po8c#T~xgvf5j~F+_N~!^-EW)3y4>wUT08yb1)_V(nWl`ApT%S$e6YiH=# zQf9DO%0Ci#tML*yjo1LQ#LGN>mLAMr7%yTFTtbpUe+z)i_GY5L;OiMK_U+G=_iKv> zk)pkbiaHih>&0D2AeCW|4ne`;(F^Q7G=1}-*S19{BxHz?e-U~4$&R#k)&vJs;V6n6rrIYnpe-RnEPeRdtl_A zP~3MLB%67X#wi|I2B&9r)>zh}xu7(~Iy2u8cE*jlzPEIdu$HQ}hXF|AQn!YNF_Es& z$_uusYGMQcLD6IVea^pi?UY4j%-qP!-z14{hx#f!NByOf_H~bcdoBCKzU4kxMg}!#V*ERJHJ<7uXXIR44=5>wHMrk#XT%L_>=R8J$Yd0i9H zqxu2vYWG6k7`Z=p-L3X5W-CH zKx7(-buLKy`@_xtUUTLxwk@pkEHr@L}4_AVd%G1ZU{`w5994V?#ED}~pB_(u= z0+P`m84NU*2k9zqe|8RCp1_TVnJ%N<1t@0-(XsOdP%AA@0tp`~bQQJtcKt3ZxNQ*| zVhN;d+J~hJR5#2}5yHI~`L?A`bWMrfSm>)I+ts+r39ztKz#<7nP{N{G$&tK*@<=Ty z9Ib?RHXg(t-SXr<-E1=Lla)KXlRHlIp(J*q44f*8sHw{q^XMVYe8_p9aY@pvX&hii zgz&CeiNL8i$B+Zdq5EfieT6>Sc&K3U8e^?ZGc-nMSnDkem(Ze8;0Liw06x5kF89}M zK*)7h*U0|>sBq{WW<;Y3R1dd@%l%(2wlesa6xe@7T=8#XO{Vp)c~9zNVrI3NpHd1iVm){_?CS$P-LsA#dagr&w%etg zV3SH6aTvco=!fUf!SYKYGMf)>%|cAn`CR5UdUjq!f}A(Tg8U@AO-NcpF^0WTdBva;kDAnH|_uqZ* zjLz!H*3j)On~Ifjl$E(@R(jfOH8VRTl(@B!Bp-U(<=0UpDR#LWdk@?4FEH~({I^rO zT5YP-4Cb$=%S>S6xjn>ZtbvE!j#2ifmUi8i%GO=SnI=yWk|CuUR;Hlxk&vCMNW+>6 zbhO9(u<9P3h7OVV_p^6Ld*$}jl`-WXWy?)lMK)4LX)-mle?HVsXGT-!$-IGcZ@-n zsg5r!nED#lj*>`n;vZVl&lGJc0%K<&s1@yd?X~5=vYOfL?>v>x81Voa0vqH;e6!Sd z?tk60n0X7AlbrSrW3uKhPoOVxXZmDOMkp|$QlzQ}p5HItXOO+(?2Q2SK$GWPML z{=4$TQG9aUq+j!p=>GsORjKj&Gf^ztzqI!}kPN2i$yd>NW(tRMB;g^qZ%8(vqrtbtdC9&o1EI65}OPHEbRyO0}kyMT~JgD5%zEW+W(z z&g%1UVI8fkCE$;U{lfk*Txi>peZ7eI?g!zi(8f0-+$m7v`J2$ic0CNMMvc+1RnV1X zBh(N<=)U~BJCJ;1?(wu4Q*z6&GW6J&ZCaM1uf<4OB8;pj5lq?$JT<+L^Kvut*776% z)I(ABfy4w=c&{8Z z+iwX)MJS1z{HrG-3Y^_^toQRzUzC6wf3sh-^*wu!zTflT zI&&8}ZWU?oZk@$P!w@=PK~IHah$?|fV!TP{ympt#p3BW|td~rDciOn^+q?F}Nc-b< zXWTB@+O=|OFydutWTvH-w?hEZJcUGuLZg*psctt(PkK~QB zm2ADs_m6&?ZsptNBF54I{xfufnxy~+aFxhaTIm{#C@Km0__?>ce!F79xPC)nwyg&A ze2qh4s5Z-)DB;5T4Lx0WS*NCwwys6i0ydRP0-%p_Un%VmEwp#rx+$KujXZ$zBzf1Y zMECD|_UhA`rP;lk+;8ROfeMMFxfFJvI+8ktV2C?%Dq5rxIyP6gxd}?gTmklZ^^V+n z;WSZH!!3AmEOx-{hC_*!cC{(r&Hmw|34qtNXhedaqna#MOAjo_t2;#uRYh#t*^x)Er!(?(r!ZJgZ*MzV-LUOsG(txKB7xke&(n=M zgZ;tw3z7NOJKOtBzCFL19Xl>!1Swzu9xNb;m@rVT>We8_cby=0tk-n(?_u;F_sn(Y zWNqfd=5YBBw~n)1t&GjkG)8(X?%k~stXUjYbR;q|`lBSIfn7?BS={yw!(_U-wA|xl zxs1|)RZo~8o*;~ZI_Ez+?0fekZ*%h2{k1GJMI{TfFcKvyvp_(jqgNlp@UYYf2TS>B zd{D;xjO{Aj-Muk?d(|CJH5G1Ziltc5?!DVm4NebiNWkc+$I~ogvmlo`;_<|Ikl0b} z=PC|j-VN5`wc0I+E;C6S{1N?_s}JGyu4do6f44h#J#Y6r#^qMM3=qbEDyo2> z4mkId(4s>cs-mnzf`LE>000!H+1E#vRTWVb1Ok8z06suqbtgoFoeV9>;M{+Y^#lBU zsuHk~S4qgP+0}I?laJfbN8J4%);}ONUQc0mp4p|`7+jP(BdZG?K6?vNzN&1V12iLQ z%vMT{Ph4(?N&POYq^Uu>Y};o40BJ3r<8H4T3TpgnM*^+H5PvR$eCNpgv(Ni2*2B#^ zVq95Dv<-nQZTMa(DXAS!RD<#$fj)LGDfseb<{`*4T^#7f1BMI)}p5$ z26j#V0JtD5jf2^*6?HmJm;Jnk;E?|S2csd@%n_<4L-mjI?OxT%d)4_#d=YOC@kxw) zm*PBrK>GDEdrS8c`@ws=6}{#D!Tnz4S&E;j-1S7xm^$LKALBBU#Y?PFkb7k`r&XWW z-#vS?c4z4`I~Kh45AdposKeK6+S;hMZ6u8wKqvn6>WZ$Cpu)rxNU#+o>27_>J0~ky zY{)-Vrk~A@2jmC&NylAU_DAj!?H9CHc02y%*5 z{7GJkzH>L4+}Vol!?|-AUB#ctO(jN0Ii1MXW%BjY%G%|cvn7z4qOzh%9Nmk#B>NKp z0H7G_I3b28BSZr8M_6!n`|ZB|LQ zF}m2Nn=`ws#TM1V(j$vJ)m4zi8U0K>vpvE0GGAdQ$;LFpl*W2#_4#?CP=qeN) zK2`$$;{IgjJ>vRnYcY7~6rU2I&F}k)}CjViFp7+G*x?2@DXRCFP!1D;zN(7c9g8KR*5Tb)w3&smbB<`#pNDzmmVr zgWw0n7O%(lpUB;rUAt%%#GQNA^S@>9qdEdsmV7qR847$fvuPn8B~e2GBE~`N>c^M2 zjlzZtCJ~>+-K+agAIiNehRW{XRwxdiR_!0pKg+FtK1u%o!l*Jb{{Rred_?%!1sdL1 zX!{So^8WyJKA-nZZ7*Hy`h};7$M&JA%S@;JQ1&pf9C%UhImo*IjzBIV4fbwsw#3 z*s~Pz6X-cPYvy10>Fi%)uwRsoONiw9Y2!y^Bwsxlo=hV@#8(PHl{#DBwOFRDr4&1 zylG~!j=GwUI~#7?%^QMkCO;QgIOg8SZ+V+#v8u^<9zpn1xc>kw56q5{OSxG?P-YCn z$#Q>}`Fg%Dj^FT={iQ-^a{mA;{!C_f9D~O#Uc~6k6nk?U$Oc*}jrY43C6t>%9+~O! z&}s*iACSH0J;-XieUKm0b6@z#p#FUl+;aq^(%RSoT2+mIko}Y==U%U4|5AU^L^c~gA0r2 z(0>T+U$TOq&cAO(6JOrkP)$31g9G*t^4FuSQ$-{x6fv_1DMLpbHdKn8Ib~Q8LZnI^ zZNRtSk7O=cdx6LLy!xsra&<0GP@{My3M{fYksrpcKvylH!V_`E|*Vv1%vJa7u9aP#E_@yNsVIHsntfWa@O0~4YbvheNdl&2LK>gbBr#K4V8NHLh@{ZY>wg=pMztS&vExsEyFcw}0k8UFw!K7Zio z*3RZ@JBY4eYD%XE{ai&jgV9f@8}sAsRa4W`$+~*_u4brK0ku%MW3BIL1}?ZE_4--~ z*k6Nt1e@!&CUUFdST_%qf8(du$n_y0+Ih8O)_e`!ML*L4<^3hE4>9xU#}VJVFMK4i zW3qA3)hZ%W;&Q5#xlc37-c4-n;Hi{H5ogfW2v^$&eYU&|BYGbtKNV}|>V0~7`A++6 zDDuQvYuw9}pcto^8OP4OR{sF=V%Su>&*J3!%79Z>RrSX6!fq)RDZ{)N?4)yHat0q0 zuxOF1;CqfNyx!i%-rroRZ|`oh57&&Z<~zS(6{pXv4gT>yO_zQ4Cd+?RB7K*3hEh%| z6~Jp}96yQUBx8kqy4C*xfAn6d6muJklmaNmrt~0ip!GaD=1<(e?yIYW+JL8bfEYn9=@&D+>a*m-ofn`BW=4qu|^H5mn~E3%C+!X=@|*-)R?qvRe`vgL_+ z-<)D_1RbT^=j$uTqo{R8GZGMrK4dB$4btENs^kT_^z^$|WKr`?u}3;V&@zR3>?^R74X00B2bkktET_RJgGW+FIfurVxKxHBR6S?*Y0pv*Y$& z(T1vQp6HsF9vYrjjMPbAIzdf|hGf+6Nm?~|T}9R}r{~?GlGqb8;C`NXWK+-QPb&HK zGyec|U)+;x=SR5v)qAU99q%XE+_XCljNnOab9rt-xZLN7fmtH7Vc^=K1s>o$tO$t# zKK)(r?`!n_-h&+uHiDyYRze$eZUI1^YRbEcpRvbF8>7-;=w_9X5PzMKOpkUv6y5LF z7tK=V!ygLQfZOVDzcF7;_hq#;0sz@%_M?^3Vg@q{{R#RTS=Bcaw-0=v!dO&TtUPb zI+0HtK5svn;7KA3>l=ipr*vtgm4_tyi6Ory*}N!N)ua`#$o~L@{{XAYr%NtIynMQg z)!Qp!WOugOizgfy`KHQ8GgDVZ2*+h=UGMUh+*zBI=hN`lfRy9e8 zq?<1lIf6x5Bde^Xh3N}LC#8{CxIbP;u#Vlg@AAg7!DLo4F|33pqZ9byTdVJL*nIVwV#c8Ok3XdFh*y@FaBmXA&(y1 zlJ5I$m_c}kHyO{G`RQR?eTVHGD~{#~>gYiS`5&){{TKU{P=V#bapee z{ySoK#V!bA{@;3JG1--%sE)dzU^AGwr>Fikj-j4$PPuHpHfZ9SEo~9;A$2SWBKtmI zm0?hTa1_)AKH5^W`HrJrY1lSCW4*O|qQt|fF+)viY1>m$03x+h=0NBL-@7k;ZmP128e)VBn|@m4%%|hC)&$#a~Cbx zwDP+UEyK5D^0gR0rC{aesvabNci4@_$bQ;{bQ*7p)_S=|u*=L=ELNbixqv$6_ zufzh1f&)>`Ps|GKzL(18v$eTB+qyD)lR1%Zy{yRYY|VB{C=q82?CDc9%n>D1s1F({ z{RM#@+S@sb^71v2QQ1X6KZd8$xUD@a(2!c~8&qBeyih?I9||ZK94Zu7_VMTg$aQ|` z+O;ucv0hKLr<_z&NlsR3X#%r2TFOx?%PlQe8iIvwA4X0OwU@B%o7K3s-E3o%hMN39 z{{TgW2qX4-gVmtC2{IddqNL#cnf0&B9DZY??X+;)AG7wA2JMltTWc=_=NGwfS*(Q~ zKBEPnf}S^6@ikS`!yZE$Ql(_3bq}hYj;~sg>=$!2_SbbKnk!2MD;pw`87ofUqqL3$ zVuWKIIOJ>8{C<3E@;~u-=pO7&kEX`GL^zC5%w%d-u4S)=q9c!KnMBjAEnF^D;+{zw zLLyPDf=eA%_I0=K?I2S$-W*_oN*dFEs6JwV3h?3O*Ou5wrIjjLq#F78{eb+q{Oi?# zd_v1?x;~?#+nduhiQD@`D@JO{tzJLvsss`$UDjmb0by{L zGK-maHo3Hnyi?GvGu^<0P6nc*<;3HntJ`_ukVh0Q(Xhn^KF{@W`E-7|k0sZ=k+!kh zyJ+M;jP2aCwUE+PBr?#M9)_-~9XixUIF7nEH8iJ!ioqEi@Z1SDA8*9*MSH%_Rcwf( zG{^Mc*ZL{L__~L=!=86Nqj0&|tZhVhQBz!wHE{rfi^7yY6IV5$#d@=kjI-ltG8v7P zKaLDe^TJG!?OK4?kM!_Jg6 z{hd9tt-RdPx9_%q3mxLY%?AaQLYWl#c~?Kurw)}pr`Wq^t~%#)c5ds+E+c8}eXTy^ z%wOCXn{if$~-Ys@} zc!Sy|TZd!x>={Yn+MQE^&eq~^(NHXM zMNeJ5CC1cHzTw?L4V;Ay*i|p&w_SJ$f9?X$9Dzdf}@E9_0-zbKbEyEcwehN7N&cZ+g2gDa7w zjj7br#gLM!DmG$3(n@=3UUR%xh+W(?iy5l1p>-9g(#Ix;$kh5%qMetOd2^SJ_BLIj z8+&cWCXVLaDlMf9tgglYLMe4>F+iHAHCCAqcGvSG{$+h%*t2dtw|Qn=MXG0tp$ z#>L_CTN^HsR4UYBW5&?qs3yeIFh*GCpm-;ZEh4`ldm38v-tc5gwcTD&;2Jd3)?h8MKz{C zkvb#(Jpm}-vK+vDw$N-CB| zjVkJ!Q)>*cX*#{aHnHf6G?U?_4s%*p^7a1!C_Qu$IYtNONx747pTxLZj}|C^IssfO zIpV~5C?Em_bq;}kkN#sn%mZU)umO}qkE7}Ebdy|D%;3imV|L5&bT!H06(WiJmu}*C37^Fm%G)X+h1IFb^4k=ivBnGU($G#ANYw?uJATZ*W| zSHU0I=CM=PQ{D;V2`X5m(Z=DI*s?v&8{M+zIcl>MJ*U^mkCjF`#BHyZ?tQQKlajY6 zHyEyVh_?h|a}$jw15}x11l3qZ-NP!}RG%X`(3!Kg`d_Uu8@_3&cNQONW3jm^S4OCk znp$A-MNaZYp;*NLLB{}l6zv?xWox$CTirI*mQt+CP2!ozFYJE=G^C z-0l)d69c3$Y7)R4<*IsD@4eTHuG%@OJXGplS70-qJS>1al zz4x}m-Ww|$lU@FwO+RHioj&ti{q2u4dr!+8*~^^IJRIp|VFuS8*vb_nKr1w>RpJ03 zNgGk>l?qp@y8u`Lqy+$3Kve(>eFc>i0sgQa=IE!;q$w=)0)xx!{PF46Ef`eP`SeXQ zUGdoctGcrr7vlyK3y`DR85PEF4&mK_-)3U#<84(q&AUe*t3O!~T`eHj9;?|3+5MHv zyk1{R^t&`@Sq&a%_yO|^>S^bk@D$HkFSYwg$zI>=8*esy@48(>bAJzuXS3Q+UdtKy zWw>+xxPSt>0|F2eM|nTY!AO zQZ^K&GD1;_Gz~#chuF)MLn3(ODhtP~ND+wTLyHH}eS$ub?4)F!WY?I@|V{nl3!VnyA1bx_;xTC*7s zo}N43?rGOgEI|W%lgq<<*dFE|_d3_Tcy}k`Uzw&*Cs`&N%Cxjo5{ zl4>!PNfILsR9Kj)*F#*yfG;0UV9r+GHm+Oc%V@5N`nF>uqJyXwJ-Uyr03Kuxr7ydO zv%JZ%`&r7Hbh|@ZU))CbGx))U?&8CWWEMrk^f_{@v|e-MBEP0oEBd*>coN zZ0_-@qWk=|I~Z3k6@{#eT56Dv0Mp?VJZtfJ zd3Bhc-1~RSyGG_WetWSSoM^wHWRKy+B)n^LA))Zp5A2qO&%|gbN(W*07sc<1m>NF7 z@4oQd`y}D*Q~mDjPUfq|R%a!F5=xZA?YQHTr#Dj~8yZR~N~wT6jXe7-+j**MyTKKX z)pv1xw8)i-p&U*$t$1XPq;30m<~{D-_S!wOmhCnSK)s~=KFJU#*))V+P%#*+c&SN>PEE{xZRtCFmCSj&4^8KJky|fWaPls4yKHVcv>^15WgW6Slrjqw_MYXTN3bzlFNJ$@+%^X){gXEB*TZ3LC5_(|ed(4R6oA8ovs%G+F)mk?}r?|TDkj%iV4mNume zM4n{&2EPf9kQ{c2{z&%3 z(?xEEONmtwd9kPXdViWZ!&BX;Wems3R;+jcPe$iw z{2J}d#7SMe<;3;wKgZ{4e2mML&lpq&ar`$MBh%AKW5(&ZJ$;lcg9dd03_`|Eqv z?tQ)d8+PXxFYOL79fek13qWt=tsix}vgJvCz{~3aY8*caW7bo7tF=>pOj> zg5qCjJ-=&t9WD`};U_hkTkCQe%4cP-*6;IUz7syo}Y zczF|(`2*Cuwpz;kzbrArMAA8?uF*=0oQl$e7|)kfH}XsV6+O5szW)FX@gw7P4h|FL zhL?Z$#$B@2#9X4)QFZ3ctfQlhvi{^vSD0-E!b)}*9>%s@f`W~>-jaWYKk~B=@Gs}m zs5UwPZfB|VQBUS;*1vxwznPcL&z4eE!`(k5`wuC%YNTiW;_Xb3>+OXCn}HH-U6hzi zY|10DF_=oyDD{>%Bw=N-?OS*sO=N+`;v-Xj)~`meSXx`=C=@@b$u#vRJrM}wjwRC) zBx`coQ9_MOZp=Uc633E%KFzrFucbEA+55YHW-0de#M--;duQs~MJ^9$U~;>cF;dqH zXfe22O4`Y6NWGBT^X-}Eg4Q!N%;_8>i!%iS^CS+u0VDt_dbr<={{YAX`HOsvr^jb< zn;U9$4$7}(BXRdOHz?DxcJ%{=+vs>##zlt?quH{{X_p zMSs&857}Oe?{_FHWH8FEW~agj`Aq7rrvl_@$}a zJ4i>=`v|`VYFVl=^W`_rR-7>OOBO>G#1pDNVO!pOzm}_GY>_Xi?{DWtAF%XKF86Tb z^r8qpc|Yd=01w;M?(`SJ--(|V=%AzM5070})>FW-{{Xq%9@NLryDB7&bc(9I-II>H za#Yqh{c^QVxBQdrCwIDTH{_eU$sgoSKVZl5=&os|xHX<;Vd-3Ya1;c5je0Z8%llXdS zu7y=)Vh^e^SXdQnUflfwHn;fuqqh;|(wIuNocZ*PGC;Ch!WJ}Wnad`Y4oI?|1&P&f z>FpqOR{*X79U1rz%6sa@wEqACZDwAy<+d!pzklD%bumqaQ&B=w{N7sX;6(z#9cWUVfg>VP>iV zc>e&a^XeYFm*P>Cr{(kMYfBmr2p*MIV9dkP+QzO=;FEu^=i2fB&;@8epFx@3h>)DI z90!#;O6Ic^nO)O|*i=)i5vMb_bTy=p7fz;Bre-c4^%4XG0B#sw-pOySl1rGj=-6Yq z{zKFJ9Z*}#6^#3&qLu7V^u*Gm%NhNh3v}}^Q60b`SyxD~{OM4?LC3Wby#*`f&~4!W z0&**!iSF(-T`Abm?wT4iF3sGN%@uV$EJZ{#b7_{kjGbkE_Kvaq@M^ZCB~<-Kux<2* zWZYKjHLawigF(O^BkczxsUL0;^DfTT61_JVR23xgVTC{GSa!G1C!;Y(UyaP;De`!_ zm}_zM@GSJzP%^s76RxXVUqg%8l=7$9;FV>KB#DDYzz|2LK=*=cY1#{gD=Hcge2@9P z51&zHrLu*w)L+c@{??JABqGFePx~8tY^do>Z(7sgr3d&=NPXFmrlO*nno@=8Y27rs zqa@MFStouT#@#>t12$s+l%H9unuPR8v20B+IAPSPU!NdZ-f_5+)5v$&E+M5bxlXe;(` z{{TNy#h&}QSw$RAF1!znRMY(5%ynAd%%f^i^iRc2;g+J@8SJBOjE>*iRG5~e6@{d( zt9ps0niv?DijIPYJne*RqI*B^H- zVddAefL`v`_ExD@&}rkWtW(UAA}XG&z;QI|RV{^2S=d{mudwpsPvF=Tn+3HgidibE z^!V}_1X1Y>?A9a?No)TAXWZY+X7h8BJ+o{=(#qfukgh6yE0TQ&Swa2T{{VLlm)LJ_ zlbku0C69Dq)6B$oJ>s!a)7NLWE1@l5hC>2beze48Skj}eP#D!UhQ#vsGe60%Y4 ztZb5LlP_3J)*lL+sB3Fsf6_gQHtn9rk@npzR!(4%YDvhByjcGLNaBO?;a;Ziytm#< zZ`d{s-Ak?qCHY3ZIGJ;D$VxatYyHjR(aJ#`w|HxCyr3Xm$R7aOE?# zQdjQo>Db%0T28^9rfD^ZTWxMiTCK61#p4~A!3cUskP=#Jkzi)xg8of%Nc!tq)a0K( zTAy6~oqU{q=l#y+KfKpEe)i`ZOSrjW)>mD=(kXPCc$|P|eOls{=0#9s)Tn9%Ya%aq zR|)a6sJeTy_bP9GukLNR+&eQ3Mf^ftw_k>?+g*pZGYuj~Lmu(kk{axP+R{096I0a5 z46~vQ01N03iS(Fmpvl`@zwJCPwS zjV`5RR$W$LZZ0|ZAFkrdPW~f@r(aNOdh)Y7GdmWoPIKx{`mxY^mFUX)@hwC+yrpDd zMa^YtJ#D%Q|THaV!TZhoFAPybnovwWFcg^jbtW* ztf1DJ6ehK&K<44;da6xP)Zyk*&H!oYUX4EB$j=#&ntgsl7w&+-YknATZm?cDW>8n{ zsQ&;D?E5%$?5(%%wwGId)KJ{mPZP&1Ocl~dq*9VcBASPd)RlELRtAJqq+efbgzHYu z+xzD&hskH?w*GB$GDl4mYa^^QwNSw|FsLz6tg+7F%Sdz}ADa(ou3B5hmfkWJHeNq% zG3$?)Ncks|c{kf%Yx#fM4nf=F+qq+FwKmq4%2}2u{8o_Elc}oC#IqenyiGbXxZji& zdEM`~wzU0EONqti^Z5KK3lt*tY z;`pYAg; zrG($7)YBCLCRvemD%n6Mi&z6lH)aFkqwpW`UU=xiFI3lA1$dnQ0IT+N18z@`5i{Bv zLXoPH@kU0di898iM=Aw>KB3DmH@_eSv7|e(0M)y{!}f#H`0pYhP}BU~2g}lxl~h%b zv_*2XGc2_*E|sRMjapw6hGiVc)apyJYH=aslW@3hOI1IDoP7TP)n8n6)RL-@LE?B< z{a(Ft+51Ovb&mC*&PN=zINIYukI!Qvf~F|)xcat=nyx~!1`=0ds)|bqB~JwX3HFn7 zhTD6wdosZ$1e9}~4duf+SYfCS*;;g>3-`8TDt9OuQN^e;#})LhE7gZ>ey59cWos(v zsM9Tl+VzzG0Nxtd3Ny2I+g7>Us+3+@&=cb7>XYDCH&C zBFKa?jUz~Fu=O$j0B!Ek-?EWc$J^!puPz-FCH*vvihaEV8?4MYB4&!Z@}B56ZW{Q4`K9!KZr!_%Y7UDeXv;#MJ8*1lkQ(}gSR z^7-@{<@%bfWT~lob2}L#@u`0_pqU*OX&L1b24{Uv#hXl@)DLC}e3VpELHh^g{{R)k zs)+#(L9Ty4+x+?q^4)1xjU=@9X=I9|EHfg!vem^Nk{VAKSadq7vVywQdQJVVj`1)Y zU=jN({Qm&S)1j-uyu9gOmVCd|dM!KerE)_$xj3mRvh?*)B{fn{;+5&DmCC9>t9dCX zYDyMXk5NFDYyJ(bcNkI=7-fovqMm;<~_)Ho|VPOJ*>4wG^X;`YM&DHh@-))s-k z5}%WfKVcmzhFLAy8aYV^H1aw0^7}_jov+%M33D&Cy6HcX!Etw#N)k9~rP^+oLyMn>cOHhL#E885Drk z)6vz^&fpFOa+Ac6Hqb^4mRpn`?hF}Mg{gKv zMxza0hdU)cQ79$N&4jJnwH35-t5Xd|pjtzxP+x1mePnBJwvxnE!4)fz4r!hQR2ur= z^#^meu&c|Pq};c=0N+3$zjIxU<)ziEk;sswtu%fj(jenVQ7DuoiUmm1Qlg-BWu2K@ zx3}ii!FP_st)|OuP2snjZ|-NKkW@tY+LsYi)=py<6}xjW7lwO_sf-_|)h{+d9MMI- z*)?sZkHeOks{R%~G;AMC9YIxy%QZFN*cU$ zl(kc><&CN4jW6a`oIqYSb24fwrNLkLFW1>s*7oMD;u;PfzbcPUP(PnpsV10|2N*tn zN7je^o{UD>>Imulf8;t^5Z7}YakRF3!mO}<(H=G;_SO&A@O_Y7Zl%Gi;Q4xb@y|@X z!qIfpmHz-&`Fb0$y=_B89#y9i2}Y^dlcbQAC!P|(UyF18zp`ns+32j*r%9S(Nv9u| z9)s=e(wN=Fp0CQTIapNFQd3={Qw37f_|~AfZ=}tn6>AHAPb1pp0qjv*kyC*~`| z^7ZQRP5|zy$Dc{hpgwB%({s6d%T8T|V7DhokmbnpK0!@* zP=0+`X4&gKgR`;J_?@-1uvnTJRe)2&PmZJw7^RIOraniA$jt;%s;MNE00HdTQ4_QP z2khz;zUB?%ah0dL+$DE4uW|F^fPBwOkSsX2(!$ms;;$W z`MrQ1^zWo#9;z0n9(`afBiUhJET5ELQz-nF)Ab4u(0{P@jih2hN|prn{{XAcr2$bY zWo;|!ao0E19}^7^=_EMPMgIW6iylwn{_bQT(EMZ9s;F1~&nxo(09W{WZ2l`-hpcJn zCi^m?GbfFL3ZNTM))Ly410Syo?E~%?Ha8wL52k<;EAbEZKbK2R-)p(sEH`m@m8~nC zKV^K+%a2Wcnb=$Z06o_GyK3#KnoNG?+_;%=_{`zg9GJRXjj8fAipt0ZTI1e91B(T6 z8=DVn{{XI+kwrDUv4Zk0m0^OY+*tWmm>;*L+>gn8p|x|jF7Nx?GEK2q+zF+F1WM8O zMwzc?h!nc!stV%0JJIg$r}&Za_irsdRCQZ>Zcyd}^^&JVYdc58Skr&)w&k^N+n&#T zeQzWdvlQ{5aU^pA!Qwx{!iTzrO;v?K=r`PZi$9rY{I#_r2>h_G*M|XLm!A%Yn;yrsZGrqNMDdLVrpYJdPx(5jAC{lZ-{4Qg z81k6T#_o(}{p^ZGW`nBwc+++c`TNM#ibI)veOhguwj`5{Sv-Xzf~8NZ(o${Quet8g zw5HsIY=>f0SJc!J!#JQl3}H)_kp;X(A|DZ9Ktb|fI{sa22lBuE6rb{^w7-e%zl+;D zZv1H4RX%!n_gz_~><-zfrjU62&}6byQEe@=I|UAcmV$X9ELY7SvwItDJcqYg6`J+T z^ZE|dsrgisjBy_zIx_k+dU)WQ`e#j+&M+6idP)sJF3{7WR96zlU!Oa9XdB0aSgw1%78I zrG<$-%~Mb1)t-EB{zo6o3*-`GGZ|j8gQ50bOT{c(pStR$+m+MONWMW+kJ&UZWOs#H z$p@-8mX?~Gjg_X3_W=Ft+%8<%fKfYK+#U-M)I9jPq5+JWntC3dw}tf}02NFV8H zteffsQiZ*QQ@wk)zFdPI*>0AQnu6aOkM_p^`Qd+WMv!fa$Gxg)P(07&<@uB7M^=fP z_&f1{ZAv|hwz`XGb?zR88lM*Zb%)38dYT}}p=ug>2o>^`G7T*9RvL+9Dm5|p8$UAd zu-^-*w;5-Zn?55K6!ZY_{Hac%KYYIG-pzgEwrH%q!`L0SC?jEScMF*AEy?0gTAnt(!GZO@tLu4^yAH ziZ->yzJg)pE@ZRbCrd(7JJCuj8U`m6Q|57ie=fL-?tk}Td)w{C<9U0@`;Ct@J8{{Y7JwnHn0e=Lb$KI2gS&{8e#Sf0}A;uxY4QNvd!6rrULMt;zJ(*E%Kh3)p; zf9>@4Ho;JRP1~e4=O_C&EKHySQ{gL-!jqqM~aQ@b}0TYPET)jla_rOxDAv3mh29t0!qZL@hKjc}Ni_MHC3Jr+y7TCGGuocypqY2*10 zuZ!ca{3g%&e{~PoGDjZF*+&-D6rMqJ6;-py2Mo=B zVJpse-R>&3`XEo}insgISNQ?aRNKAuwGow#K0>GVoCEnDuFI~v52U(-YEQBHlc~D% ztM;``GSXCHb{5jYZHQ_@E|{t-rNz;~Qlk6vXJo|`sy_x0IDcnip z>0T7_r%0o@xQb}*M9gMWP)V=*6h2^3bcyRcw74w(Lkm2GscN!c!<;kSVX2Nu*7D9Pq#vrOtL+%5{J8zS86T$} z#a#iq_rG=Sy8Qe1UNxboT)pqA0B!EZHau-&+tz`){wZ*(x1yYf=1< z4v*j+wGJo&{$r0{|Iyi#Xzbm^Epk?xMxli~y1wAF9z|zi5YeEpV2A2|AJg6pTSGd^ zWg|}?@Z+wC^Cvj+{8r6p^+IV)J^`wf8O=cB>F4Xv`Adc<&m33n>P|(nkx)+t6=)4@gr0n&O(iS~7z|&-4udHQ4<&#H+K0W9 z!z!_@eNA!Fcx1MFh~>NSJRd|L6JMTb`3{S(Ld}re`|q&#mPm;hvd~8|AV}Iuijs81 zftV`CM@bmccpr~o-I8az+;=PIHL0iVKjs7F(4(7t8%?)quz_f4s+Fz)`TWV~*&)(R zi62%3AF2AA-qr@*#CrR>0Tm{M{hc!I3>GJJVrwvYx-_oFR;XE^a#e$)Yl?VeOFT6Y zy^1>W5A_^-Pdrgv#_-IQiMWsTa3jm5c9%C6Hxb=h$)e(_tQ zOl0>C>J-Qe1Xl52@e8Ir5I7M=1JA1F`QzOCx(=1h!%?|&75lre^7ze@f}0_es;H_G zW@jsyo{=gfa}z_0S#>mOEF1iNi@7&%`pxza7rNdMWN%D-HS+kW(C_Y(v-22pR8}Gl39?ky7v>4-F=51 zKX!JW_km^I6Ia7ekfX!WmRXZ-;?kugrxDXgmXbuay9FMRV*_&sG|#)=RvF|=L}Ei! zhITw%shs%^1Fx4azK7ngfBVMsEZcU@+Ib4b4$jb%;8A-_0MA1oe=~74@&ADR# z0DatN7S^_pd!9T9`(KCcuk7mVeY=u*eqGe949Ov+P>TF*cEkwAa2elG z!l##4ef+$CkQVOv)xNOZ#oa$6>Q3m#NhLh}b<`N;i)?51^;{Zja2wZg?kJkCBTrE# zhB4C8$KjGCk||Zfu$UX$`#svtqTgAFZ@`2NKkbE1q3R6}42svKe#iS;&z{!vhR^N{ zJk=iGzFT3SfE$IDCm*W>(m0I_PC%-NSkx?v$s!{z#CQ&#>m9WkrYmIN5!N{4YO2Z@ zvNe*3+ftcotHngD+KtVK7ykfQdpFxT1C+LuRJGWl@cdzH_7 z>$`3o(RO1boe1VM74iulkxFBwRznp=)Z!R%^nelKiDIOtM1>aR5Cx4uh_NmG0r%_M zIPKh^fkJr-3=beN!=gJa#^g$5lJZYeS7WI8o;+!fv!GXWZ9TD{imHb@w{Te+Y0D)< z85~6<;-bLEc^kqDN~MSleO5nTWS2XAh03zrS;XqYH9%|j}++{Wud z3P{49cm(kE96ntWPQ&{ITyZG1^HLzWW%xi1BXJl}DaH($ue*{Q9q6 z$M~<1!`4j>PY(=kVsxdhg-o|`+pjLpE%!JI0&v49 z-|0;$pD<`gr&$rp+~c+H_TqiE=rsp&oI0O9OT>Ctf$}|d))ZZVwf9CZ8(q0`xs9hK z3(-_!Gc{9Wg#=8b(pS+{)WaoOPZLF_ORBVgm6A*Jsj*F$%A!6rYUKur;%A&8KRTM3p=u; ziiMgtQD9G~{(r;Rmv#2;&o8y#NfVw6B^`dvLX1CQ>MFGN4))tX+^qz${{Rwpu>6fd z{iC4&0CH?<99DXLvyyrUw**u%R~&pbbn?}lWfe!bc|Dr}7g-rLle$ZMsf83P+sP4}rw8%0GK6%Q(( z1TwH&0dT~do_&d1ZnDH}XoWzf5A6Kw^XM{noyPTJxR&*q=t$rwNvSxcDtP*IqNnTa zlUiNBfl;c7WJzLy+9?^oZ`A7`Z5n?(3wulbT-YU64Yb>kc=j*t;nQ;SM>0TEuJdpo zNTDpmQ#ipD=mhx%)SLGOuFBxsBx8VeqH&(r7FGl++RHN*;$?lkRbC&I>+l-K2|bD%F%n ztgC(s&;kKGYpe3|C)Jx1F;kDn<#$fl$!y&2T8cW%jsm(Ho5rV1X(p}%5HyQl>B_k8MuDjI*M)rgR~^+FzJKb^LAFDz zf|=_QnwpUzG1SXE$RMPnRb_J=^GHHL1NimoVhL;dNIa@DNilIV02luN7v<5e z-1irkFk9Nf@=onQ5E65Y0n!h8XSU3^T(;TTUwMz4FGnser*UKD`#CAG^OZGJxL-6g zP8wL&NX0?%>DFE~1cDG-#c;DnEbfdH)F~Q)Bh2t0;rY~cI`ZeVS92;|^DWaxwEo5- zH4ja0K?_5jDhc_6(RAB83X>g_i)!`W+o{UuD`AERsIj!)#48dtC&et26$?dA0AsF6 zWmv$y$o8^n?(eQNv&l8V^5O-2z{0Q3hg1IBw{piQ?2Wij6{gvY$<7wz@&PM z08g_RcI#cTFR$LNzypGl+h0#tKOia8MZEi^&0gg0pVY5qxpHP=DEA=%mren2Te8w2 z#LFr150Fzq(Omfx^J6i-=@)J6T4}bQUwJ91;-yd7&+a%DNTPzCxoCuuP~+NG0Vtro z$Qs#?06V>NTihpuW;9yV59vRU2AlRCEP~oT}T5cC$gdCY`on@HSXi@e%kz97i4p1a*R6eV$nM$DcPF3-4}j zJb!ccqouDQA#G-jEB-9clQfFo*+{*Sok&@gyKLJBx9Rq_e>JmOx;nk7zwymB&dqr| zlsPD6hDc(I&aL8F_@SFY92U~2@;%l&X4$tXEZM7VE@NZCspbBd15er3086<|d1+<6 z8&;2b+h-q96)5qtkXR6Nq>)kbC)2HZ{#5+Nj|IB7uTfwy6__f`nVQM%&BwX3F(npS zrz44}@Ksab(HW{Sl)_a6PH!xU%7qQ=HNSHmsgipIwjG3qX8;j&72USwZ5_qEv`55=W0`d;Oi0rsP|%>FDZwm9Kqpdsq3;dpym4DktEutb zk&v1=>t@@#nvI&4mmL#`s+%jg=|0N47O}YX%F-1?H&Dds_7t?!y4}SN-EZQ_#I0B^ zn&(ptui7YhQ>jbb4`BVK<(^#JH{Nz>b~{uh1;wiX%_9O+!nSR3%1Gd$YDl3fGu6yz zdqb)=Ud+MIzwmf2y4|__mJ=J7%U13euIt)b;X@@oHWzQ@^65=AB$+IP&hpJtk+nfY zy8yQLFToEh?Us=>&c|&X!C(tD8EZ@pPg7EBk}7)USoYi8o^jtd8$L_sJH5}Bts|OP z(mQ_-ad`FWX=jQSD&jcks*$q@>eNzCPch_n-2zfik)_*{(V&82^|kcSQq@u^GAK%j z=Y)u=BRt6)jYE)rp53{%*sd0nY?fgUqJT*M08FJ%<~k*^ z=#9SS{_0QqmJevK)MDYpPfCqMD)@lu1hpzE1qOPnp3?qgUnw(LiK;N!98XeU{E~kU z#O?exJ0m~aB#oh~w+3>bAvJABj^05U!yoipTii*y^Y1pvHW*pQTq>ad0FO9rMEZ<+ zbvSK*b?!vvi)D*_*{(MmoNAh9Zw#M33kg`%d4R;Y9COj+_!;xhJKkG@r>Q$^;%DB? zi>%A+-Q$R*hZ`2@r^X`7mBQvRl-g)%vy_x=_Yh40M5u)%1p_U}$CG*1?{%5Bo#jW? z1=SmX6umwrVS%U&f+<{rE7m@H-|U9n$`%pxZzuSRvk6r$E!~Ws4zom-H#Khzw__ud zq?I7jpju4TI&2k5bHXi+j-RZIRO$*pulBy4$I?t#fEOo+`F_Fv6OOU2I4kitZ<+r9 zC#8SE)fE2#GT)V(qi%L~JE%5J@XKv{KFh>YWw(t+4$DhF8Lh|^lD0yRk>B(*E0MGX&Cqtn05OT2mme`9GY^4VScuv(^y zY_`PS8A&s8<*}7>BhOK`vXzoGRtBalV0xHmS1~=8QZl!{Y&V<6*sF4v?>(p|Ty9BP z4~m4;tJeaDjtJ^P=bvghE1az*w_T4z!=Hy*EfPro0EjTHG8i7V&BbpW zo47VkE3_$c^zF0rTT+L8Qf6zNV4+R1k;BEAhO(%?qMc#Kxh^ko=*#uv+@$YjVjGLN z38!626bMCsDi7z^Ki_WM?e|%Eb!~~8df+^cgA^Sw7ag8(SJx!yQFCtdK}oOt7#k`LI~;dw%H}Tw2Z= z&nr+gupom%r#Tr1(}zP%{O&R*0o6k1Qxgr7QiAe;(?$?X+B5&ut}8s9?HH zDh(SI%?1eKFh^9|?)P-D-t8>!rMCLGn%;Mf^s~akp(-dqV_F*dk>}8l*xw=cKFHbG z4fEPPiM0B|XJFuIvbpW;xv_g!3re1=$x)QdR#HJQl-wu`&cuZZNdw%IYrkA?u!OYL z;)()`TGaiVL8d>SQ4Cz02F-FK7UEWOhNXB@0DclN*15kfKjBQ@6Z((%uG{#_v$qe) z?dt)WnjOh2RrUV>P*Kz%2(o_~%Fw>++?4AeV1Cmd3~gXiS3(=v^`9%>TzB3-gCC{~ ze!+qHpR{x-gJGS5Ymi4D?QioBpC8MuUH)BvIPaeyGDc4azPpCIue#$X&k^cwnOdEL zv?ilt=%UQkP*qF1w`d9%P{`NRLR@N&7_V<)%Po&>v7^TTX$RtLpUSu&km&l`ZnU;2 zQaa1zPEY0j$3d6G-{pbxSLT%!R^aHao~f(ZG}Y5mLXcO-`iK*$+K7_tu5-i#%NYD9f1P6NCtq@$%yF6<~b~;w1W00hDnq% zYgS!IPMu<-Di0DX)$jZb{{V#M?ET}nrr-YnF*m;ain5nERY8yHeVI)b%%!ZS#t6kt zZgXkY};cCV!h#4Aj7F$0Tf6a(ZAu8(=E zWVYp-`zr`Hn|;8%3i3$}d^Bf0v8g{FZd}!9NEG8sd)WT~9ljI)04ba`cIDVxQXI!- z?>OpU+VsmqjeX@VCYo}~1UahZugGJtuuY+A@>Mg*H0+BUV31ebPs|(j^|KqT-+j5f zzLL5Th*eQv!x-#U^&nL69S`|?W8FQ}Xm(wbmu$AKT(r~U%Awm^k;X|0@g|Upl#04g z63yk)X59X3yH0~HM|JHAO_Q{$CW<-tKHkjLW)2n?kz-oC<}$Jv<*K8MNE)I_VjWNx z2*6v|XKvoEZ>|#D*%1@ac2w4w;C{^0@)hWLzxxC98*G<*2LAx#UBsmLbE?K0LRm=g0lOvnW~FD0k0sWMthr^hGSIJuc4MlH%~x?IN9P z_Z8C=ZW$b0dmrsy&RE8(+t%XJQK}Llqz{pHsXsa>uT3`TKWS5%Q2JNam9O(7<<%GW z{{YV~m>(zRpZzs=_h9afO!FC+Y0%}4)!8)de@Lg<`%*kE-(3mm*6=*6qt@(hOqI0q zw=e9O+jgjXGIAT8g$Z&94V^dR4i&;&nCja zv$6jGT%Tv)6To!AK4kQ6x)0!Y%zu;So?eak=h_?J4^vVp2JQat&$o6g6Y5oH>bKVE zY$npDk}%qe8qXn7aHrXI{_VEyafxs55;Z3k$v`g0X7i7K{_SmWyZKYFZWEBIy1J=Kyl7{8$0EFYB9@;OvEik9nCz)hLsukvfbzH0#~jJde8TA* zme*z&1JQ(F0zu(c%Y3jv&qg~f?7Nhg7WYL}**i4UQ`a@AK49bQ>h1PMD`{YMzAl4c z;4m9kYc(7nVTIcGjD7C&-NBr9Z!P-(L6bz0-bICryUN*5zv)B|QueGn;^2fV5F1 z{<2LW3ZwE*w&j&zib>qjP*?oJ^F2Lp1Km#zv}3)^KhA$4o{H`}A5yz>F}$WnQ!aLw z?802L$>)}Or&DWKNXnPEBmjQHUY|m+ zx17H$>wG+OX z7AKB>BZ7cC64y4h$y4+iLH__BX%5-0OfUpDnEC$zKb1OMo9BlTYK*d#pdjP?pPhRD z(%c8d`-hLo0Y^Wd#l7KMS6h9(WPDMLBiE#!Z+`5}xg$ZA+!Qd>qPsO55BGH{vD`nB zI(=&vkD=DfZ)j(~v$i^AokRKzpXJfbuFtq#0QUBd$?9-3>0UpVOeeJVCSwznOip?k zDrUvxBBohYpx03JH3B%p$z@maTyy=Q?I-U`Nura%oN6j*<(eP$eZ4OI!@FD00lBpy z1dCc{8ih?gKgrN-@oFn=ebrFfjFWCS(Te~Lp`%a%1A$^svc6dqw7EXA{{WMtzIny< zf&+mMm(28My@>h*fy2|FbGv)XV)Qo8sNH+cvsA7gEFRvZc-t|!E9`u9v^4C&mIZrx zXCucF{Y~sWqrAO_#vc}A+oIo(NK(%=7Bi!0`UbJkUou8{1z7Bug|o~>KGPEn)Qs$6Esu|d@UlPw6Cs5k;Qsj z(`;#X1`i>g*_8t;J{Fy-w-(nLzr6UYa(buE(olfk$1pVF{%L8$Ju-{RfjwT#MWDEa zrnGMmC?%4e$_JSKCG{gK<~;gXHnyG#u6DvqktJkG)r(kK)Ay`8i})GTWEsHgcJ9*xZFgR6TLB zGG0~O5Ykjgl=b_Ib4C_QJY8}s$h35-wFMhYvY`b?zn1-@xGrSohtUF)NRZUGp=R=4 z27@Po`9}WQ{m?F-a2wCL*WqA|$Xh#h{?sWnX{HOF>RY3*#)NFpA2y#qKpArC>10DQff^ydQy8?LFv(#UHkW5>lBKv zrC0`2_&=Xz*Kx$@-T@!r{{T1mI&m45fm1`!VY%q0j!KhGh+~Y2PJly3vLHx=szGZz zGXUc1ZTKVDLgflG1>g_o(Ek8ox{gJFOvhUaXMrHp)9e5mar;5&Fw7vAA0o{ljRMBN zf^{d3<4Z3L#q{5gW%3T(oOC&}Z5IHdlGQ(*bC0uzdPgQ35uT%;8DC2dLY{OI$dYQj zN<&$ok%pwHM;u#`dymhu%iX@ub+wkt{@rA^agcnzYIueoM09@^=eTV5QD0cxyfdMo zBhTc+%}=4nMO(1?<+ff{h#~uoeqE{tKDwSJA|y^4j=7a|MJO^05(gt!*Vr3n53`<}RhK+^s zmk}3k?mqF~H1yeB!B>yP;PzG}$&#CH;OMAnvHCu)fP!*M2-l~L~#JMW&~x}gO9>9#Pkg2{{VQVpOUsuZ+T_j8wh2RYq_{I^SiYX z4Qe7qBfAC3$e_uJ$zc3}%qU~hRKkiDPbQoCS51so0{;Nh`u%;3S`vp&ntZy7Y`0A% zd{)(3)SOf1YsdUO2l+ZF;Cm{UnF-dd`q7kn(TTUDqYtmw{fD%&qXK9TLkkP2rC#C$ zXMr3IcptW-%cPb{kM5vqWfGa?0uLsVOl(_Hp=jeQ6p{$P(0fSgT7Uyu^nY(SiG-}m zA{qOBc|W(LtrW6j(ahQaj7klyFT+hW5`m2*c{W2W5MN=QL@Cy-UNabR)GoV`V3YSMi$kFT}1yG7;V ziEmrMwHfqcKj+c&Ir(%O=O1}_QnAJKvJ!36PyJa0W-)B1aOL1;*jv^ z!+89x=}wBpR_vdTcsxdLG>Y)oZjBRGVNG0QMAZ{k2L3I)t0R%UD2*K@@9MC(y4`aQ z)wIU;+eAw8d9cdY*1TN(nECXNmpz2{H{DD7UT61zbhx$K2?Z@`5^V<|LVsmugmGdT zT2r>U>b&zA&er(}zv$^&uRYjX<1+p{bpt?!C@G|6^O_n2DM7aIbkSeQArVG{^)WwC zRI=_n)#{;Vn(4R-3IXRq!BlyieW$Fz+qS+z_JfqJCtG_>pOx)}WRp>>j6NN58p(4z zABAe{Pr?AKmuwvnh`eK+0P*o_^=dH107~k7U8Rbnr<#wO@Hcs6#oE951;gpo%e<_zZG4t{Tmz=&@C;UW zT%<&BflvI@X5rGSuH1taPPx-0#Cf42cv|ZI%4)f{l%~?q_+iwKablG04u8vYE_Xk|b z`h?V|{{ZDwbIQ@=6cSw|v-<*$bDDV>H&<7&at#!U#772?&xa6etIUJeM*FY#1>|mN z<(qlEwuQFOaja2-T}`Q@+?0x#HxH8$`coo?fa6QYRq1E)FXQ0(qum%j@aY}HgRATP z^Ngc@!R%=%+B|f*tVB`cKZ{Y|>LXg|w`N-v3PoE)!aoIk4J3>fOZ$3ln&X)_2yU%p zPp4(?l#DeoRZ=Qkj4;I*RPpFP?5Df4{n|aR+`X;$Q);Kg~A{uDbT-}&wO(JUR_%7MvYOpvysVFO^p)L)b=N4W?@Y!QC&WOnA{aK zoEb{TLr9kqtI72k6SDGl-pHboHhpA}`kz7kg=hgLokzA-9`JqcIpADO;Wm3_3er*5 z!)}C{m5pmzXJPni(@JPus&KEIFJAnZ{$o3~pLuV*oZAbdvGr0uK2Hm#-N(^biD-5% z7Nf#gG2$&jxRLyx`em=vLtLe_Lt9`fRQQ7j$xhYyqtsh}ZuFN*CQou^ z_GMyY_cvk<$5ocW(8eSykfN`ysgihiPF1JiEebWw{QuR#sTe zBQ?R+z=97}CD&gJs`1nR02S<>#jeg)6+=EBYf~I=un zJ1$*xI`3}_vGP$t_EgmW0DyeD!_IO0$y?q<^c6+=hNr^sUIOvLf0cSl4 znXJ#m?zW12MtdRGf~hIn?s4B z{Kjegk3d@;qu-u;({*9D?$2iJK-zwm16`~BZd)Blics1` zPAl92;xSP}>%Z zHQ+$wk?IEl*C@BHRo=OF>RqpQwgN?c3g|<_BXA8IqYR|b*9X*frmx8k*~f1F&)?hY zan;f-e(T;_k2m(Yd1j6&apxl^+Zm^XJd~K~OjL13WMHbnJSN(`!Lg;@=XrU0ft$sZ znxiBVPLV^z@Sw>Ye7fm=$+z0__b+UFEI=%Fwy{S}0O>)f{{XgXn*9EKQ||lR8NB}b ztw^e5+;!QS`gpO_nA&=pi82)xb!$&UhoGWM)T38bG;pmv7YtcZFYZ>`Ea8W5g%%Q; zR))N5PCql~PESO4mo&I`l2M>!u`~b-@jL+Y^6Pp`FGu&X{{SuCtN8a*QA-zaQuRj2 z+uOJJ&1lC(je3gca=Fd7RaZ=9wAgHYLeV(&0k+m-Xyu4~<=nZ~aArF(yp~AxE~3n_=t)!&!I%~VQlx`gXQI=*eoOp2{!?8$ zlEHS5b6__|Z)U2X&gOdiYGi4$oAW)K6p2SmjmK?T2CS>wcnnkpv{htQ2bBqXF(Ct6 zCnIlYn6&mkcruK+bR0AE~_#+@kU?s`vgxt%XJ78V;Vylos>l*r1J)LE5s z^2ll0v_+*gV3S6FBY)vcUEjL#b=VJ#{WG*Wh39D@i?H{_Y`gyebW_uTrYW$yW@u=( zwj!;RUEZ(wm~INk6AyC^$?c30qD{ZdvRq@bBEc8st*FP!vx3X?{uwC==TPHnZDsL^zE=Df5+pQxsa($k2 zFxbt3x2fq?>m+nGnIjftKE{&Xa>pv$n9P>;$T+Hsxy5o8u1VvbJtGRu!hn82c>%}r z9UQ&+{ExeH=yU{{T{?tg^P06f`43_ZH4UWT#TEwLac$-r)ZEp8Iu{ z-a8qQ9wkBIFp*0uhI}d-5nT*TJh}+`599vA>P$uor(*2ZlOa=CmJ(#LQq^ZNvr^-# z0#np9^%T~pki;HV2qFVX2sriwv*%s+nCH2VcHIcK3cZO)(yTHl4n=X2etl$(r?4k*WSYHESXu4t%WdUN`*U}YSTs;F3OmsTDk(G)IOx0i7?aIyNRJq*F2W?QZ zMTN&w;pikx4GgeSfYT|GvNxUNZ^%B?Soi-R~r=nIzD(P)mF|i_t(GRaXA)4$bWf`SKg&| zR5^F0lBCk(680J*#nFf;k~IKnQio6D+^@6pzc1_&q+3SQ3^X4VH9zL5*m7V5u}=FrC^c61Tlt^S!H$s zRY7JZz+c(%JV`j{GyV>&KcIh=2lE8^BD6L82jgb_ariZ3Vx$!{VhQJ&t6il#Z|#z38iyEo*YkC zW6=Kq@R^#3(j2$SFOfbY6GUouUq|3evpW#Y1pD`S(-`9^Vv-0jvIgX&2Zz)IhBom9LkcDb@A-UhKNQ`}obXvz0j* zEB6*Il3W&Dv5-?^sUXc@$AKxS@$~VjKww-A6y@ngdenEQX#TJ!+iw)V5SV@ksP%6N?Aiu|kl zI-iiErODG(P*+5?6qRv26U5&}M;5sH>0~^q{16YlN{K2-9E(`kP>+{Xf>|xzIihVc zDX2f{{(S&6_4&@G%S}OB4MtOGR?gB=&A`*E=_C@{#|3O?Ei6rClGhyb>^8F8?6Mf7 zQuZur5BWjzZ&ASXGmakuz{owY^Z+q?EFu zA5e8GBU}1{LH2JR=VK!37Xf}p2cZ1hCg}_5Hl>HEe< z^tRf*Edsx@qPzV+U3s8(_>KM^o{0k2AYb~MelPy?J-^ag6Tozsz{wt0apkixy3IvT zO$Hj3)aqFsC2ESDI#{Vt#YM;U_L|rA?&q8kV*n`oc%QeW*TCCYTUs!r%*ET~iVlQW z=}fM=KX2E-f1w&~KqQ505&8Ca96HD&8UFx_`+5z%z>Q9<Fz2M601TIMsTen z2H>-T$)uBT?4bH@ac^s*fFP`9r2PK?)t-uFyYU#TwNNk(Jvi6o51lE}w;zj!S4rd- zh=qGxUd}(w*nXByE;;`IU)h{C>R2%yzv{<9+spZ5SBVemWPZ;-&+_VgloV|^^nTM8 zCCSn?0*YhR!5`ECYx{h|ABkF29+F3Qaw0w7s40)yYyM8Z|I^xYc2Rb2{m6d=+Uq{g z+ojx0_G^CPD{v(VcgZIbo0Qf`d2gw3-K z+V$9M3^^J~>}K2BIJ#V7ZjH}e^z9Q-;Bn{e{V*8=O;GHRQ;uD)U}?JFSZvm;_bLOh zAyHHpV@?2Z$C_kfwUpA2^Qt<}WF?bJ5Py%l0{~n}te0v!v3sb#)WtjU`M};Ob#!76c2DeVI!qJXtI<$$JEq zVNv1WR91$R;6FO`7JI$8{oB2x_WPOrz~?IqyFHe|9?cgG<4-Xvox|Om)4R8&PWs=qaa3ibr>CW*p~obY_)IMXF{-T|E`nKQFhcTO*p@ErNn(Ay zb0y8}hFO_)9AHpm)6jMEBktF{o7cMh;djkD=D6WXt*x@LXss=^5|N72T!yulN(Pb1 zGz&lj17A*&u~Li5hH^!fm~f@PE=S;8`$_cDvn@eC>i+--QLFEE5kn&@AOL_#B8pD{ zO>)F!D9P!vY@BM^VrP(o$l6qpf5h>}Kkq))$7JPd$^!Av0O&v$zd_6HWwwrA4hbGt z1(mddf643QIQrwM*lpLC+c`{Tdv90daM|oVRCUBxCTm@h1XuDbW5KFZIsauP*sg(P8I%So~S+ z)rv=X5HvGea0w_s+Cfb%TA>xw(J$IPL%6$pv-Z}*+P!ZM=j`YzTsx?R6*zq_1mwkB4VR?;IA1<6x=h7>3 z2bLnPSrR!STOdI@sb*s$$gHJR()=AufARJmlploPkM)16_Vg;*3dbO20J8(ex<|;5 zIvQsOptEq|=?w*3@E0e+D2Y{6#YH+J8n-TQWYX$kj1R(b|g62g@N?5IO4I*N!1R%>Y=Q|{L>3y4ao z{ZB9Te8)xB7gFul!e;)+k{Y0sPq&5-0msv)zLVJtN zjX|wA)bwL#Gou7rX(V|A=jC7aIu2?mWT07!K+~vSKbam=Bz{t-Lb#Ut5=1rP%M*RV#tS>s-^k!gCCkZA ztA#x2KVAp4b0DonPCU94?bj#65j2b$O$BL9Tm}aK)Z#H;x1#Ua9p}|uDpk7&aZ*s^ z>s6N#hlB1jJHt5TiKbje+{YzGQmnG5Rbq)AudCbH9^<_2n>wp*7YdHw3W~Fz^r$Mw z{aNZ>rTaCvxIs0w=xxpXBQmBwrJF=c>m-=N*Nbrr@O>x|)lRPy~_eFMH0jG)(sJtQO-sq^7U8 zPXYF1{(VclzxQt2M(qaJ`;?pR`o^9Wk}}(jB+9%Dw2C@>B#iY^J>m0zE4u3P zRNG%CT}uRyG&Os(FC!*yu~mO^Tum*CVd(U@BEe-UMT(w1#k;pP%XK5@or$hpj!)P; zhg}W!x9+{Sa{aZG+ue*$AONMLAQ)3P61N$j8LdW)BZu8vLBjv zE=l&oXp3^@t-)XgK!)Bh9(lBkBvA@b3=L+HCz%wXH|HJDzYFo7#<#XkPR#CFn3Apx zd@)kKN(t%|tV@Q))X4OkPZO(;ysUPqkwGbQ>GpnCY2}E-w^Df9iOmHoU+AgAFU^g5 z$6F-DM<5wfmNjVgfma{mCrVFEQcZ(ggfz5ZDCr*}_TNtmpI z1GCnD@=cwD$ut;vpjK;1oT&vWv$f<}{#|jY7g*N!_6ObhlK%j7F0Mjbe*&5ce@O9T z{JvdgH?>~Cav!!4TU>3{&v(paJMSisRK>j@T%-~DY0}2DXFVofFq}jG@$9t3;b}`y3cS}kr zAHqD{zCwU;By@A`=e!(=?Ec!%zbf5x9I=xHg1BkqK2IWprrH|uk?KzbRy|(#O8kE6 z{{WAhdZ!<boFEn*?tV6>n>V2J;5y}Bxqj{Q&%3+4H=NIUTG<|!)^LI#gH{z{iE|{RQA~^) zN5B*mUaPm|m-8i{!!A><{yJ9EjPNRhxoGhu>RDjs+xA&_-*&v`_eo%-^b@S*7@BPveXKCe?C_;ld6^cl^Gn3bwi&N zK(?uBY9v^Ya?Akt7C~iyyWHr8H=5Y?sG@*mCD}OqkMRAQhFI+@ zKIq&{H8h!Jgb&}mdVIAcB+><%ZVfz&I+n!h_VFx%KX!-!p#R zXOovbpxfoPidOK&YuS z2OpI&_MCKC?T6h5m^r%Px%b~q#%;G`6}XZ)Wu^4%@iW~_Ws8$B0-9sN=p)&G z6!G{9e22>4<}bfmuDW9$LM?}$$UR)M)mzPv#qJ1bWHMyyY{6;v?lA-~t(Ia2vcv~(po(pnHpch8|~)%dp||Br-Qc)7U57lv5)qnx741bziWQ({GaUuCpdG>;_u$% zyLg)3vPT4slF%%bX(g>mx|kO{V^r#*vzw~3FD2QMC?Rc7(!r`4bX!;gpsO?6lE;(& zx3#-|&jpH#0%T#9IVb&(km!5N9P4?!NNFyZQMCk8Re#%XVtAULvxi$M{9pNf+xhN> z>K?D@9+2F7?{aMIkA&NKjq$n+v2Ch(DAri%3_c@IN8zQT5yYmVtqz#~07bp1kC^uf zo9H%;o=IegX=xnM0T}W${j3kmtW5VO*bi=O`OlfT{{Y<2bnUjymvgxKn5^JY^>3{c zS$#pDTgj=|M-vTA@p<%Mo8ynkuH`RL-+kiydkIig+hq0V0+1tWCZ12SG&s_zkD&Pt zOB>$j+rPOt&B!0$8@GoM{{Taa1NP#gp0(%%J>~XC+i7?jIdT;u`hI zk}KQckC#IJ%lJd_<7P&(4Wm)ID?q%J+pj5Al3AP*b)0=UrJ+O3xI_NL`!TlVjhfbl zZFRS+l7E*E<catSUgq| zkPazu*y?HspGqjZtt=|e+6AuHKF?!@IG02*s;{6F{{RP2hU>j<`_$&^dfg|wxc(`m zX$a4eVridBbd25KAi9&OD0@s`)Rry0azOxtOEOWH-*u-dPQaOPi{l=9-fYo~Ep!$KvtX%Bdq*)~X># zO!tg1R|P`0`_C_Zbaqxds)S~3C{(HkJSire4m7FaXZGcvltDtwUI_K+kV#gyo*I6+1dbTM`%e;n+I;%w zC%8WI?p)Vu`##NN)*DQil$X^sqk)Xj0UA_M)oRQ;Ndlv*bIVUhi;F3n%w;Jt_-s8b zW?M0o$VezCany9`)4gq6)hr-}mYF?HT#irmAbSqa7!ye>)2D!dvyv%KHNnLPoq7V= z87Es?D@#Xv*_mUF7rmUE6&i9`ys6|qMD?S$^CkFS)So6kZ||<}=`Hq~d#?KilM|Qh zP`DX|eSc!Wk3pWy?C7e@QGW~E^pw=~Z8cPC8o8&CM9VI(YIgqsd#!ejpja-|CDq(a zRyNcUGM-g5EOeTR04gb*b&=Z#-Rqfd;(|@@bhojLtx5o8m1=OT0SK*5J?%q^9;_ev zX?!03Ti9LKN4B>QK})|olAee7rW1E}UT!|dz~^Mgp_3?>eU~i`KWSm|F+>GKP)|i$ z!ZSxAu=YgW?eF{it!*U2&^HB(0I%X2zCBdP$QbCqpS_y9WTjVnjiBb z_!fG;qhhaiZSKhJeWkgg&TXx;))eyZd8w+VM#kUZg-8`vs^x(Jy$4#N_czV_*8Ka-X2{wUTT=~H95GK>n4D$vb%F_Ims5yVo{E|$ zd9J9TnJr?>J;{8x?EQ|`VxM^2-s0hEbfD0Jpn00H{#EoH3b~Kp&CdJ9gO~Pbt)Mv9 zDe)ie(lns;^QWokp4D&N>sL>dqLX!JqQ~aNI_5EySvtIaFDR6AJoItoF|-oX(AGys zG_27HBX1iLMTsZet7Wxq+jym&nj=z`rCal3R{niLyT>qZTl|S8@wmx8l1hSTicSes z6je0EK&cofrfs>mbDOU(Pq#LH-_34}^;4o#V0OM9zdM$h=5UFl8;GW=t0CQh)Kb?x zpKD~1B2y%?1wrOW1NNSYusHQ?e;+@QfAbmd*yysebnHDTwJQuw{p0T}yn8Nxx01|e zrrEUcWw+g3;`Jf^8ypXC46A#9w&BjZ1%f$SqdbG~#5Gj^0H!oww?xme40_iFzD!++hjQClrY)gji^1PTF#u4};4=g^O1<*nP8w-i73sH&)h4_UZ7S94FB+&g$=BAKOpb{bfgEncZ?FYGBk^S|$~!f!Wck`_4vs;7t` zDuAGQSN3(1e6#HbE$mFUo8UM5sK^bAc+LpZ9~YtEWGr!7bsOTx&yMK$+uHkkb5Q5E z=H%JAyyi4^UtjKx)mgZ<-sju364S$$$YUYN&sUVg?i?*GVW^~@0F18)M-Gn43tG)W zHmTD>j1UMubPf1_K0OOLr<3-MYTKo>`UHz|(0mz{P&98!jsOye0g&K>*6LDKQ`ghc zSK_Lptj5*R(q%FA5XMz%C^9sOS4BCHh7&u%P>1Pjk_WKW$7|9z6ka&>uM_x=c=d?Z z%2YaBL{@Oc7!$#i(SRO8p#DG}iO0@7NAWL@8>M`L5sk|2+>;p)Jg*3@5EQ2+*X`;Y z)PNetfopT@y5Q+##{>SV^&)$DK8|O$sl&%2Zs>E@(l zH841X<~o+StJ>aL_YU2gaGFbP>Ln`-@#jr)R!GhsI?$dBGC}g|VoibBdvCM$PRscZ z)HMyC*xUOD22Q3oj7L_nJnc(e6--f|O?E1>2_UEd_|j;+fR$o>j_!N>E%Rv$6RfRPpDL;kOhFavQ(sDWqh}nL_kJ-`Ge8;**p;}dO^IZPX)U0n= zY}{k4tBq>eRf{WRCu)en{C>rf761?J1MSGRn+RJ_hf)5Kukzv5C*Su=h0GUt!C~ZO-y5ICBCuSpNVbPs_-3Fx#U|pKhCQpBGXs z6n`}zY2tbvks_ytIHOSz|=jKfplu~X!;xeEHUrKZ7S!ZMnQspPy%Q91p%qvhF~^pZ!iP0w;$ zaAJ(sbBuX^v(UqrId1QBngT7^k=zBvbrJqS#GC*;`qo3dKc1g%Z919o{WDv&@K_3Z z`h~~O9^a$OZ z)7}_~JYH%H?$f8FkO>G@iEFm(^p%iGBnQ`^g&f-6*DmMJ+jNwb?XFZ;w62{{Rb9 z_!@%0>3$)^RCSFW>3c7}@)AwHSza#b%I2S~68@xB;p4^$3JxhCB?-aOXbrVN9BBv< zg1P|I0Jze>rJGRHNFv_kL{JcE96!m{H%ji(_mFGD?erZ=s6j7@7T_BK{{J0BhIJ3+1QFe$@GQ z+xv^P`$sy}HP!Dm9v2Z#)5C$J5_kbXpaD*a zj#noV75&wDG`kl?0ZLq|#=4jM;3Jdy2ajj=c8)>pqSSHq_4_};(p#&T*MrrwT7QG> z>eD_D_0~H9*6?rHC>8Tt)vBIsgR2t;8j7-Hq@sv2i!03$k;{TQI7HX7!X8PUmGK=>glMLo9Z01~Jsu{h zZ7T2Rj%F%>t_+1EyOtyy+W!FS4`hM`tE%PHRQ#%N2VC!yb&*yXraB;*h)_WVimh0h zir3T1wIq3T-5x+N@o4lG^%VLuC^oW`xF8-+GbE>gm*Ry6>c_o%zmisjq>BDSMBIW zYt9^>aUq9$_VPD{YD-$&&jgvtW!Cbc#~P^32Ln)ezA0k9ALV;TwVRmgTr%(sk=F?@ezU66iw{CMo zcpLjU03qvwq1TOmeN7(N&+R?;F>>_$oz44})6C0oik6r0hBIoxf;pn?ZxD8_uqtvz zdf2~Y^nY9Io$tGQQxmiBxcDuK8ki+$ zp!sqAMierz4Ar3MUcJ4DT0tEv)PYL%>-+GUq=Uz=Q>2#d-&}|Z?{$g`~;+)9}}L~lh3|G+7F=kkC5o1?yr=an!ahNwq72K3r@mBg10RX@jQ;8 z$Hy~Mqpck~IuFo9p>N6egPiI2$LAf&d9Aq(te8od|| zt=>Ctf6BBJGYo!aXkA+gTPig{Sk2{EugO-}&gwOrs6gTlQ}%8&9_fpkV` zhtJI8^Mk#CWw_$5_S2redNuW{OR3B&SuFX+YfY1&`<2+jw49NYmqD2krj=SJ}{Scf5|<>Ske7MP|)K z2%rP=G{?`Q14~N{9XwRD=&{2JghfyQ*fsOg@%KH8LGy=-*RmdxSsRNr@-$>JFR&dJNR-&wzJ7PfZGds=xGI+}hE#;wE19*s85vvb|&`faMhYm0%! zV^YL@wBh!e4vSvx`4`soo_Of86}c$lE#!P|J)W9r(2~NHX z(|bj<&m>Xq^Ib-!hDc*23j;y{Z8fJFkxEn7sn3_aljnPp3*A~p1GfPrlx0)HSQ>yC z;68qxR-bzR05B|`_Q^j|{5r+d=C`N@4d>fgngmUi*6>V)C8nWw6Vc@NLN=gv2UuJ5 zq>L^Oo84HslET@!HpX>nlUIv6Xc3_pIuGL`ARj6kXRO=yqwarY%NA?y58gukExBU4 ztoE2>Ciih*Y8pT^yjHv^LJN_D zrLG>Ts;TNfyBLD!(7e^mgV36OfSdi(ZRPU!7uPLuyS_UnE5f^)l0m#7IwbSB++NkIEjw?d-j6W@8~GO&spD z_)WJ@7mE*#j}M$ZdAHkJZPtM<6l$8~jb@OcscB_2L_jOpy@)u|k48_Veid$g#g2!wK1Al* zta|?d9Zmc~Yz0kp7~R2>#e`Cl?n?Uq0P=mGj4Cccy>o`J2yJ7{tCg-NRleTl@GStY ziqVMvn;(FG#*fRWSKR*qyw1n7-b=|o&h2A-=GmXa6RI?p@k?BbXyfj@m&+7@Qlzl2 zPMyK?-)Zd3T)j{6YYRuWa5$Lcpl$CR0EM1XrYUFH*ouWRRMZ|x%GdcNb7oZJH@)th z>1k-Kw(K#5MHJUcf6g`Y{{T$ikUb&x>+YSu^Ck3r{{Zi{ z{{Z-z@F#Khi{m>dx~c0n=UvYvSv*$NndYY5d*U*n#U*mCi7*>pqB~jJ{HmriXu>Ji z>|@KknJws!{{VN?wuFWen(BYIhLrwi%Ngqueg6B{?L3gTyqWEsk=^rpgB-U&2DP#^ z$W9`Al|O`joNbpZMxL%0dvD&P_~q9y<+n~p1=rgPZc+?>7ZpbYH2!viGSFc*&JvI; z`CP3)UrceUGcngI0eAN(PjO?l+N;V^8&nif1vq&sjwj?k(tP^oPcCx5KKsAU64>mP zw>!5rUPQub;~A<^k9rAZE#JO{mqqd(*$w6r)V6&1G*U1A(V1*44H%OVe{Zpq5mJF}M4qSn36YfO51 zlk)wfVDvWkgWq09_HxJl-Og_LmQ^MT2v`}I(+@E?f*Srg1zS21h{e!LUGaPQa`nih zUoBSb&C;0#IvQM;Xm&knAz?L4q(>ebZ=}m$Plke=aH2^+RG3?3SybeTpsHcez`RZY;e`zbX zMsYC-~(_BgoHAx`=%HP5O5k@f@06Hes zmGe|c(@iTpk{xWtwH7DUsfj0&ez*1}g5EgLM;ZWw9Rc?(-sbLRxVfCPu4`J>zIEe| zpX}<#egS+cpS}0~+ul8wNi9EEP*>Ar;=#(2rDpzGSzU!7bmD_<381w^@9Um0%M!4= zsnxZRD6c4@dV2o=vHq__q?os68+T z`8wx4<=*4G?lN6n%{9*HGi0+ovbjE0I-QMA&ZPYMDm|_9$K!8P$x%U5yhilgG@*lS z{=bQL6ry!5qMoxa9I;_&-&*Nw&g~!NeTR1rYuPs7%O%*7U*SqOB?1ZEQ%>CR%tQxQRDG~KrD3m9dGr&uucB}xf7jhVYjM^VVsluR8#ytWp^z7#W`Nr zz?Yl3*7Eg*3rB4lTgHAuM>0uHInt->=$iI7%}SH66;qceIA>yi*!v3I^G`BvidC;2B0f=#0RCe?wDpmEq4#(8dy`#f+4&yYTgBlm z&a0UR9M)3Gw674O%cm}=_=WOQx@V-zU^WI<8HlU`alCiy9kYw6f>tQi5YLoTmCFWJ zBp9G@>&R|Lw=6kJm^Tt85R^msp8)XVT$AkawWYZU+^>cRpm}h_VI}PGTz*2HTCeIR{fqJKWA6D@n){C zsy05_>1>Yh-dpP%x8XS5pSgF&N|!00q@h9nNw%x96x38}RgK5MJai^SX(3BSSg1`h zU6+fu*vD+QGRh+zrO2&44FCiV3tj`RS^M#2Z_k{~y!)4B%e!vZdv@L><+YS=91iE> zxkP7jvdG=j=^DB+3y11a}Q>c;*Y*=m4>+^Z@BpcOS4YHB)7RDeeiPadJ~c{#&>+cu@y z7Si3ey~a0=M{2Wzq#Y_M0+J}o$5F#j3Uo_*_vT;9kCZj_72WmUJ&)LQ^UExw0g>Dl z810`(CjS6C4Gzu1e+=6cRE_@t9HXTXkHGgjZTlwCwF+(fd{MXY1*;#KV^*){)+yH% zt~v^O)2KU3xAQPz#X6O-~8>d~XhX%dz{EdKz5tE>3u{{RWn`S;xmkIVL4eSPt_ zYSpSuEZhG8I=h>BECj1Mrq9_;lt?NXCb|jhqte_sQV8}IxaYl%6q`1Ck3yo0{`Ay8 z%cOTVOKe#R7L-pWqRV%N=IqasIrsw2H7-{qdfTr&vFU3a zx3gzEin1h>+x(+8@l1dRgOWXw%g%d+&?eqAhBN0)MxSZN*^Y`XH!G^?O(~jCWRdoo zXYxO9S4q~L1@XhLdQ)%X=?rsJZF~mY+C`(%t2IS_b)u%Oo!oOLlA)Q{ zomVFQ!26};*5t@#xp`bINGwmLX(xFUIL6sLMu8Qk)3lY2{yE zKCA zsI(KYksnd}e7NV!^Yk4WkB@)L^SC>Mbkk8&Z7PkgvNF{)r#sl${5sHJ&fAKxOAu5&tIQjtSMni*U7B@6BNuI0WK;T(v`G%ZjoOppkp4?nk{KQ(jDF7k{wFL8F0 zZlQZ%h^x6YqU#{iC9f8GQ_%Iby)`W!Cl`dmW9a5u3{4I*5s!>QVvXo<)KJmVvzBf{ zBmn6g1I76EzIh@(8l)tOk1P-|Qhe)5&~=5$;!8E%%+sirMt5w~hIS-@P86*x$D+ma zAeg!Xd`#4-IH_DJ)IkI*Qqe?mDCTwK6qXi6VW#Xq*7jd|ji|r$KntWNkUC3LjM3TYI@Y~=0;+p8?koPN~w-#-7->Ax0zyN7uino$0UkxG#XJE zkO6K1;M|;Y#0x#_!G~y$zs!Ea^Xn&Kl*g#4p)~n_tNgueZTz#lQ#;e&%9jD#8^;+} zrhnk%u6_14>4Yp|!qK1}ch%A6I>W~dU8L{qL ztJ}|Yc9ecbjLfUsNvufp;f5+m5mgNKZh?;b)ej^%@ zGa9q5s*E)jwCcn$yOO3yF=S|DSjK}MMwxFDt43YkdT?05ppJBw9P#XL1?P!TBxF*V z95`1a%l7q;SDR0Rm}Ug$wEeWf^ZfJEtecAm3M`~TGpmQ z6rE@Z^oC>fxcd7{*Eg5nr)L3^;|2}Wb?>Sb&q`{cj{}369ERnonk6Xo*!oms1v!RB z0&1z+IH`bReL~*J_YK-OwLt^wxS^3smf$q=A)bHnbH@QBjtuf>~sXE1$@;am!OxA$}B% z0@t@b{kQF86D`Vva>lgdLG$BN>r8#UP8J(=j>ia&&5KDw8bT?a6hZh`)6DV54yyL2 zCFhkqZc8dCX=G+)m5|v3mb*9ui~j&mVu-DLG;K?Qcn>P^>A7x)cMobr3M!x z6l)AqFikRPDh913kEPI&e;9AA{a<*@ZtG#MOjM;|&=($`Q_(mYjEv%@T5fd=B+0e z@<*)kkiO=m4;35sF4B$Trl#N6>JLdu%6f-de6&b3r0kOmEY?{YlsDGgl1;w({{Y>U zxa0o)PbR3rVZp%l4MAS8d*5Gd6O%7u<_=!B{{WDs`x+?E(#~pH5;%z1cS22ZRIhGs zl~faO$VKj1YzZK6wigy2#_FR|=N0Q7S%|r(g{lVlSo(rLOl5S4==an<<^3q&)4TPe;|HG z&Cz=+EGv4aeJQE~$deJ}Mt*V(_5Rv)O8FHYqYyl`P(NXei+UORhBu9{+U_??B5Gnttv_e->*WXUfxK=~ed4{(Ysut_>GzrBD&Q|>vrN^4 z4FC{9$N(Qsj4ZhkC}NI|ujm6$=|#2vw$fx{f5peLnCyxb4x}*o@hAMltZTdGU#(eM z+GLU!>;q52tH%bEEZIJzk4>*Dq-~^u^|LB~;9J%7xNq?Gy<=8%)G_H?e7??s_ZQbT z_Vc7N(TA8&9D3CLDjpc={{U<6jCKa8Q#G@;zV@KFVL_fs>S;o+`N0-P5m`r96Cdk# z{{UN$X0h8UsdlzjPdbB|@W`R*7T3h=csFCKqbrduJ*(B4%~`Y`c*auc4O&s@IsC1F{INQdr+4AyC?RrT*5{P zjl%){)rEhbQzp;OKF4nU6kO5D+xF8t@RH8vE4Wsp4q}}WPA688Aw6DS^7Z&1(7P_X z74na1?>)uaSpCa{@^xIh>t#o^D)zKe)XfEc;Qk#hnJTi?DG!R4pu-Zy0cVR)kT_kV2OE;o4Y;jN2ZTKzl1H4xKi zB8HqJ<3zf;er9F>o)+eTrMn0KTr3>pJirZ>?@JPpCR@iKezUD zS02z8;2*V3ZRD+>-TeZU_1`|Gy* zPqZbz+!p7Y?&EK!f}n`-X>&N^;REoFF2aKqJxX5LduMsin}bbq%?B>qu<@m(3!0D7 zi15}&6Tt>fXgVPh`9I-~O7DonvpE{o*lf(J+fUa>dl_;c%BXJrvI!y!AOcO~cWmnWx zjz=6@*%jvBaNu!FW|A7pd#z0sLaR#CE2}F+%oHgHjX&$#*fkpe0At;t+;)qpZTAR< zp(-&92=mAKzn4;e$G6$v*qdwnWSY)t04Uj4TnZ3)jwF2k&W@MHuKFG0x3ZXQ)b#N0 zy`@bYS$adIA2*0uBZikf1Y9`{BM9dN`eh*f8;+U%-+kd8=yK$ne(xeLIBn5^GLQ6l zuoB=`&+y1RnupJ0K;ij)-||<29i|@O9it92m4n(#az8?T3N1Ix>p13{{UcrKBE40yNZ^UaZ^(d z5r`+x0Dmg{s5%tAi@E@H?|$pu7vAUY*gE>#a{&~29pza_)c`nIXz(=b4~nL`JC8M7 zpc5243k^@jgJQ?t1Md-U?TP-Wa>Ofj&vQeplSYos55m$f2bG3WGld<`#15u^YrU$M zoU6WX5;Q!s6oGM2_Y63yA0!+d{d-q6BD{AVUvX~?t7LZ$QnxKzQ8;Cis-kCxnVRfY zI%|mOBK#u86+rxcee(yIH-2R2ZQb{7W!>&CZ{(7?q;_DZi2-;(OZW37n&(!c}d$-QOQy?W%f4m$7$3)+RE#3~PYL z4UEfFI7~d*B=pZvp{fK&L_j;-OrF>KSz)=zyvxi`s%*CBu^WWa1D9(50HL9vAI9SX zgQ>IH9kSwm&JF6@myYkfJb-QX#SD?OgB~=oD6GOWl#J3nLsW#S(9`d5{OrSRt-U8% z{9DCAweT>;^m1>Jk6KEpjEm!%t8GzKpkp+uH9ktSRPXgg2F>nq-TBTNXj;RUqX`(t ziKd^L1OEUXKWH6vOWU8izT>`b$BXTbEN!Bg)n1O1wUREZ9{kh3MAyR*zSt0HpyFS}{FS0}X`tBGc5Rq+RZmMUH4gx!MqNHOV zsV0cm_>WdzXg((Y053db6}yh24%+zyDEzc^aKlA5a)P1bB_yPxmFjW*dx~~E)zuj? zGAAgkNMCXy!ONVJ3cTb`yMc@X)joqFG4sojkzTNxO~c>Mz1{4#`%F#C{?Yi9W+lWj zC^-z^ESrR&f1yRD-A)*QE7fLvg86mZUm@~MF73;VKG3D8GvT%d-sfTiQ zCPIm)+Wm2ks!!t8%)qTSLp>y7PwwvBSqG|l7s(=mu*T=;Al^5-O`an2Hmia=Qn@~r z{uT4}G&BdOo7qobdBfg)(LZ-Y)?A+ynr?Rq5cq3Mw07Xr>Mkk4ROnJcmDFJCbJ=~X z-2VV7J02Xa=a(_Qw`NjiqT4$|Z%|cK(BUZLlJR18#@?gyiaJ=e0VKp3WwxoLCy^3f z-)?*T*e$7>fK>*7SAYVz`DfJB=dQl;cO(0K?5`+2hQ}4Y*|0#m?k=ZwSCzobw>J+> zZhV%ZSK*BS$5vDEi}_zlB%t2^045$Nsp8R)rRt1Ta{VD5RXgiDO#T?Dkrwh$(!T&7 zG|Dw6v8K(*!ZNozp~&E$^bzv=0j)TZk=7r3&G*rXR_m7ioKqz2Sle@zFg0WRN){TK ztA(0XrGK-Hu-yv(03$z`KE>)gbJff9 z@4Z*oHd`#;uJKJF7uRY=rjp`W4Q*i~EY5sVzY4~^-2t6*@V6nGT%XBrpIi2Qy@s9R z&181|;LZws{#^~_rKjDQG-B9lX%Gdb!ef-xl(O0(=_S^Dyz;T#`I_i~$4eR?m3+s@ z4(Pe$RWXwzEz2`R#@^ez z=4mD)ZROix9k|B2QlIn>^JD4_dN%g^?y+lce%$@<-tznRH%fd%Z1NdkMid}VAvL;X z;3HiY$x0}773!3?M*6PL)Yi{cS5+*vwKCOK$yHY^ZFWYYS7(;1CtW+eMP*cubuo54 zo`0{p*zD#f@#a1y!Q#iroSJ>Uyic!F_VLaTJ+kfgXtwroC{>Cus-Xq~(P$J8Bv1et zr$K#PSE@-RkwUW`U6d*SeuDN;1^tUG?4_KnR`C+Rf2fnxMY`^ak2Lpp3J{(ofCW5- zXg|-=o3EhRISjQmPVmZP7jM&6Le;QgXnyx0l7=}oR8eE3np%1&s#zCFd0Zl2@|~cAh*;Q6N!oDzQ=ZJfC2Di~ak0 zW)5X^C*c6oIrv6Dm(QtJW8_b0eV?%tZJR#Nvcjql)K1Z?%}>N`E*Q$h*E(2K`D3AP zVSg^4mOIusDj#6Ou<`Ph(^tQtKEHdsj4ue_KKc0{{TzYH*;s- z-r>xU@-MgXqR@dZ;VEX%1`u17P)8ax%q!*P)q!>I#b1km9`WZtgxEVf2Kd;6)o;!J z09Q?y$wA`%#;JVn=#{9k@&MjIA-|JzdUS<{(SIJrR@+Y1wlOK{-yeIu*Sr1Gea#z%!p>;6HVDwh)yAI&*m#l;l#Jud^bL0J^D_9+*78))ZT!w# zx3>fri|n=?I<^@lRci{J*OfHbwS+R+jWX3R{3-T^`S3%RQIng^Bsw znYSI@_ccK4X%Qp%VuMt_lT3e?M5{IY$G%o(_f7{iy~VwzsKjTnxx95PHElK<9ru{Z z=xZq;d_EEiNGGOwVhYg8WmiLH2i??flm4aNj@-1gUyNd%HgrdgRJQjQg+X&GFpsWZ_4d zC-U{`dF2g*XXVQi&Hm_f^qjrRNQz^G-8x=eDfmi5R(RrKD5OQL$HD;5MANtb0FWN_ z`Ayc<`$uqB^+!fjZObtO{Ijh>`AGl!STkS{QBisI2-mNe9f4f?9 zM&08m{{R`jxpx)erZ}NnV&a62Q59e*nXOFMvcK2Hs%q-YWePJ| zH+SSU_0|4Zy8DIw=j`ovYff96kv+q@0bx2tu<^=@Dm-r`jNlqpIYcbn6e%F}Z=Vr< zaCE21UZC7Pje*O_w9t8Ta6{3OV zP8B^9bAPg&rN}&^FE{hAHtq+&U>Yk}BX*urKd^&ez^YH`T*|>BRt{B(RBJ)S{7~y` zijC3VwQ+XlW?81Mg0FbbCOc*A{A??xT6{LyN{So~Hk^qI0P8hNUh+uAO{a~wllE%} z%UwjXN#@UiPd`9CX`Zp;aQnh@y`vq6+B;_D-L+Ik$!4NU+lddt(_EF3c^ed{DG=a@ zp!C7JdI$MzLq#%fouBd6j*=&iC>ol#4@F-{@+of|Re0LtT3Owhfnq`fZU?n8?VOmZ ze0zH>BLg52`Ga5cbZg7r?tS+qx{0cCy0(RWnJ51MC^(9m>OI4cmZDHmjU@Fd2vT4p z>mBdhjmlf0ci1-tg5>8wZD>!fl0yPd@SeIm>}TIg?_J3@2W$Js`%5n}a$2{9E~U2? z_euy_p^!%Q(yEFOCXO<4JX-K2T_fB(+xd8Q99?nqAEh=f99_=o1K(q+~sFf)Vgb$npG?F z0E+pHiQn9RW&N=G((<0;?l0YwnQnI8cDDrFY;w&dv^Ni+u|WZ1uuVWra>8EHQZ$gi z8r$bteD(Ne-#J=Mz1ANlI?p4x@<3v+dwRboCe+<&S5r-I9v>CDX|WQ0>|S6JHCDTT zg6EHEt}JgBg`+Bhfm=@i+)9yw`+SF7w!P&JYS=t=-T7weS}7RJC>=va)Mb<*X2DuE zDl^j$S#?jz{;uvxhG(9G>Dl@z%cs+l4tk&Ptq zF)S2;>^Bvr=WldOw{0bhRcg&f9-X{F^`;L)z5AIxyyiYuA4$u}w{wIV3M>)UHw5>C zAOTqlf_uP`T9mGObosemQ-tWrB%)Q8OrGb&(L7F}1d+tGH4-et$}bp(CN3;}Am94? zwe%riLd`{Ir_UTb@$%@W+j?DdI|&E&R_w#fRM2{Q@XuAn&>saluje-Wgm)xaHS4aR z$k1-wrq06JkvGOdz5x{m+skL6k}0u!en71Ck<%xhsxjgcM!J}Zxf0$@ zZQ-akzBd<1jK}TDY;6>HTwW6vkyB%FIQ(cskAjMh8feluLV${(@^9=xbe=oO1lHh3 zN}8xNP>CXw5Xs{*NkLl9x`Ym<$e>+G9>_PFSTF5b7_Y=G zC;_OUrP}kUBHpe!UAH?>8mduLDX)XLY9gEDZZnqY-#<(w=tYKABE7DZ>$cv3~ZnAvXAG{`4Zk!To-Rf2<_ zB8L??&rz2#^83xRZbN33pxlg7EG$@r@rpK#@c_L6!KO}lbxa+H{M#yeuRWF8({%3F z%jCA*O!QLZahd9)kEzJxwLvkL?l3saviT~beo8zK4gUGZB>CB)x#34q=AZKqy`)L!*>4w zYwip_!|D#2qW=7Dn%aD38m}doo~R<#P5Y9ZRV5S^93; zZ+8p2TE+=KkoC_Kf$P!M-}l$|XPD= z$+a9~#t)R8IOEJ*&ADz<&uO#=NQ;13K{`P+RRj#VsNv>lK3_rJ#d|jf$IDv=@9s2^ zU2iLFq@^^+Jo;-a-Wwj-|C`ZC-}qLdM>mDgLYL#mBiHZP?_NjIo_Q zr`PTI`gI>}8`N;sUO}tSf1Bm&(j;$a(cGW~R3QpW7JW@;I$1f=NA=`$?ELI3%DTAc z^7QlQgZjXLngOT%U*PF$wYM!M;i~%qC)(He-dLk9SI^;7BP=p4iEyI&PxSUfyX{kL zk$pj3cGUoyaIP{vK7AeSTdX^To(8=W(x7_N)93Q(RUTS;DT}K-v9T*C@-niU`j}aP zJn}!s**jUsaDhkxys^>BT|6#Yq>nu3qrvcpJVZg$(td)s44VR5KX07nWRkpz#BHRICF z%W2zryJ6iqZ*%Unyoji7B^!!3^kiTdAC)*BzM)-N**jCZI?rKt=U(I?%52Wc+Zb)* zfUb^Ik&O;+iYl>BJdl=+D`-ru1mJ#|qhW46$~N+?+&1@C{{Y!Y1AgBl=tl$d>zsSW z*LBPLzU8s*h*tX2R*8p^(r6eDHEISQBiH}d+VlB|e4wQGY4Gp7d*Z69F}N_>TB~n$ z^)1RhZ(?r(_${j(WU{jgJcVGYdlFVEW`D5;l(U8qoWU`qYg+)d~BU4jTQBgT8^%Yff zJw;s7b8|IJ^E0!5R{Hx2SXd-}8i;`$N%Q@^XNC3gm82ocjtV@07^nFw(hiU;l~nP~ zDTXGMe6sWVQHz-$PxVv>+3duuQZgo|0|V6g58Kf^bS{D0O4ldT*ZFnVS#=+5{J`(c zrP3WCwkr2__ujc*?(WOLB*{%lM~m@!oqE;s7NFzO_ z(hZMj65Tjgrnz36UA%{{qK>1!VBN*l-Nn?8rqUs$N03Fp{Ld5TQ`X3v%lUfzivC&M zch}gy+ui#|vUaZF4+?HgjJbMzcG=IQOIua7Yrl=EG_@4S@-;n5g^sc$Ya*2+*k1YU zH|vQW)fpxRlp?kAu0PZ<*93pOH`kMl<(Eq`OH2Tlk5@BQcef7iFNnWZw8HKNle=jc6te!pPo#0qpDb`JZ+>|L#w+*u~PSm=sD zN@VcKU6FlDNsflVnPjMv!L7oeE%YAae{s3{X!hrncaCn|*c*Ff{W!Hy&og2;SNcxe zX~9Dt1EHTL@|FJpHgEfO$z(rLW~)6aBZyGEjp!6`u1ipP^;VUehcmqMxjoIAlkReP zNzBt8d{pp&7MhBhK6F#k#1&OX766`4zCZ3f&%X2LG4A}`%oBLKt>lH<_+wrP5-*ZQ zx>Z2(0GyN7f7)!@XDn?t8y41@EG^SY`m=FoW9H6kN%gNn77Cg;VRQgIs}d})s07y6 zWkqEkqokkl9D5pU@G8VqWx{}KN>?-jpDsRNW1yDnGs!BkBt}@!dDGPY0IS!cP4k!M z*IWD=+8C)abOV3)9{G++Zm;SpI?+jx%(b2u+`Ec+mRG}U>I#vi<}2i?kQm_yOR^5R zSC%gK$*$%Sh_=WSc(SnVLFfSZn2riQRiNrp_IKHR``(TI4YtLkw%Hb7lH4kXW_%w4 z0K_Xzr0RBK;lPJfl_e3i(ck|7A-+_6fz8uz9_#Jx!$~YP(dDq+f3Rz+_MXeyIwlj) z(PD9U$>I_{2?F&sO;uYVxp_W-4SXHC%2Yd5zL0lfW$~C^B=`X?>~o zKidyzxpVhE%gQ!48@$NNb9FpxJd$b@WNBmtWSqN4NTINgT-f4>cquY0tPZ_X| zLg{1Vt_Ywf$nYlyoj`u^`xhq3WqZvWiwK))O1;IAO>Y!prR2A!UNjkKh%AdzrGTKZ z+U$Pisimues+PJ+xk(gjJG`#-P&Ldoo`sfbeG9>{ZU83M_6qk$*;_5!ZoA&OUv3ur z^gz2rwFx?munWN?090uKU*RKx>kRF0Hb`f;mfm=Uy8L=T04sT>NLH`q#DQA$8g=(# z*7UDzZ5`&B2_U7&SAPWD6x7-nPlT(hhK9O^pv$5MOR#WFin50O&HdwVw|w1o?Y}*8 z=Q2er3uc$XxK*cgGBTu*u;Gg872rj9j)t7$$#%ZydwtAYvet^z#TSik&0g8j3&$eT ztPUwbP(dTkon6jCqfJz-Nu5}UeGG*pj!05UW{jYfN1%(9Jd^eJ*5)b=L8_dOm^l>u zk6fm=jQD7z6>Niyf(Z-{4?5G+?daa^$}>TN#Zx$6D59s9a-goM=Z$8Rm10Obp2U7F z?n&C9Fj(866mqpbwLZOL?)7!`o2~rfx;#b;@>Mh+;OXoFNB|N~&;fFP)&tpy1mFzx zR!A8q9VYj#;7yyhGW&|ECMJTF+L8uBTB{)~;-IGq!P7NUC}Z>sa(#k5$>%$NZn-ah z=G*0`(#85pN5?z%!iVHsja9~wdOziDie6{mw%wK!MVdjayp}PU8or@xLFQ;WtAj2} zF}SKS8K;=!GW8SIPb90O%TX~7?HD#91utL+3br2j%`N@z{{X(;Zo93|iGO!9Nh1?l zyO2o-j*w0Vkf7_J3l)yrvqNRJBK;k*DkvGEt_6Rkjyy@J>F%QyA&Rbe&iZ0m;y)4 z0&CWr{gK(7{{ZtJw6d6NUN>`Zn*RXfxg$%mcD+4B_>3~GY?Pw2CRRnqQ<#h+U1mab z3co_5k8@R}p82`k+HG(~-%k{35fl)BP-i}7xnt+%20HpAdr#)4Vr~3Y1t=8|Yzi#H$A@{8 zGbIgfMuk^1x^e{YXz@{KEHs%}Zb<8I}Fm{{Ti`6!zR* zOR#a#K0cduraFp;a@A5P@gMHq7M&j(v+1Rcc$E3;m^Q6(zqLD$G?5R{Y|w};lu!@= zH2#PfQRRxYJi+K;?SI_X$}Pn6pS~Nza|bp|-XmL?9qpC){=BS2muwH=J{$mwXm#qW zWXM-$>l$aDGnw4EtcdeTIh!kx%vV;*047&y>+%^Yx|gs7J27wT>ifQ6DXyK)ffUA09x8!*?n|%x@u>hgUlet6v()tW$3DA_ zswLT-Mb@|#5X2AL;IR?QYY3u2{#BUER2!QCQB^aWokaT|6KA&D3Y3P`e<5G+l7BLK z=af+Uh3@|VH#mtm9$@Dyte=W$bo!Idz8y?eiWF7B!scH37z2=mi*Z~$pdaM8h~Fh_{viFNq%@K?D0Oy*Byc9w5F zwKi6Aag?pyyN}C}-<#;p%gaup?J+!Z|^+f}ncPMB>P+)0$GLtj<_5Fk=i97hJz%5bdL1Wmb-QR+TowV?iy?mvV9j-iX) z^WG1>9_ewka@(GhPEp_PdMnvVG`^5e3*<8nT8 zeCAf73R$H%9i@#kN3=G5I~#?eplKLZWQbrTtem|>hmyfSKpL7&$C#(_Zycql_)r>G z>>gP2;&^bSGTV}Uz2skHwjs0frrk@o1L`j10j_5t49wsSDPM*Z(;Q&@HK`q4utUZXVw&>uE0<9EMnEwD#{lA|@TlX``b2N~|poXYD z#PGla%RXceP&x}UdzzAfJP?(uuLD9s8xI^zc)aohYv21ImOjPy8%);)WO1U~%$_Ig zALZfJKJ#a|8)nY3+FG!=-hiUUr?m;iWMTgR90alRr%d=fCR1@#u0t_VA*2pM#2-pZ z$VK3Z2cjs~=v(Xf`ukshxm#^;8%q?VgjD>$qXW9P_v)_stiscF^Pn ztpk;(>7tI*QGm_I$P(41fc$XyYux_;BXXGP9=qBS({046NNV?nX&(`^=wnh=rK8D7 z9r7la0$M6$np61z8~X(0DtT5@69dwM!g;*mt2 zkdf`}sYy{=9-;sN<6HYPpK;o@weaP*jv%AqUNrvzN}!+R)G@JpS?@Qyb2ja_a>nhu zERUP3hG7vWIk>uYL;lr|MFW0+HZF<4tkCRjrN285AS{s2Jv|=K!piM?J5=Q5tIA0j zKaaLnKEwAs@3h0K>CxqHUxa^^zvCmR^OgSMzUA&_DLI>%cD<(5s4+oDU{9Be!x^tt ztJ+^Ay92VSjc)wkTeE-EBQrw#pEp}RI-T5t-)W3#QjVPtfn|;)1N=Ru7CW});r9#2 zuNqXbA7_&OT~7N_dwK26n_F^EE7;jbfJ_l2I;mP}dU&!PIbu(#=(}Y%o?5+D0aM|N zK{8Xozi$HFy)oDj(r91FB%fzin-!J0GI&~^xF@*%zbgHMpsw%FyS3<8Vz>!ZCBlsY zr0}UVG#qkk>C!=}lV4r`=?6BD|%`1B&sX zt$*UWyU*p1{HuGDxqAy_cZYOsJcnO&R?^I4cU2W0?4X|;xcgqG87x^0ZX<7CYvGQh zZF<>}KJO<`iA^L0ql3!qOm?{c02Ug&Jy#VJL+ivA^At2R^ZPo*k9+>}9KG%S(Yo^Q zE$)$CbLGS`!oCaZTLU7rO+CzrXp+XP%?tpUi-l)Yj)nH0`7eUrTi2_O+S-##kH~Ia z+q1Bli74cHR-oC{IeJ<=g3oLT0qQ-)FF~p%UC(Mi^v%m?KvY z!Uvz3>zp3e-fWv6H^aGZv8>ismb1>P^gb-;jU-@}#<>_CI29!E$bsHJCw8a9O{;_I zZnDQ=cNY7`;Z}x|16wMbR?yqc6+F1aX~GtI-E8ec|spayuK1!`MC3 zZrV|e3PIuNF_SPXFR|IebbyOQ0zW1M7_HOFm*!+^DU5$_28(Xq* zkR#CI^SfhsIb7Wg^i)idg`}LNO)m}No&qpX6!fv`6WdLN z`EQb^-KK)K*96I+5%8r|R-kafY!hF%9em7t)6Uku?EBfte$zv|wTCX-PHnCyc-Z)N z6S9feM#O%iX;>>D(vB;^N$RqD54^iGxpRNT_tx{y<)Nynqp7FB$B?g~+jzL=nI0%; zFmccJ)Nw}$@v|~CjKfosZ|sWqb-mnW@h+}efjC-_qvRKW{gw6WrTm-iUnBczwT-)! z`DW7INaJ;B%yGTUr9lOxoUW%N_W&3u28aNsMz3ifhS?pMAF$~+_SN0Atm`qu!8T77 zT})=CFvykE&hG?|4z-ZH7Dc-aUX}K9YyDZ0-~4fAj^uh|AIyGrsOkddFZd;FxtOme z&$MnFyC52TW)VvpX>CBG02l+Lu9vGE9X-dQ&E0<%dZV)N*__uw_e~aVs**Q9!ZOYd zLmy4yZv?F@G}w%^6314cqnHpI+T@Nw zw(WlH`(-VxG7C8n2gPRJm#)}H0yyXmZ}T=0+GNxZ~Ly+9P^ytoG2_82k<^ zcjsF#i^fF?txnlTbf~I>2~c&6Y{^w)6GZxBEOaWakPum1$Gcu$h-)3ZErk3uVZe%- zs5-I3$YZQg`_KDrbM5Z=%NxYkV&?02vm)kdQKY-JqRBNt6ltR|GZR*44D3r1PTv0j z$>+7V-(!3t#pnBnbw!z_*!$mbY;BjjGp@8Xhht!I_-S$U8JvxK#4@#*3hJ5Y#O%eH zAPU8Z9>cqZq(5CGFh%-+d^N2JCnMEQ6$jxM>zW?p?S?*aTTPPDAO;;H^(_RV1G<39U^$$5RKjzRP=sYA<&?-H~mkxB*os zkrBczNvNw3YDEK60=+A~2zTGdzPQ^vza6?eTW9Uf<-9Yr<{Vz-o=gP)0K;hGk_t%X zsH}#c9SNwcowOrLq>y;Ey`FNka%|R@&3PV+iC7ILgwaI-KWR7~dFVawf3SY`ZkL-~ z)t9$>h1Shy6Bd@+MZna=79nD0auq-%g*3;XM8El#e>V-|)7`JR{y6m(CTvzeZ{qM( z+qTU|~Q3bNE0M0-QZM*oXODcWqZ{b?;*B33Kx9S}lWD zgssCG>WOj{IQ%~9rmhW$GD`AFDHgLD(n5?*fXo)aTiTtT8|Y!Vw!2@`j1anoaDF8f z#~<+HtYP=xXxgkdjfZ&K;#j4xC(8q%X9Q2>2Ge9Hu5q?P&16_JO>(Lzi*cgq4g2mqA`_BML*L=v6KWZ#9v$ zy5^y^0sx^T{{W^t3p3UmTd=COOJnx$W$yj2Q@1we_{f)%eW{PBaMc+6WRV7_!`0@a zUlg@*E6V~uq%F03i9N;l5boQ|yCtmj*lpy}%(SeIFz!6Nau9Go5%TM>-`&mk6WIN& z_Sa$em!5X>FT30AsJMzbfmE@xm}-gwgjdD5PYzp$ATo_Gj?nt4bGCC^?C$KwCwa$T zNuQ*ZqRR@#)ip?viBaO68bq5DFd^b~c3HvH%*MbCIcIFzA=|C)w)aUb-?>ONq4Orc z=%2-3hkygmHMxfOcYVU<*KtNmq{9kR9zkh=9X=2+eEvn}aPD=-lTQ%x)Da5?n5+AK&-3&E-8XS*Sd>;@@O{3YXF*L>T}5QAEbh+CZUJkB zjW*Uf;?K<(Kmoj=OX9#SRy)x`!82B@I_{ zc2Z?1_O?$cPa>sO7iQ7WQqPm!`8q3;P-()_(-Edg)g8=q)z2dk>tYr zq2qLMBr1Z$F!dJ)@}&J&^X(1wvdTg5fl?@I{;%iJg`L5O5#kU*sQ&;zTjzhmW&U9f z(fIej{wi)7=bLl%ZeZ^{o|DKtwH;(76W-StQ06!izJFTPipyMMz`^H z*Wja~wD`O6qZL^!bMMXDx_fhU(nTXEmkqNh6Km~w=T&u9hHTE@t&`LU*G!~xJ>t&u z4zx<)0VHP?;lt!B)>r-BY){m42J%2I5g=S=C&Y7KD$xcy(mq%kT@3nIi6kxQJPTY8 z&ad~6WGNs@flw$q$-=s{u^xRjZ4VuVH7%%)fYFcvt07R&)WrR3C*^y&rvF6^^ zTSxV`))vU!z9?p=m|XtK)1+6Di%SdH*b4Y%N7~r^w69y8f5KzF5$)cu_|2dB!Md?= z)b@AC42ExLb@gp+GBlfOskWwJ@%4Yg8btELQ@r^6kpU!$2MWWY(XsXYD;~5%MFd_6K}*cIWEu%f&^P+na)n zz}mE}ek&_)_Z64KRDjP(mB-W{DoU30saCo(0s&pZUA{qc3y&3jeCyV<_LsvQ{ZR(b~abhsSw;EF%u?3JF*7+k~Sy!W>0bC@R(yS*3~iKQVgA3WFA1OiAX-nC4?ag@zi=84ukeH zTW!}&`<~X9F;le}-BA47!zm^R{4yuct*ZY3lz!L6<@#$i-TwgSSE+iYr+4M*wzkuo zukiVpb6I_(fR;3`tIuZh*__2~Y*o8~97h@$*7Vw&QMIJLL$QtFym%Mv}KPl~Y6JE{q*3WMgt1H0`45i*_=Pa!^Xwp`uB1qxYwchvt z0Db=7*rMiUa6rXPKQA&r!Pa*HPN3Gv$cmBbO+{DA2wf$Ol>-~xxdd^@`ui%Fg#s{e zJwMgQ{2V%6YKrb%=x7c;&p*rg^HCUzj%?a}xv-o4*X<}LxS^5O_15vrF#v%A&(!z2@7f z{{Y6XkB1FK3fsnVNBq>1r|e#UU9^tVMxrAl2Ocn_f^`i=jla|&CzJg><3B99E`TPf zJgMhVpV%sXT}%7ZD#ql=MW$>156tw1`BCy?VSGdA?c3ek{l#qt7Bt1}9kEXS3jOiD ztAxw9wzUaTuID9KHB`!@{GN^}C2IxuHS)H_cg!1&w%=@^i5T}}Dxzjd82SPGNCS^a zxgV1EKX7@L&zE-HQL!E+#MIT`K~+|84Mws^NR;8FbsQ>2m%EF3_P=TNcH;RZ+;h*m zyAOKg=dYHkvKeH;ZM<#tBfgfm5o#9--}Ac8pTv8n(rb(1w;-q^!y2F0?E4`_q^ z>Q@|Oe^O5m_60lF?7y^oC$`+RWw)iIao>wziik$Lc$*{xlG4kUxRrq}%-Xp0VD^Su zmvvI4lq3A0FpjQ~&E}?=ulkr+G%s&MkFWaT-pJWaLXJLN4L5k3Y&xZH(ITqeL=P%@ zk1_Th2ceG>u}(+m4DLd!BC7&NHcRRSTFZ5BsI~o=LASia*X;iQKR_+Rnnj-zrE)>X z?fLx2<<`NU2D@TT#@Rz-Z$y%_e)X*d93RE%*iAm=+YakZjLB5UMc*rq2(;A$(+u4tCn0x%3Iv7-U@cD zwa^-*jYpJHRLL0p2U2j;(M|a!f`bpgw@x~qS?7)%=1QtK+0CgSnnaVw5cGhtG?xW` z1N=SnGv3|0Et{XYt8BG;M7Q#=UI9Z8-~s3hVxFHavKQH1)?Le#b{omjRoc=eCZ8Js zMNiDrHTC)RbNws6Fy7uj^4LACx4*g=OpfK;o0~01iQCv}98eV5I{eOOCp;8b z>R6-4vlpI41h52>ef1yOo$2|T+ulXqu1cfaZSdsv z{HEVDl@CI@qwXZx9XU%hZX$W<^Yt{f8;^5SLQU1FD50jAK`T%Nn8>`t?x!wnQM%ev zcR@`}RF57&d~N4SP#S#t9D6za+}`SQ^!8KpmEZ2GX=r|)6&DwVygWluZx8gzd08u% z$*2@N-v0p2`}v}GzE){6J^Y^@ww6g}G+Q&Fw)$;)dR%o`SeaXOSN-!1>p!82Az2ox9e(rBAbRy{Ec2#?{=|>Y5xr*xy+S%=HZpZjh~gJ7cPA zYU(QJ=C7uwk_PcQYr6eN1K4Y5<<45)Hvwh1ZIMSTsKF$NXmx%fltr6U>^vu8;!SlN zQc_pr+B!`39#TzB8q}+(DBOL`9ZHrF$^ak&tO52L-+4~^mTv{E$r4&gUk*?x9e;$6 z!s8m3K2#)i#{PNa{m+xP0c&$0lG0#a35UY^NICu&Txvt|Ad%Lrzs#6tehF?(w~Xn^ zci4-$_a^l#COzh*87yC(gEflH1d3?aDOpTwo-r)`Q68eC18ZalEAA0qY!>tF#T0}J z)E^6hLtp86iqw8xb+g%Ta_zm<KO&CI1f`*GIKkd~PiIOC2gSC&OeNC-emMyj_LG+K&=ZhLCW6%^jbBj%0PyMe zVgCRe-}{RhwXhiPzRTq&SRhEGPq&FQnIx&IoyvG1f+Z~MOIb$%o;{MDUYbYKZoDws)*XEI>?mhe4Npl$tT3IDdbtQ?ACj6SChW;_>aQB>3)CG zIrOJo_WQ(pneMN;Z*j`}xo#{uAh1(y9HZ)QDd%${of-+qwnouPc&#B60_Vyf=1bF^ z8;g?-u`BU?pV~FB>Zid{)ykWHZY+q*mD{^14W<()A(tNk`zbXzTWv(3;AHbZ=||!Fc=`c@)Pd}$+|JK! z`aWj&cSYXiQ6g>1bwL^9{x={$uKs2vJ`g_}NstL=#}AA>oARf2)a1=&Rv%}_Uej-0 z%g&mtjIzwkC90;!NnI<{ZVkgaAMHPiE9#ZhSP=f#vE6SI86u<`}0Hvp4|?V6atFQ6lsFpPoAAk@W!laLEG)Gn0+Vk&t=y1Kg4=m zC4TON7`K0C)&0I=o|7zyVynnaT&h34`<|VF5%4i|4a8{rbOBV`gd1ERyY?G>a~v1q zEB2f*^!zL24-T<|mA#tg{{VaU_`T8l#qQ5(%iwCY+XEPz!Q!jo0$SGCjJNzsoMqiL zYBXoQdrv#NvRRG6mCNOGIo#b`m3dtDUaDHWrdFm_CQ0gQqiF?U{`Il zNiE2p{!bE8YHOMw&xz|Qw;pcVwvC1zpOp6Wv)b*{M+!!(8Y&D?6+g3DX1FAplTvyG z^82!r5lm*yWT2v@An92jRYd%PQl1fcXFrYy=acMFWwT9tE{h9Rl5ddhA2vJ(Q0Fsy zmA3N5iMr;^_8U#S)`6O`$>*jd%gB6<2cAzsHb<~OjkJ(rT+-4rIcFM0bwIV1SRN^( zAbl3+`k!MvPF(%pqFcoeFs3-5{{Wzm+xt4ko%i0q>uXJC%W|7-wTo4S1;m5M5yB-S z$!dLDp`)k1J$4sr=6=I!Z92^AQ^YEAHT28j#n8mbt^VgRJI9ZvD!;Bqdy83a-qBxg zO)?vMD79P@Kmg(WCg2o#fN5SlIvaAgw^sI2!?|-rki)f56Cq**jKaPQ1ZpzNnn>ua zqkzsu>HJ>)TzfE4W3yeA3Ef%Ms8JT)$42k9sA5J)$?o$)cHHyIJm8 zN^SO#7|VMxmQrd)bl2zR-)0BM)1$6__l^!)18(I@8+&U=p#f!Z1EwphLjoazMg*)H zW`FnHO0}c!zmwes@Xu$_Z4Jwtq0eu+3MG!4tortzifX)Q0h$U4qlKfzZE6$%2_B)u z^Dr(WVWfMe*PH<-dhvUkwEpST*XM`|tUV_uq3hekTQ&Jw>r95?C8=Z0hNv%GXj!s50&y+};eG zS&}xhM@{yy52k{7G4AKh85wVvE1zT>&r4fmO2 zA-<;Z6vZ14I4yG&U>t^%#eeD30={eaUM7@FQqs+mt!6Io8EFi%waZCSTQfY4$CAg^ z$JqpXUg3Es>UJqLC60e3{{THYpKrH|TR2XK42mcM(5N1RPiO#n4g;hZoGpV=bblduSJhbJg2ljx!+Gsyu$L+5`-OHTgw~Q)FLs7s22sI*^ ztv+Xmr$Mc5W~QQ{>I|(Ug{~xKXLbU{=0{>~e>VF26+0mALX$4euI+?5oc!gj4bi2_RVZak@^ z#aaXUf=cc`)ZdS51aaFEvN%i*KAlBe@$RoC@|+$wHuEL5tiTc@XAL_N0bMXAsg9xW zwv8>vS01iM;}7yGuisVJ+P?ekI=U!kltnhr>Pk2=IVPS<`03@|8OllVu|Bcu`&@l! zE6TUzEU+td`eK2dDg}57`2aFo?Cm{ax46H3O|xoQqvXC?Ync!dE-#$H4FSmzMto)k ze~w#X5A)dTqd%0t#m|Yje0Fiv-9=Ryv+@E<*g?Jft zYNDl$b&W#bfd=Et+qJ!%bH!?28h0`SR1~SG9oRl%zMfrRpD}&y`S;wr+nuLz=ecY) z>gii+T3N*~)My%5$dXWMKoZPOoEr2c{DbX@`a`Jq?`z4o=iW7YTMq=-{6VQP)aC1H zs$rs{r=FrmNg$?riPSk$bWRr5KEao>e(r*4d!ufXNX3e%qJ>h&Ncc-*726<~@i49~T4jqdKI{{V8i zc!Y+dgFDxWIqmsZ%ZElD?tSoiBiYH~BO6eC0^!AYFt>k*I@ zs->9J^l0iol@{KirmAhN+*!e2DntTj_Rczb2bML_BTjLZP*g9FDCI#aLEztmr}p{~ zt@Qho*ZN2Z{OEdtq5kk~;_7$?{q3!<(kVH&x{+i6nvFgxGMaqOepJa1?eFFD@;7hp zIdRyXySF!m6lms`J%Z2U=*Ez&>pM~9nufZDQlJ)7dtZh>fW7xAZxBjjNRmYy8CVbG zXh&IR?bqKA*=^@#j`sfmdA-|ii5j4u-bc+qDjqKqHx=MTE9M7PTiCt5+Feh&@?CA; zm`%w((5QlZOH$_}Y4Z4bb_NNmw)RqGk{rf5$##KdkQC)e`VfWH_3qz0T5gfQfI%6_ z1J6nPL*-wytoP*KZ#fg6_6sg__M3FFUSUUBbwEPHGkigAB3c+^%>$KE55x}yNRoA)oIoYS&Bj`;!br$a)LGJ*P$HbX}s$Tc~r^6P!S<+r`7 zcgMkRiW!Z~Q%gmM$MqfsautKbZE0nop? zji7~LA9s&br1Dpp?|l3doOnRJDBZuKX^GRTa*Tc+7`0A1aTy? zh$i{=sXTR_9a3+}Ux=R}dP^Hmy*9Od9^$E@N35u?*fq7UoWzQG0H#1$zZI5hoIOo7 zHAQ6%)n0eL`q}-_v!L8Ly1(w%aO~=TwyC0;8BQa2&=-!L zrE!Jt_E|Wb8D5>NQI&wWwUW1pHjFZ#k7)zl*>QgNA55 zdWpZh0(&i=+a6ZtOT{KTJ?KVAraq$HLB!w+$5KhBZ8At5Zq3wx2EH%+bm%^{*qzIp z6gwxb>A#0jNt)g{3`P!jd4G&o)HNP1n;R8wb0e6^%O*lqTAw>Uu;2ixkXAgS%llQj z+-}7_sMB1emDFj#dC+hGR}|}m&F^=*``0vX)*i*|WZv9HF%_Is+>@B~$s~;?lq#B| z1jG>4bY`si1yAy+o>{T~0B^P>D1w=)akTs1S~_DKk}LpZ1M8YuRm7%JJzksrE$v3G zLOPVJe~@wq=jZEQk7bAN{{ReeU5T%h6R%9IVjZdmuhXRz0t$q#Gfp+>FTK7xe<;4# z#8&MJ%KfW|mnsWOoyP9%$G0+TQ%^@Lee2g{gX8LCP&KidHjSh}2sg22=VfU>K<4k z0D}_qA17{nx?gbF=4-v6WRaH(>dGn^Y53IC40dI1k4bbiwc`NwecH*w1$VE$6$XgTo-9m?Oc~#ZZ6U6j1J|&WA`3YX5@Oa z9fIGRMspU$Rc-BWcSlafz$8>0?irPd{xKXK`*UgvV zT7yjFeVsx(uPp7}-)@}2xBIQkn_Z=amFq(U@m$6syG5y46{HI3Tn2~-aN)+V6fwB} z0FB?u%jMr!V>brh>5BTlj{ARnR^sw|$0?G}K^|W({3WJ>g45HkYdDp3@m5XyDk6=8 z7Pw+AEr;7}*73)SAB3c2$l0f$12z1IQ2zikeds>s`x%1kaOHS8mvXfZu_RH=Du!`Z zE@yb+Wh4qYEI~A(9SIx9`FwviUa^Y5a`gwwy}jDkdWxU!W@{)?ra+Psl$6cAu#bzY zX`?KmOwhA88i%s|!`Y497Fo9Gt!8ZYe`eYAEGTR9BcT%? zSL-2)swy(3n)ARd#e6*f}Vr);DT_01{+sA8XaupaY^Bw|xW(#*w zRnjNjV&SNwsK{+xvqK_9F1&q6WCZJr@&K1G^B*8t@3xZdb47c14~H3ZMGe5TZUI&y zOHfv|r8it|zU054~`5y7;hC)?=4dxFT{QiEuOgHv7 zyJhX(+ql_1z5Tp~H;I=+M$3YQe+@i<#VJaPbQ$*VT+wz`-gJ#2i*n-Vc8`A3@P<;%obS)XZ&0Mt( z{{Uvq7**XPQ{lI-o`yfdeSZnhs5FhbXtLP6?oSt;rk0B@kF1`SzK&$kH7!I=L&W?5 z*8Dd*fw&|edA+pFXLVs~bzvxbIS?{1$Y4hw^N%Bru!nep^3wk5+i;Af;yDbb1xP#( zugLlFuMVz5`8|Ir{IAb`#*eXkY-KjT#Z8HqjxEcRrZQ1w`&V#My2yI>XVvMv6lr1n zV}{2cqQGrEskZ4M$Kmi;oMM=1DJUtR(uk#0mvgD*a$Us`Pd7y?0$`LuvcHPq9;?BC z;K1?yoPOSmW}WuC+k26StEGqZEB+egaf*D;UokzSPhCMxxVDB~iRkmYXFWYFbu^%g ziWt7X3(mp2i%_2Z6X-UIzUsBPx9jD9V1?6Z?9cd17Ur#^Tse zlyJcD!Kgo%4waD89Z@k|1y)T=RPpuFc>P0>&#?2#DB`uL9SIRK4-T%={uA%=3SN!= zXFVx|udQlbz211O*V6fb&glfTyN?wvS8F_gNT^;t!-IhnSR-7c@_nw_k$$D7LEOLK zI6u!x`E?xox3~WEaUGE z5{OXQ3{>@-%W-Z!%~L1{#f-B>G(?uu#jSB~c*VXvaofgqpXxVP+bw47OL5|w=iQf=Q zSBCx>NBgxEwUpHKkS```hnCdw*>7ffoDP4ex%MLEvHtAim6w8={&+loT?hGx{z=lt z9|eU!EctcyL-@bc_}+&2#qryuag@+dQ1w?#_5RnAIIgJqIxV+BE^fY5Dm2vPGcwfG z%ugmsn3L=`yj?Zk;d3*bYc%^SkL6CW(MWrX%a93aWk1O2r`Rb$_H>}n)=fOg8yL}K z*6VjB)3CD?YmeNDoooT)o;`!_BxYc^r}=-_9SdwBL_)w4MK}*HpU9J*fgZ`&TOYT! z)@x$#O|_2QTU##z)6ay;Q^xeqBM%bQ(=pRgkI6tuXsRJ}nl|NFeF{r`!tToHZnoLl zJA~jt{zQ3$<_-wyH#KrkD|6Q`U2?}f>~{N(#c&Ua9HOLP(c^L59E)DrBP!~69zAOJ z^4sFIFUG#l&f|LbFIAE2xacvtDrqy-6pfeL*&6zpA)f(Iso`vo+IWPJR0UR&87#wE zlG3)@?pDPz+1Yaq!oj%7QCx`4Fbg(xYB&|eM;dj=AG|O3VSA%tx9>jSdmFUea~~qx z)uglx4(AGhS%h(gA6ptN2{4Zw3Ih{Rw?J+SD^W}#j;2_uT67GJ3;Hbf5!eCsX&aIC z2l4Dne{U7cZ8fOvrVkqW5JhSaksLwmja%-`Bv)5j-0|WT}~-#+rdFu%?t>_LcX+K4Ruu z&T8g8>zTJUEq%CM$vmHIj7}gOG{W%G{=&yDt^;aerKhg z6CqCwQ6dC0R!FhHt9NL~Ityu0se{}P>en{Y7xgvs3zS+ti<2hZ*lE7KLPHNIgB3*{n%b_^&7glTgl5>5W3`y!8U2RgdX8F#0-o=c{BI~w{C=mFv=CKEu3@o!=cx>lXhfd@a!&!oG@J3~Ivakg%V7*eS(23H&_ z2IN zYxDbh#$E4zLe~@A+=aG`7G@;r0YynaU=`}uIzO-Wm&Oc6Q*?GF=Eg<5w>CDG7R6Gx z+)Iqc#~`R&RUB!0tc_(wQ36>42vn_?8_tz?WUuQ1k&71TPU(AC{TD3}7$x=0| zu_qOvTH>_NSOM;rH**iZyN!m$$-5lw%T_b9c&;>wWg|(I$?c65Yo$ppL8}3Q)qZ#H zYi)$c@9xsw`5Ha7wc)C*ugO+qCk85NI7-D&5=6I_ddlataYGPinnR@lC*L(W!v6qp z_b1#<=I>{)d2hEX)-gh&txf@mK%ZSB-*r3Fq{ zljN($r-lUyAazMUDL!`hAIwY!(CF+-DroI-(5{nJcoMrWng4{ zm3;Lxw6u8bMvEO8P^$9=nCGU^y4><_Aab`VNjzidEYdkN62eJx@1)RF24Vpq3|5>v zlf9|?yX-5^9LLUv(o3Fg-EJA=o<#%c;2QAri>n`@o zOAcDMlGkg*jfo~Al07k`55R-TL8<&l%b^c@?AbFretF}7yP`Pw!PTI z%?R{>NH$Newv6t?m8Od0pw}^P@LBHn@iTXasUDR8pYZf1Z5#$uZ10_$n~EtTd`9cr zm8j^V?`+M%EI{RUDaVIL> z!V=^tmKme*V3Whup`9wMvM6@&xw83O#z*2;VqiDk-K2(U z*4sU$Qkyq$<17b*4G!t2r>WZcy7{FHsAd@D3IjO;?e2f%E#G(NN$xF%))ionRFmqY zK<0=+71q?kt$fc6^_LrG-*ek-uFA?ka;$E)oz_Hfs&ZSS|W9L3AK({kszTV#zjzLkv3u{)6@ zP8Fe?MJUvPw32}8pcEwaaZ_PF+f^<`nyLW9!BCY{^Ha^^W1-c&h>na^h&)^$>Fl?} z?jF4aVckW=E-Y>%dL2qpm4$eY1cT~2)Tgv*vU@wS`wwYPP|Ysf-kX~U?$iCtvSYIq zl+hDX-l>6&0StLQ?DiJ=g9yb42lnUo`uzIK33upm@3tHrQPaf*Faa-z| zB%>Mvepw^^pUa>ZxxCG}ZhX14+1*Ya-YfD#`GWAZ8or%`eXWisq#yGZ?T**OcaB%C zvYXpClGrrZ&A+)e&fBV;e}zycTN?zD-kKzhD`bkQDKtFZMvM{^k8IxU<8Vm)d03#} z0U!@99<>D2)aTP39(z^H796Rw*zWr-!Dnr{+(OAL;xJ{9$25q?TUC@00A*6DXbBae z>bzv%*|#@J(4g>DVSoTX7W9+t0`ld8{7_f(JxTL>wajubXtw~P&>~QOBmV#w)wXPH z(VE@g%O82xZGFR=#O@7?mCRG_2gPM7am`slN4PQdmGo03B#{XzYj*yAAnJH+9Nb^o ztadTmz_!ti5VDg&S{#x=^#+Ec&!}^A-zU5GYj59o3s~p4yRkkSltSw)DI)la#ZQLd z+q;6aWef_CXnLxRiLpByw>KRg*6XdSxHq1DzC?-&3@sH!WBS;iJ#@%E+L8s*OG`7P zYM_!p_vE#XH9epx{e$K5==Yg9;>&2UpL*sE>N{Pr1zK68(1cWFi9PL7Facv)1vTo+ z-}z_F*1Jm=mG7H)vrNMZ9o%d9r%f4$>M)9s$$ZSok6LA%nBA1)*_LWv%GY^jE zn_PPmo&Nxrw+L8S?vT8cG*WaiG~gA&wSO*+d0zAl+QcU1Zt=YFt|m}vtYwl-5(TAx zBp!yHTpz;CmAo;XJxaAFIgXQX=JSxxwlXtU(9&Zmu{AK`R-^b##uH6ZQ8g>;1r)fj zHv`;!@>mhPM6SN2;lSYy#`09AFN#-`F0zY1y6!3St1h~v}e z%pa6p)6mmkHXmN^HQO{>w*`@`u545*7IPm>1nY-r@wvoAtH!oXAdozeXrDl^lEmDa z@vbGe(G={6#DZ7iJUsk>ua-~Bohs#xgOaxcYrb#Xxo>^A!#SedmUv%6q>5e|>5`22 z5{5v+x(OJmI*!K7RZmeIs@@rjgo7rl@&K%{-38-I<9b+@E2i%eL%w zJ25_aH9wzO3O(A~Qa=IGsYL-)4$)C#+CGx_~*biNFeqSo#6}apZkR4zZJ+ zzWY3bU}uk$woA>@>mg;6{7%#nge&3)xRFR5%3*|zX>K&N4vzj)A04)BWfYh$smS(r zdX27|hp{G~a#K}Q(%3xl;c4Nc+R-s^Pl{@Jl~{g22iwtE?l*2y-ZQ4Bfb{fge}bK2 zhdF)hy~y5{;5RTsv{^X*&dq!|0z~=w70kZl?i=&nE{!(w0w_&IJwWy7aS`eL zBFFqc-oM0K*x5OJK~D-gxa0PpA(~V3Jx4}b@jVoum;V42Xg*N%XJU0`8*>h`-8;t@ zPX;%8QsQCDL66AL*Flk`lP86FAWGUzI`Cty~45g6O?z& z>)Os`WZw;xp;rreYV8>euL~2Us7kA;DAlSl>hyk0eCpo4)0oJ0-pQ}3*`0B>a(Rkn zivyXf$7MHK(4)}6`AO)0*wSNY}?sPyY@Q6pC7t%^s~DJX*D-!_NyuG$?WCc9GDDo%!SPTWX|F{r>=qaYGFhlMr2{YHzU~{*Dyu66Bg%eJTf?pf%B&k`EctdIZN){y!&(DZ{E}M zO~hB|=-vdnRLGiv@QaSeS_%;&fI-Q?>Y%$vYvXV^BQD&_Cg9t72+X*=v%?)VQzKcP zn;}M$&eXN^`oLvlb_5T7`y)f{5MNfpLFwovU*V*DvhWmR2`EMH~TGsA@Gly-L&Np1BR~9gp45l>YKw z@pD%=bH^->d%WGEXp(uNGFwsvO6hLc=hh8gx|KjCnCXQ&$FO0mq!nFt*wpP#BS(ey zKI4i=k_cn{w^hf5jI7>^56Q9mdqea$pnz=V3_P?q`MNxAdgS>n?hG8~vbw!UBKq8d zSe%36W}`Ly`Y_n(dYfZY<0^NyFXSg&WEzx1xU+cQ;+uY+simc6N}4HS#!%FFjPfFV zyJ|tA`j|D;-XGoef;PEJ$R3npDxmzv0psPv9YeRN?hiFheFrPw@^tSV9?9<-%1l*$Q>i=BKEuM&wG}Nc#qGmP`;MZL1q(cQ-1Q<* z<*8JSCrt26K;q!@?$>*Z7+tpg%uN;siD{~zCKMy{2cZun`&n&qeQ9Iv7qw?*-6Rg} zeYENp>g;<=urZP*JaUeeIpL0~7v$y>YxZ_`DWBW;X|@k#QevrVHx9tc(nCQ>xKU$f zn=Q7h;$usguXNH2Mipu;{;u}`?+`Q9h+tF@`{)ESzsr`Gx0 zO*S(yvaTiao1VKHkE3jyF#$Bx)TW)~F#@IDFbN#pCn-uS_v!a0fnDN)fH20UI3#~Y zmHT=@_ul0jPjNl2+BqKQa+=yJ{o)A>u+zm6TcnamA}6#n)fZW)P)VW3S0TM{KP^5+ zO*d=qO_kX@`w3t76X7ycyL%@#0~bQIi%C~Uw{dA2tqlb`Q<%?&ElyVCwaF44#5?}+ zTlsBgmNu@E6zKxAAxDtwo&2%8{oZ|-jz4dU zVsy3DeV&_sTiq)iq>pQIcn08pLbX%*8vMG3w*C9>FYR1*o3Au&7M#t?QLSZ~*muQ7 zG-e$)d9xhv{ATCZkhw>IR$)5%?w+S$nQRjCyo zDmbaaWOnqsf?9=+qMDLO8nFoszy=`}$F}aV?^11&%ud_kmS8GWfJFfFU0z^PqtB^p z?*s04w0GZk`(JhTt(GMBGCj&GYiXEA71Rb)CFLcn9l*B=S~(?G5U>O(Bm-$3&+{v* zzA4LF)m=%~*nH;lpsIqSF+q%a96r{-*ZrgqPmbKxc-m84n#d(PjZves#^2{;3^^EX zJjY|O7qGCjR=EctQBhBjVg*S9(EX;pU~jg6cCLK;z$LFg`-#pMHoUbgY_Q2Fl545s z*1@Evm-du3jlC#u6>OHaqKs1@P!K-S3Fvvv{?~ojeT=`ii<)^WbG~6A z3pD0gW0BBQ)fJL52&+(nwFFd-n70SVf1g;{Y4?T)vbQeas-!g;54gZ~K1NqHQX<7s zPP7%!!;h<~{jwPqW`LN_Jd3j?&&~0lsEYaB#(QKueDG)w*^$w%(eE$a68bs0b9UsL z8#{Rd$EM?Lj13^wTf~gCh?x{5qxTG8(2M-J`Bn0cPN(cYj6WrIX3pL;TaOR+n4I?i z0NM28bM4tgfI+%3wX{AwRc>a92@qAq6mrwZ+O>i#L%hSk?~S)z>|5omQlqT{NS(`H z#wmhFkr@Zitf~9Fdjsq;dx6Q``g}p`Ya>Q{XBlWN>q6cw~gt|fw8(zueL8&^@iD_+B+L$;BnYJyMmyP?UouEG*K+| zU#03Y85s$lu4g7m=aHR>WA3+Gjn(z^_t%bE>P97xuloRC4?)&9JSx!`>s6*cUX=d; zCq_#hn2kg>MRkDsfdnxU0N>jzJqdds>OGo6bEGLNQP5`Q&5pXU1pfe&{QU@fH#%r) zA*Y>0W6IGZln%db=D}`ZW*n+P(mHyJqCc7s%uSn%q=y-W&TsbYJRKc8MjCi%J06CEdOE^CLc}szT8mryo;}KY zjOO=X+9uOdpsD`=Yf=6Rbs};ch3(QtW38f4YyBF3o9*M#G)VNNnGB zL$bzFTysiF*i&q7;h8 z%1UsV^Zu9t{z2Atdn|PFzTFCwMuD22KNaiMUcm%j1&{_%FQr28NDcap$+`Z%C*(NYaEToEvSm*4g`A0y`Y-NjQ+^#5eMvQTTz|;BDuc&TKz-oaQ0x6|r1pN}7 z35_lVfL{t)-%D}q89Qp$eNXzomrwSlzvZ?wrEMStOi~w!h}+e`Oe*6T<;O6h5>7e}w+dko&89?d^@Vv-`(8 zBT>=dag}+xsl%Jc6%$q9% zwxBc1AdCueENNfM&(IFFJo!D|8J_6uZ1!fVzFBB0G9Pr*%Oi?!xs41o@W&Bm9vp2T zSW}xFCBCGeaaQGc_qP&A=ZXISQ2e^ior7n#<=vvkYO)lL6#}CLn~O2|mZ|-N%cg&f zI4|$F$S#oBH4v>`2JY>RhlH%Ak={Qg9cJUltz=6oB&{EsnOS&Wspi9vLzh z*z(Tg&o0+Is)hkI%AQ%6S$*hsab@qdNUJK8-& z0e^6hy}wy??O#0Y+gu(t>3LxALl7fWk0DjkwIhHelUx8v$5Vf^dllyI?guPd+S$n< zx49C#1v+Cy40Xud5F7zoRN!Z-8{JKBy z$+C-(Pv_q|xl`_^%(ty>d82ub*_lHKU>+-x>EaqF`H&4heROg?i5<+hvX)`^P+wEtIF&s_{%k~@NCHHS6k<%vKrl&-K!WJ{U(p18?Nf;<0$+*?@_my0;_i5Oz zk`x@d6QTj#JF_vTl?F4CdwyLRe&?`tDEo9Qq)>)USo>PPn^Vz&vPDopAWC<+iziYQtI95mz0rYSyEZRux* zTFs-aq^6x};)0VOLl@s_lu}DX^g<~jqcM~+D_ynT*8p9+uVcA7?IcrS1Z-GQkjShT z%o;T{R%q@ZTBDC&Acgtndg;2_-4}}IrVice%g<=oeO&_%_%ZeXxh29=T#LO#?iLG{BAv#VhEiMo2Tv2$51?T+1BYau4b!bzLPZHl`3dThQ! zFy=@oTwk_NBS;;b2DJ-E+hoy!X14bk4 zsOmEJQ=4YL*sL}kg{FVrw*o1pMKyu}Lng6Gp_ltG#)5^2HR;=aSJve6b-8N#=BdhL zXOgB_=a$U0k;ue0wj~lUBunt_cx`>!Vo6cy4`GP$A*Nix+Z`i8 zM}bHtSt#;PKFM<+S!^}mu_X?V#pZcs>5rBcoya9#HW%}a;kX%+xmMZ zYsQ)B8RB{mb6)pjEC+Y8m=RyqUJMVD5&VhZXuGIm(yS-RY5kgv( zAl8G-oK}lgK0~OjzdC=c@#%=o);k(VJok z?$!%_BF*Dbg?i6hKQF)6B1zNL;7O z-i^gUO9PmYJz-H7u%*8JeKXi*7WoonJw3V+((0+)g#xfD(i=64f;x zgf1yu50^mp=WctsNmaLD98L%!5e5jMT9sy{3F1v_$E3b<`MCFd*=4Sx+&hw)DV7Jv zL?Fi180SD%XZy;SBQvFfmAZdX{yyaSc@7Q6#%mqk?A${tm3pxiQ{~%{!!$mfM#;#V z6mdxeJ58{S@XMf3=QRWT9VzfX&U?Hm4LarWc^5$```M~C?hdUar7Fas@YAG`%F+cT zkcBrlu;Z!=E2?T+NrS+qLr5Qst+OiusZ$pdvBoy?`>u zEOLF9DeV^f7SU?2wkc+BhsJkriKKHt?05q~Kqvs~8vW7xtqx(iyWh4BV4e-$gG5&c zUAn6LF~;gVNY~72*OODnt%y2Dwf-u63F5K$2B;bjs7xRg1p`)=^EUSw*y;uN?ai z-1}JWE{fNzspeQq;GHKDbf4mAyJau9YxcdnK^(}25 zd!BsSVoQ4td*2|pRief&B`7q|D4}-17yt}laOnv_{GWQSW!B{DddseM9>mD!a25C} z{l~QF;oG^WDCC|A!o?*L$rN)+@GHhvCuL+8KTuki+a3Kv6;jDUb4*gaKpCjW0=`~- z8@JyNoo}FccP@6^kX6PVp~y9)~vMS02FzTI;jq^TmwAPkyD zJG~G1MhNq#LcN3UCC+nfS9iO2x%-{1ye%PU#lc-9cOC|+9PrXeWAo@o++WI@rzoL_ z*L+^-N{HThp;e&k>@*UlpXeL;x)0OFylePjyf@&Kk%}@dF;9x{_xv0812H@tc>f2j6&43`1qDeY;}9b zRUKVa6;+V1GD0M^lrbQ&P%5?LR=A87M@6rh(~5pXit!#@MLXBK&~4Xm7S}M9L}R#j zcN0=74Kc#Je7ZAF@b|83G`>nTD@#QcCO!;BG&rBNF{Xx*>M7PXsdoetWLGy)$sBuH zITpp$-gyC_pa=rc{Ld5lj)D*G7Vw?6w$u#OVZhoa<8ehtwS9Y;Zee*&=X2@8t+eyo4TqDg-+w^!H|;} zlDxI28xz(?5-OSJ8cJ7|gs2RCN0Lqbkjt^|@GPI=??mHD@cTYpNPMyGr28bWH!gE* z*2^V3Qd6O;z!l77A1r;HS7&s8D$bVq9l7W?cIlz)ye4@lDe;C)skmwBDCEaQB#TNH z6S%PXQ5%|>$!Q{VS7TzgKHImCaBT|K`jd`o5BNqsabKTV3$gv~J;LSN1>3G0Yrlpt z+8W{~5-y{ufqQ9URvc-q8He#uQ?5Nb{F8nwV}0TN=pq?vuS1J0QPFTW&G6;Td$#@EPtM_qPyF+ zg&^h#3(Cqy346DhN2qAxL!32ww9cXaUl3QyrTYH>uPEZ4CNpC;Zr{b!0T!s9 zQ2a&OdlP=XG{|W9RM4`Lq$G zuBK(7$Waw88LaA9C?1rX!X-Srur5XWH;PG*LpJHoHOW3x!VUp? z1E1}MR0CDNKF5~ayRxJ)n|mnA9EPAZ^f?s%ROlf-=eW-9)80zVMGaW+^yATY?ylDA zZ;d&ayNkBF7k1$=`@)9})|j2864vJSv=#XJyoPdp!He4%+9#-`%e5rTG8LuR8d#%H zmmHOD@@+i1INbLO*;YA_M6s&X29v0;QA!$dKA&$wUS8Ta&TqACgJs&_l52N+hLn)9 z5W!F(k&afQwSS17j4lT^hTPapM&#SMIy}w;KaQiz;j;7-Ec7`nWqc`7M_WrUwzy}7 z!56U~LIDJO5?TE;*6`h1%B^i8hF0<*`Tqd1&`#>!;?CxKOSoD)sFV`7Opj*_iM+A?WeaF z1~+sn9eAN53_fFzTD6ctb8m3)EU1pGQN9-d)T?}(f%$a7vT&IlpRzW-+T1(8E57p^ ze+7@k<#)#7ijtEvx+|!u(i)8JS}Hv>kyh8b>yRbJqxC0}NVgW&J7gBOmu7iUXk~gU zF&~Kk0E6dGK9=9in~vvqb!E4uyfVmHVUDF^1mRY>pz`Sf+&x*RRMIj|BX&^WG4>O@x!bqEHiD*0W^GM^ z0H%9S5Pe9cMh`=NMdrS6_OE}l=Z;ys7Msnwvc^~k2gFjn(VC-yT|s071^|_)9R|(t zd*VE>#{zUGU94#DBFj&Vni|KNL};XutLf`ws*&VYAnIaG&%6HsR{4DY0Lvl+=UP)g zXd^vH1MgAyiH=8=z1!YPkOdl5WB?FA@YxCgIEn$&{x9MG0LB~x2B7G^yN*&D*IBpX z$hi_01&GN@P+3WGKh`$-dv$qxWQcZcFaz^i{{V!Zif_L19{X;}Mc=yH(?^UY!Hi;` z@36Euuk+}Ve6IMJ@z%2wlBr&t!O_hX3evV$Wye>vo|)!y612sJs(N>k9QuPnDySTd zH})Ie_8pwY#BIn8IHgnb!T$g!SxfhQ`@(z8Z@AdN{^Z?D6G~sgy(xAWD9To33;`S| zB9c!U)2(Ye+u<(!z-BU4eS29;x^S&Lk3~U{sD~N2o*&zO4M~EBBm>A+>*H%J%7T5w zJEtz(#Uqpv&S7Py9p37GV%!? z!#jT4J>KtQx5)|C^C%*Rg>(5+&#b!Uzi_r5SN6Y~eap4opp$3Y_M4lPm0e0PiUxI~ zR)CfOX(SMEKs|jUw#F}S_14e8?Fs`=iQAhOZ{n~NvdJVgR1`EgEOa!Hc^*k4ij`6- zV%(d3PrSQP9lT2t8bcVMJOBWHF1{)E>+R#6Ig@tgOR)DF*6n#M!vGoNcb-ObKmjdM z)ZyqlMPWWnbQa{w%Ywl7e_Ca8F}ue2+D-L>YNF8)Jn4+#~96YtvHHm?TRbF2!L04E^b$;AngZhXdZOCx!_EtAr_UK8N&!tBZ+BoUr zSQ1alyAfIqHikEF2g=cn_f?vw-L=&9Gf4$SRznT;Kg6jesdV!z)DZFl7;wYc<%cJ4JA^B8 z@+3<69w9o<%&jUtbN+6zzuYgrf3sfQ?)QAJYioJAUfI$o`UHio5tTzKM>f9=!h@iQ z!Bxtfspwb8e=Yw2l3Ozw9Qa!8rMoIAVUtu_Z*f*(^30KerZ|6yLq#1#lB(PTD&4sM z03T|lRFJ#ycL8LLlwXn0 zvdHcElWt=qcK30FP_5vi|*s@9khF9>%MZP;q_!HhLYK3W?|c?+>qh{01m)WG7m5(y*@@?C*BpZj|mYt;eRQ?it#{<-9%l_SS-`$hkZNJ=KX)Nz| z-)_(Qm$j^{ZefLuU7}j(xkNIq57xbTUCe?ZMwrL{@&Zdp_fyeXX)*o~CEuLEDE1P%)HtENS z7ob)qtNzidKFS`B>=I2IQ`=Ay>1$k)gb+%PRhezYzpt?x85hFRdt3Q+9XLi=HBzhm z`Vg@7O)XVCZe$TmQ0NPJ2dhgPt(#CIllb;;ZziWzHPU(x-NXcLMKy}&tusI2NIhRR z-1+6#{iLZGqU|q_yIrPrzO~D2jMiIhRL3|1{H7qCfwi;lBmb|P;?dMcM$E9 zveYXuU$@t<|I(+w=akdpf1Q`if4*mmEUx$1i5vM8+aHnYU5QN#Dg7uGNXZJ{LND(g z`HBNR$8gA?vKDYYYSsS$2U)r89l}Gia=luL(Ud3sG>$qU%|}s0YG@=f6G+W{W5=#N zOY3I8BF6V$sP_^HSH&!_xfSq>qR5hM*>-|&B{_Vi=E6LtnWrT%7oUhQ1- z#|{f-_lCjAXDVtxZW=sYW>qltb?oQTv1947O*6O9EM)sLwYUXljZb?z$T`%^UdzSZSi3AKnc}#Y#FAZ&JJj zkU{z%VT<;02}G`=);?`WtvZ=N0dYf&{{Y4G2uoIS2BI*E(@8Y1;*?lf7fQTmfE^=F zFJsTJ%Sb0IrkaVZ4-Za<3lGzX-%$t@3Xh&>e$&UQe*SA6$5FI8&uR5$7O(AV`zJq9 zHdsXEWgAy(2x@B*>;0UDVxpQqt(hT^8{gO~nJ#=ga|&Rwr{p;Q06KL$do{C*t?uJ? zm31w&eYO5K6d$oc`zjAq0D0t}_WuB1_?!C!dG(V%T^iqlmC@sVXMA3)nyOkTle)G< zGF3vWB#?@{no+APauBVqN`+H<@JX@ydlqsdq(Vb@V-uT1f}=cNahFpM4X#a8&7X8~tDE`+DLca2UlpuOFQsJ36P~ z?iQL2#amCF?Cr^qsgq>&a9nwNIHGS^GzS`_+w*h`2cXBi=GZ!$;Za$2@-DEcBP@lql0$dUW+)*O=OgX_5%4W|<-`X{V?ANfaBD0-^&V z)Ko|mixwJf&*$3^?{`V8>jOMNukt(q`#SJLO(Y6^zMUoLn|t-;eJ*!ySL9%tl4Yu= zG}6x%Tp;QL?PrCx%wR%8IJ)~dH@klA1hzYkta95(rCC`+D+9zZH55LFk4dJoS&dZb zn0bT4?4>_0jH~?H?ES;md!JxuXNIdYoZFJ%u=}Q>6~<<9bhX35RP#wrthsiYh{+st z9~_A8ShIdHyPCe}Uf%CK$G3A|CqM4{h%Q93S(0AXa=pL`_gnXABzML@rj@OFHQBj| zwkw$1b+l=q)?36+iA^XAA)>aEM(xto&v5{BhUzRn8*bxp)2$>`=|-M;<5m%qkeCwB zAtAwNNE$)lfIY!H{{ROtY`n*NW53wRZ*&_9+zJnck%w!kpIr*}-s5Q9ITFxv z*6|Fs@~JH%WxPhqtF1#L0oql7AY=}W#@)%`GjqihGo*EL$dRozQ+>RF}`l^G@T(60fdCAOXquC32T2Uh@V0rq#DV(p)!C{a*8nls&rJc}r_pWC+)-@v`tFd1vCMsWkKh9b(Py>$-CW z;&&a&W|^slKLUfnRDKXWMo*bN0Mt{q>ZbeJ`sS+*RA9ALOp6^FhOnM^!w4FfvfEQ! zUxW1?&aUpww4MY}g~u9k{{Uy@`#L?fus#@?A*DRUDo5x1K8^Vt^r_pJovRH{ys_l! z77E|FiD^wHK2&9jI6N}O1oKB3M`s5{qv;%T?2`KO>6CE-qt2vsW8o?&rAvABmnBiQ zDk~a@U@_FtEjX2>JW}dbbysQUc6+sgfTqe6U!Q3sH-S7saN4Wolluql>eV1r8XlSw zr)PL7%+Npx4^D|4M}x^RMZ5q;k`Nh1$sqa%x2w2nj4PjBAJ6jt01sOliBd_^{uBPJ z{{X0T4{ppx8ds&Ri~NBdrIW=RMq@38mitKKlgV$W)YczQXVy2DXc-x*N6w$L{{Wk+ zPYH42x=~i70g`d#JjbPaQgk25KIHh9+BhEJ`1!u`J1cl$YNDulY3m+r9_6Hl#;b4d zO|>kEj@%e3*mXrcH9|2|V$m`HGrp4TPOqlw%1(AbO%zV+c#c9l2bPAtR=@XH_)C2PehscjFu#UMc z?&q{y&$ZmZ)>0R_*e4~eZa~AR;*U%TQ}GWmMi@9dE4MeB_IcgIu%|m2a6iLi>&UV2 zeW}Q>=OrzFkh3_G_X7kHU(tOZR1scFCjI-?E@6$f&kIPm2NffUHKEUSek$XKKofVi zuEG1X?6lpCx{bjmx@*7>vlQXy$DuRH{YAZr{{Vbjj5{blX#W6KdLZ!6Tuh8X0^lF0 zx&Hup9@AW1eNyTP*ejkiAME+{u(bPnO;u$n=Xa)ztdS|xC*@`&5#!*CrNzI*`vUHF zQA)<%*+77CBN~YR0G~&fm2=VcwS>_s&m}~MBh`L?Z}>V(+r$@S*#9`^!6o# zXg2W)ZfGR}r-2FvPuhN9eq9GD-1R(S z=gPWdxf)6GF9!F&x}A#FQ&)nd@jvSI>4@*HpcIPXlw*PP$o+?hP-5E~em63v8yY1p zujDjz?IxvvBArDEI%GP9?`G%Ps5x6}Q>*BbwH!b+^T$uV`MWrw+-0RHh9l+v40Y|l zw6@OGg0h=!V6k{OEAlnDinwvKP*TG-S0f`$TVBw@vB&4Bor}2^)JgVjw{rH^xA=zM z&2_QVOLu4N;6E;zzTLMS$)aoP$B?1~6(`{w2kiCh4$y~qQsKN?>m`EAXNE&0MQ+{4 z)Z=mQi)zVR5gXFgODnBxR3#R2r$LY#Tyj631zwaU%w8RPM<9B=D|j>A*kBP^c_VC-kkw+x=_U4t=2AH^^-xH8o;z2NFGg zL+8?Xpl3K3^FEz3OFPsxn!y1)0&Fd$DJI&Xx%w+M48xh>o2tjYJ>9 zNum2H4_dp~uVaZXJPO-5)ERR?e~1i^@O=6~_b*Cye}C-}vAbt#Q|_(39!8%nO9Rza z+pX!PGd0Q^KKz2&m#b z`g364_l{V;{o}IUm~KjyI1H?($(4ZwS0bYaBc*l|6}C1O+`;W!4J8f(ZSAa878e7A zq|_mx#pB>wdOAv2i#*Pe#+KAcEO{p9+6TY4+u(`=BEtk~6%ZPbqks#?^EvZ9F(U3e z&E>`9f#$oJ%R7;R%xXzE1MK~Sraa#L$71Q_o@(4)B9bVinrw!5BS(#=h6t=Bsbg6@ z5k~|?hNpJYE&&4L*&Ww1Pa>FXq97kO$v^EzKf}@Wk1I(jQ!>dT*Wig+v*}O?ugDLu z^jAAG<{!q6wWX}D>`#z=UyYiN?nm%=_nsRmo~fReCza^2n|BvgQ;@5zb&RZW#~tKi z6cR}GM(KZc`lVSNy+}0vcpsNiF3HFo(YQ2l?A)t$p{d?tWIzd}UPb@`>Ph^%4|ccn zD)=Q()m2dZm+Ny+79z7DRaGWj()Kn}&766yjFX=wa_L1~5 z+)s8iBB7~1L(hlHqsy;jJ=fjZ&c|-$3yCh|oly{JtFf+{62NKmEKV`&)lvMs{%xC! zvU7Di8{&rXslaue9Pv|TJ40`+GH!j-D<9m44>fEd@L1Y+8VuwtwL^r^1=tnLob_`w z#>-@tqqZLul%u!$P{OJQub-7V>KEOk?gPslwX)mum%ckSw&%_=t28@wkK$R{fxye* zF*7u z$NpAJfvly>XEv_u4U&{gkj(7-Y&F#s*wGv!IA_JZ0Z{U$vP$2{$l&s(UU1)95+;&4 z2|P*wO+LzhgO5dgxA!de0xjCweYa`9+vy0TaNbH|R+6TrW$`!zqyTBB=h0la5*H=Bk=l){k&)s!Vk?L7x?rh{aOX82QZON+z^p`;ib-`w?=JTkgBnmDB>S5hVE) z6yQhty?VxM ze=(lr-}%n2#dPNLUX{jGGGZ&b%N<==jO+frwtG!NC?KGQA&Rg?XOU`+|~Z(9@=t-*Uxv}Eo=)xyc$! zw>pxpmdH@AcsQ1<%)btbQ=*@Q{$5`)sc{(Wjd#bK+%#gDEslzPsQDUs=3p9U!_sCA zR170wsRhEYCxd@s`1v!LQ6qQRUqv`}6ZYu_qpX75{`mg@cAJgH_RiPdJ65>Xe^9N^ zjg$@oXNOB>v^+>4aOx&ueouUBOy(_T?oOzuf*NWErkbm9Q(_p-?>$>%R$sipPXv*` zib|FMU(^l#>4y2Uc!^t>6l051=StLct8PBUd)nJw`G=Odf>&mcFiUorX#gjPMvH}D zSeg(I$n;qE{{YT@?%VkJaXDFb#_ul*q?w%l5!Wpxr1E$wDlwI`D^;oQc6j`P*SYpv zb7^bCJQS{=N4W#;X&$D}T zV|=j1u1$|@B78}5mV7HLB)F{wUDAdthC26J95NJw29?}5n z_&Oi?EOo}z=pC7~H@{`}JX`WHF5}Eefvm-F;m>Olf8I|Jf0xUt&vE;_`*-do=hWY9QCV+v zU-7GDSmbPD#Zg3&Yw7_bgAP3zZ-#mQ0F2$A-l2#~6Vjo9yA4g*!&d)ef=h0^ZKKdG>4F%1zc{72}IrC#w%O`#h<~s6+2BwEN-6 z{?ct8(d^3CR$G?xEUfPqpvP}Cba?H}NgB$J5HKP&FQl6EG55FgA?_Z*+_gXGQ*!0H z>ty5Oq^6{rpB0Qv(YYr@oK;rkYbs-|e0?nLpwiRAK~&|5Vr;8*=S|A)cKz9K(Aup9 zXahH?B-Vq_4=QyU`%m{M_S=*8NI%yN6DrhPb(DMVFw)X<=*6R)B!U5S`L+oLwe}}9C=er2@o_ps#t}#Tn-7Zx}qM2Ec zf4s2hs@6uaRnP2t zcp9u^a64Kx-1r2WErpsjVh7w*QY}?Dw`E_hR+J8a4(j*>-~lBm}te&V~bk)(^0$g$$!9(|tJuysNYmqDG$G(4k5 zEBSfx>rfx~QSV`4_g~9?rRz*w(N#Wu!L+M47bJRCng0M+&!NA!wr+OYtD=-yrZoQmN`Nj0`e1)&TKytR1X7S& z_Vl5*_MC%dWcq@C!|FY<%#u0+26Op+y-7+MH9mvCh9L*ux#IktDfN%0od%Q8#RM4y z-|_AYhLhRJ8xTNZ57@)3v-ZOIW#x+nRz55a=zc^oar~RAfWoTg@f2IEdc{acD&t0S zsUVF~Lo+!lsVgT4599rBaCPxE7q=TZ#)_3V$gM>_V!V3G4ZltGoI9Y+Xc&C_>-N)! zPnk*usG!%OScv2(ppaOQe@L~73TyxZyQ4{{bFBtK!NM>ecxQlE#*?Ee5(I@TlkrS=@Vr{#PbbV>ytz}gr+ zy%aaH!&Q+r8Oq67Sdz69e-VvO%^#QjVep^huKM{C+1Uu!5rLzMlWJijkxoNrqtS4ghnkjPFA&bO385r zBy!BhLKE+!QKYvrQFt=cAMl#|zs>UNi=2(gdyhMFJ%=sWu9j!4&Tt}$2=N`NJca(--20EOw;&$}{-(EifgraW+JW58P zc9gTR_jKDWZKd&=FxMWZBz=|t01xb^T}|b!vux#EqRU~~Aqlrzrj-@RKZ)9$UCl{9 z~tdRZK=37 z*5<(NExAgW4Z*pxl(=k0IL}W)wKdgkq8N@svRLTpqb+?>Na~0OBz=96?-#av9@l@p zZj<<1b*x57T7|Tt@j6r%KOmr!(2m;mrIjI#YVK$NAG73onYs2(>eySWC$x9I3n#U+ z_=#;@jL%ZZM>@u3(;aOjjtwqL8#mTD;CW${P1TRK_KW?mn0DK3-(|mw>ui_}GDg)} z`Kt~p!-FFL%jP;z_r@988AB|JG8i2C5O`4eQ}*;EY^wS;ijsM0=6bq1g%CY7Q8c=i zaM8^mkTS}GHqs&s$Ujl__KR?{pHs%9Xe08crZ{@nrSV_tNaxfBlTJCH&-gkqm@HP^ z6_u?|Qod;4T)MT=%;?VY0>U|@jXYt10dCw|{5^!On(stm)3?jdKePNe>eEhA;Gh%) z{!~0T^rMw%)r!qUbSlB%3Z8K^VBiF${p zF~s_u*ssv3vG!?izCEnU*{9pb%k2LES00>b%&5o1B}cFMj~;_;Ug6xGQ zN~w~glr2J3(*ygk%^5mUT4WxVQR!j`Hn{e$nR$C)_djEkW8Pp3codi>pw|=A45pRR zPsW@XYl_hH=PmOt^X>NY9`&(Yy4$l49uP=b5~84i!GQQ0l~csfk=2!TWlvo0%nTd) zj-MMY9-kdmm#nK~2=o!rQ%O->6;ejZBB`Mfkjh2D9A4wz0$uV}?aTbpKP>LnByN#P z5GbhDZ@BH0y&HL2bl#b@yxmbgK80*`DaLzlJdYT*oLd8CD zwM(K?V!?}Fn*)6zhZg?;59`mdZNuuK=^96u`oH4(5$*A$XyiFAf7C1fZ?~aKYS(%o z5HX6O!UkChse(Y{Y6cd(X6Q(D0BVovW6!Y7>~8vtj?dZtuaWinbSRGH5n)syNEge2 z^&hj#&+X`NThK)YMgr?jDkWC{%?R`9QynR9TN%ZYA7@T)gjVoWC zC@bsp=``0-s1rj?72)W853PK?N7>d~yf|W}r7Edmfhnx9(*~$!Rz6u3{G}i&r-Zd0hO`n3Q%jD*zWTeH= zVw$fbQzNiEVD-7LF&=p>ETD$3amE9Aq6M^J8aK=MIz6A2ZxpH(Bs{{X8U z1eqBYNiPyCQLB31Nk4B(gXvGzBQYOQYlG~@C1nIL>0QX<;|6(acjikynJzQO8+KCqTs0*3vt*Jxon!hN3AW zU>QjF8c%O6oy_*LDOpj7BhsJY^&UiIaqE|t+kM{GeRsEBr7mHRqj`#tFnqxjVe%uP z0h^!HPxR*ef4tk@wK2&jrU1tdyd+|-i8Cm5A+*R;={z5yzduiI$8$6$vC6>wiT#~u z#=4c-AV@f<=?Rb%&}9~!NQqA*26)eu$1H^2CO`N;e9JtyVTz1L&7O`_KJNYvWM!h*FTwWUXpK2$jKr$dtF zok7>8qz}{-dbIPZ`gr<(hqVxMM(ULMg0m?8Aw&B`Kf%yVwq%h0m}Ec8{a>F`DYIDj zSkm8aq*)h05sMpWQ5f{w`dANQD?V!593*qwv>|Z_j2g8VUABFQh zM4F&Sa4cN$^*TZNSlAn}{10Jm$9*>bBv6poM+E*A`+ZN#fb;20R^{kU6a8Py=hI1M zcJ*s^BpZN8R|3cB^#cC@PAq+d9pstXM{Q1clf?9B6;J@Q3O~XAuRlJTq0G@wnXB7z znvddG+8P|KVm%E~QY{urd0?Yx>)I8ens$~34H7%L4^s;tZ7ZRf(AUHO6ZRjUN*dZk zwvPR@_%bsh(T1v^?yAT{wPP;$)I zDx%Tn05NV-MmD#)W$?u8gy^Q2gr5D#>z}L$nNTBb2M2^$NW{~>s^JEfC_wU)mdsWDsOtHtag#< zsbxqJA}aDLFdoO&e6ezW#y4ho(9r4s07PJTlV5}LsXjxgvy}awn|E7#o%%20GKP(IDy5u&-%aE>T9%*Oe&rj0D<}azQ5(@NyNhgLnOv?4MV(X3}}vIsuMJ=P|{An zva!U-2@)Mn%q{dj$YypVidA!8<@;;8d#;b`I01hCRzgjolPRqS+~`VtQP$a)z2Urk;_O znOZa&i6~1o@BRey>@X&$v~sN30Gf~Ik^6cUMbEeQX>SJm0=#H6mW%{{io5{O-|r*P zQ^@?MVQmiE*>ttrUb>o+wS`Sw)K#-m(^o+6QsQ`Y1FlJAWh{t|sgwpI*nalPcw+rU zQTdNQ=TqsAUZq|}<{Jq&mhfkiXv%@7LxKWmz}h^vCUFpYB=!(VkUJ+mG<}8Eb2agZOb4Dl!Et^2Zu=m2h(}E%M}c zKfX6eZBk+t8cj-tzZY;_Iyp{jdFgTcOKM~C_==h; z+~o9i6Hi@U7OprZ6cp-2WJG^-$U!y+(zmud4a^poJFNczre$g%B7}kdPPr5P?B94k zP2FVVuV*$x4&`-fvR&Ot49e*OvV}zlI?uE zwf$g-fh4-LMy=*6z<__tKzhTihwf$VcP{&1wR@xYjQ3VfOqX;=md9%FMa}HcVWK)e zwDDv@35+4otfod*H0gPtf98i4)nIoJMq0 zQ&Pb^i3J@_WXT3c%5C9laztuegLMR(bDx?gw2@|!B#o5(F%=+F$X5sDPoGoYw0yny zP}up>#`9;}?yPrcW=$q-&1QpBGbk+U4H`OrF(4Xd2GYVs1Xp{m6`Qgkh)m@z^4=h^SK`#El47dwPSA-7WXCW8ipJP7{) zW2iU#!hPbghwiDr?LOb`5bhko%r{VNu*V9SCJiyyCWye+vWS(bP${VSf4%(tM4dRJ&8=6I$hMst5uy~VP%8V|c0z|F6bKcRl zxsC_=tDi(8Nc&%a`#Ai%;*Ybx-SzJex%P2xoXrU3Zd_7EyU1OxUrtYhYzn(6UJlek zL7_DrA^My7#Pzo3tr-5>>pjQTsL_dkk6ppo=T z5PhWE{lu}IjCb}g0sbXA)P0~(kG6;G=vD3)_igjG$!u>uyXTuN?SZG$+##` zx+)?^kDIU5dl<)iXSiD#>~4}+$l|87`5!QTM0JGQk0SH0w_M2%$IpDTeYW1Dgb3~s zsy9DMrgf8757-|4wB1?7Hrxw^jP zy;Zl6hH34i{8cPjrHfSnjGCZ5gp71Y{{WTO!)?>vzaqPvY47Z=>+4;;u{KnAjq^>4 zjyinqcxNgj6qr<~m8PSLj;u%bA8?{%ky6NPN%kM)u3VdR+_xC68R{*s^h z_m5nYy8iJGdT({L*DrGG$VnjmG^?joDx#C*W6#W!(20-!S>G42G*1D;gqzC9m_HOEzkISR-BixMx=N$x%FuX{{R3T1Fru3p8ReXODNnnyIAUK zu-HaxQB3%*na=+h$-3ae3+nTw5ZrygZVdD4^HMHSy zH3nCB!KuJxp`|O;KllFt#xIZ^U5u}qyJ1&uJUT&BT>0IY&7Q}{PYRY2RmDuBEkhs? z9cv{&qrTn=%2fXcaVJ@-NpW-GZqB@0F95ZhZ^+|{hcsjdk&|o`-7;r?K3bt zPq22zS^RRea!F4HR+spNHPjXhRgaQrwGm;j*t3=)GBw#+>d{}>pYVau6P`ex%vwD> zIT4rhB7&pP9R0m*+lBcVuxlwqbunhKPpw&^dI;+yWHynLToZCR`r7`^AlSwnt5Kc8u%zBZAo9J7$1dFRrkv;wi`6swpG>m zQJuciQ~puZA0&UXPONdF$DhJqe)+U?dk>ObG;sZ|;QBguDe>!ma^L%v#;*50-OL!}6~m zmqyRvhs+)8@L%K>JGSug)mH4hxc=$(zR#wc$4R-iRYg)YX{V-;JWrdzRG+=aOx7Yr zG2cY80&0_q;agOfxUE4sH6s=B$iW^*)1ap?a`YR`oUq)+71fDG{udsebUYi>W|bXp zJBr@>H?_8I*z8`u-1HldV{aS|J8^Bi{x?k2*%};_8sRQuX*?Cw#bl0HSn7gQXxIi@ zdk1cD6p+OuX(~L&pU?UA7FowNtIGuNk#MY3itwT0Jwe8N`qb0s+{S;Jz3lHGElawv zvaX;UEI-|hGyxM;^ouRP9D9%VR%0xzLDJP<*+bS@dwi-nYhwWSA_h41W*krD!~8t~ zF}Qfq$03ziAN9ch0B!6q!1XCsqXQi&Hl1u(?Z=0%npt5=TKaj`cw$-Qr=BSmT56Pq z!$&hyR3bix8d}yq+=a|?#^BI`2>V9^)nrAP9UN5{5J$+0ALZ5$=M((S_dm>?>(YH= ziOA$>_CLqov%_F>xa#PH10&v*bP?lwJ9O037ieXvfY2ok6LOH#84Q2tTKzxeO;+p4O3DZyFH`w>b%vaU?d`W9Tys$|FYhaz!a!dKObG4aMyKp0n4Hv#`E^Y6 z)it%!If9m=p@1f8lM~9R!9Td@r9sjz0U!_d9@I-3snsNaA5SyXk#BQzD>7SJvrrnf z2?On>KFW|fUu~=g&RuYwAdsmI}iXrLKKf_PlR}er^!$Gx<0c@ zq+ng64N9GI$5UTHs{=d@4@NfzaywG11-Wq&%9$J{Qy-beGz_LcyTnfgWOk^gK7^h~ zz#~`bz1nU9wY|hI8>t!7B9%BiXbpbejLpvJWYFD}ArZp{QW)y_q6TTBuQ&>(Og@}R)*nF(Oj-5S!h;7A=Dl;!JD@orr((M z8*S>!AomP__K{P8#Qy*g#c+Pibyc4r{u=gw#)^TEo|+x$)^*i?X}7yaZ7j=(XJP~x z?bS$+G}}iuQN^Q_wKS&U8K3lw%uK*rAvQKqikBs(|V~ zBpiB)<(ZXQ#wY+PmQBO`iNk4`%5Ot6DdGI#RWw``P2N|Ji19O+qjX`kV(dU zdN%tvaAP+<5(hpA%`{O8xF-Jqb)yv}*>vefry8^tBy;XQ-8Q*wZVm|yaDUb7=jYOx zFQfz?5}5vf>htMYfyh?ve5PAFOPs5suBfG{qKXeRi4IbRrbwGsK-u9+GKvG12`O`7 zVRA~QR%C`D7wOazX^=;d^R0g>bbSTSh>BInI3}KdFPJ?x_GZqTeeKQJ*gHCg5H{s4 zH2cd2wFRcl3D#+(sl?4aOrdM3lxm)hd6E#bB7miRn{AVbWVc6htXs6x;rXAJq5DDU zOWVV7u5lY{QQeBxyg<%=&$Fuf+&#a&Ha|}Gw$s`b(l#4;QBo#GDNDs&LquyS-zaHF zVARr7(n2DtMX{1FdH$l)$=g3NbAKuGM&O}$O|-WF3d$%7ksStki(GaDPFD$g~;>j4%jXkWR6*6Iti^l(M*4vqhHc{XAjt$%Wv&1%e&}y9xpjN z64am->R;KeMbz-ywBk6fNc6U{wP%(dDV?=_7DK7ZnV*u_RyI2e$p@eZ9Ph4clwnY~=Io zN!R`98C&+K`#Ka~Y@4-$E!@O31Mwg<^&A6!!ISpmrftda$K|%#^GTHH4cn5(#ZM$c zzid=ux3xKvHx9ZZ+xZH*wkaso6vD4^e;(u=o86yj_m2zd`O?xkfv8!7z(>fL6d=d+ zx(hzx975tTGIt6vCrR}T15u3*L8Uyr`oZz{;SYQFhF2q3x-i-PrR(esaiGucJ?Xcy zIDDmDRXNvFiP_t0FBL6zR=y~k*F1`pP!<<=W24z$xL)>hS0h-U+pZwpciGoeP}|6@ z7zcyTG8R-?@I@v@^iiIzY9ze5j@ZcB=rQI2;C%o&$^3!OR%t`DdZ**Q%H0!fOew`| z{fUUJ&2H_-GyUG|+;HQsKsX8o3HfF+ENew!3E}>@se1AQx_x0|c|_r~?%=8O|&G zAb>UI-uufxyYriiaMpsAIsCp)EhI}bFpg}cT(vJwvl2s^WRORHsa3tb^%G~`k!V}*#H&74Ij?G=RG2{-Uo}Qw<8J+>-PAx_YfV>KF5#m}lQf2jaCt()d>end7pm1F2bu zE>r+T#~`ws@$^3KWTQ}=^oQw5jbA0WQ`4l*{K-;duq~der>U-7RCNYeXldG}vTG{M z6i`BiS(-wC*j$To?9*+$TXec(sGv<$893uX=5xcXT3Z<|KACi`vMH$0dK#Y~DgF+D z{fDt>DEmKgc2rf;!!~;c@kxZ9lg9AW*EJEUt!k4i9VA4zjIOP0dG_V)lEplmg2~$@ zJ88g?#=kmn_2}wd)$VqE)EDlDvZ5G+pxT)6fUtJBDVp<);<+T)x1FO?ca0Z$Lv(Wc39Z(>?m?bVgmhM*F( zCxv}{$3hohrb7?5a5!x4bm#M!{A^UUxk*)*?q+&`MN>6B3w^A_V5IOnzSB6?EZd(p$2W;h{fY8^0{iop`yf6%~_GIm4c*nwCG+* zKmeeltU6R?mT-41?OtfYt%GXk%DD{~fw5Z0NrH$6mLQ!ES)Xd!bD;(9o zPNEwv!g#F-rVdE+I*$%K1u528^53ysmCDxbCoMDHuiO8zeBg6YmQ?@ zmb_YUTD)j`iT%IJq7Gu@3(jM^b=tkRovi}!ipA9k92gNA@$#YjE77*ty|y#IVNH{( zq_3vPgj{ZS9VAlHRO%&S5*l*wJZ|?3Bxb;y5&8Ea?Y!9}%AZ?u9tRkeXlg&CN5npS zM_B32p4~pwE~T-8SZ0F0CA@%!Uo%ZqU}=)Ak~kkOgiM~~rKFfs8KR{OWJ6I^G*qG9 zA$by*)I4HC7`~z}Vb9Z_Z(nZyFlemWk)A9#x7p}EetiOL_IVuy(kW)a3IT3BHB!Hj z{{V{Ufc%pA*MsW(r9Q{&N5F4A*7W9lwr&deGdK;kc_f7>ra0P`r>)Kj5Sbx)K&Rk3 z>NfWcbC*5G%XiDOTU&?S83VCkbjGcfsKr@^Xnc)&%dcWS>vvw{?Q-*nHe63-%OX;d zM59F4C26gJa7scCXkfK+4w3-qh~)lX_s)K-OHtXG+uBQ1b z+FC0zRlC12oT|lT=;{qVPO<7~@)+ufRMcbYAeQJNf3;v7Sfe$?kFf^H%=?*+NhZ2! zBuN48HPokypV`Of)O+p^vK)fVZDVcAme!W{7Vf&DK&>2#dt_2GQK%9PLjgmMj^!@$ zhdofaDnJDmQW-K-rb48wbwy@XCd+vdn5jH+zT3GTE6;E^JC>)~N&a18q}vpmNo}g- zPu1HW4XKKh?X5is&*#>+{{Zl!-{yms_}|qSKZ*S*ys5Dr!P~gX%AU-t$GaWHvHIe! zEjY!cuY$5Uuz5Yx>kqCMX((Kn*-1X-k81gSWt!)huV5_zyN9Sics~TwlYa8WGt*opbI37K(evq5_tiO zAE)QslYKms$PC;~c$$jWfcrn$>mWIJ$$uj}PD(8UHw+(I@Tn)ujs-ejVxpvqssUEh zeX~snsg^WZYGbAICz+{Zc1X=a#j8MK5tvwzJ(n`G1}G~fF;jwQX!_!<)IfA#=~X3I22w#Gs;4+0gPw#6Ipdw8dEyMt0~dJZQYRn;DJ4DZ z;I;3hfIg$z2^4@r91rk(>(GuFRs16AXhuyB#pOzQ{$FoPyfq3%D@`pz_$81CnU`9{ zAvf1M$9p5a#qDB1JPtjVTu8)eRPF98^>T>VH4y>C)1h zAzOoZpB+_I6!5v8nbM|B5lDq()M?g5jrAD8f9k(pIQD?5T!ONJpx}@8f5Fk^t=#)v z#CLXbGTfomro0IGR8)D9<}uZy{7dQ$`|^BZ@*PFlxV^91**xt&+sJLTf@&(se6nER)|9u;s=*o*I;^!BZKL!kJgxd%{JS}ZC#lb4s4b_ zijH`y^E2Qj$JS(JT8Lg~M0r}LtRHUByGo%;c*#>f$6?`E+u1=choU+H0OCanK737a z*UfJ2?md?4?q@Y~#^N`qFlZu@6nZS%*UI>*w9Mp)6GpZ!0=KY!*U6i< z$sOE#Uou9CGgXU0Ryg|WvR%a`bVSBdc<5uUOso`e zRKx->iK7g>Fh5^yzbS9fO7{`-0Fpv7&8okZYfAL|e|!&M_r0#mmhb(8dp)8V0gm3$ zZG>iqs$8Loos`vvpwu}8bQ*5&ia#MBhwnEZ%EqLrtB!bOmlqyE#1(P@YKEGz>1oy& z#7K?%cUacL>Fp%D9`L=>@6;#KxIdqlL!Mpx!23HapG~rR0pdd$RsvHP)PwMVf!MLD z5#5$GJbJ2cko{4-^Od;`sbAdrEz^~zrAj(2(N%=UEk!Gd3oP_+j4@TIta3|ge=%Jk zkVU!s1$? z&^SKB!8u)LdhdBqd)}GVGPoAo1arCh(!;@%hDXF4E zctQzbu8G{}gfhfZO-Dzlkbj^8*$l*lP&={!{(WZN{{VXy)dI1Br`&raE^}{g9JblZ$x$VAm799Hs}DRfi9~d( zER<72_b@{QW6>dWyOXDzdtC#|Y)r9A$tN1Aq5fR}w`g`=XRg=0?DqHDa6o}B5hhj? zt57q7p?~}I?bGh`v&x=P?lDcSTkz8l3HWLqOD+%w0WH z-)EPutCBaSl9H}xR)$6%Ck<{n_ayRk)~{iAeH5#rMjgi#0C|(cKD~0g@42z_w%5KU7-==jD=O=S5D>wUK@Onm1Xnodr+l6MZ`+DJ`&HLp7{&rTJ`%d3 zgDKgYj*#bHH(g06hN_QgV@pSk{vQ;F(Oo{c=lVvY^?MI*e&EV3+Q(xFp$!^F8mdPS zgMlB?I6hrZ{>A?QcP7gGrw2KE>Gf^7-9)lQwp+h|AV(EfyOM@a5RNb=mXC{*@PNN& ze>Gp0P{$1UDvq+n0^X%JI0lKKSFI{7n&aqmvmH_iyXI-7JDRt>unC;xsfrFf&h>uTQVsJKT-0 zZF|j=nKqrrcd4bY6GN#6dnA--@elAYT;M-MSNWWLaqEu7`2PS^@|&Pj8C^WG{{Rr) z&9#;ZFuRv-k1Ef*7M`6_8XWH4u=}Ejl1Wa?WkB(h>^sg|J)Pdvcg?IRelMqkukm_S zeEjKJ;P@3A~1#Js8OpsiEp#sdSAW)5^>D4<; znuln7Q|ldrK=klscVF?n(Ycg543#D?Ba^Ah#SGwDRf{bgbY?dC7=^BH?+|&0VAt0Q zq+*Il^Ps8W^F2v^`tK>f`@_#y@wH)&=s>i{{RLQ?_BeX{`YVz!R4i--x#Q?Qt@-ED zJ%>E{ioSgo-qgr{mSd*462Vylc@(g6uPV5XJs)35LQf@sr@0T4U}NI}QW#VZnDhSt z2m{Zk&zz@IEEQ4OXia@{PuWWPb-b-FUu@j$5S*6R!&OT3v}6>d6!W*16$kezObi&Y zCgl5hEnt&hi4v3cb&U_XUt5qNypdL?&ZGJDt7r3Y`B$;KBX}Q-{R>Y*n-8vX?^D?O zuMb-F5pQktL|8?ErJbjpC)>L=O=3bDMOH&m7g$iR+hyCWHmKJ1-~#4AK&UkeeKUf7 z&V~Cuw&OffTwct~?go{>(m2%6aXy}(Gu1#XG&DGfs@*(Q6^S2;HIqzhPXiqeVm_#) zX$9O~#^c+jSGc`+RjV2kQ%veSMSR6LdUP!aAhlUsQQQh=6dW<+YsaK!_}nYCc1}r> zNg~SUm+asn>_sRGG_syQ0FXHZT#I`><^8bk`~9e82F~2-Kk2vu(FXqjxQ(x5xzfa4 zTy~7`UL^kjt2}x+pYWePsHpAl=AY5IDKUwX!*xD0d-mpfNm0Jn9=I*NRgA*cxm748 zT>fsHLK@nn9sA1j%F9q z#`xE7bRfHqaC-yi{0I4UDRRa0?0e0f<1rA13n!Q9$=Xk*E35MBP39$ zeE#0DvuM7O%I*u8&jtsM5BbOVdOPWmrpsfoo97!V%}-jCMGdVJn4(z* zkj?su_m2&2EuGEZFWn$nBLtx*`$Z?no+g=~;ne*U@!i{7?{>~iQW`h|;2?Sq0=Ul; z(zTWSco zjCXMEQJ>lX$Ee4U>C5@0?Aq;{^CNX+*-S0J_O{#IwE6jYTl2nu?cv;fI4MNn138XvpNTpKnyL`a>?J zU0PiG=oj6;nd9a@OPiLiC$8hRH57T6BqflF*$5$;4+ZoVJw zR%8G$#VT1qBR)j^rEhNMWy&Uss)=NZA`&WJC8?v*rph4&W8^Q?i`e^{=GsIoStA9# ze9!05Rt?I1!2>kJ#4r}LRs4o4PnCXs4V`y936QEt-kBtlo;68WJf)@#j?1PprpH~s z!v4`qYU;Jn-5OX04$G}WP<;J5GSt-#3di>89Xx!((GjRK$;pu|=+mg3NaE(g-pizc zTvA1^_(%D_E`%}M&1}J~&kJ-;&- zsp@I=r<)*&W!SGl5tbzzCV=NoJcCw;%Aj!S)jEH2W2+jwX>Mv5b30dbGUD<$T$Lm_ z9Bl7Z9FfaKkfp1NSZe7iA~rEe#(+=b-X~e!%^a5djg0RN>?|2s7^|Zxs4BpM2ss2( zp(nY#xAm4kylphD;cpu@s?e0hY3N0AXlqcWp!8R}Klx64ZOw0-w(r949>>|6cObrL zy5j*?gsQ{hs>>fY@SLt%lOdX;#7Yh0r@W#Q!njK)$nCT5P0yA)OcobAb&clYnEIKO z!?49QtZt~zJl=q}olbg%cBQ_$@Z*{wSl~D%Ll5-2X{*<{LH-fYL6G<*@h59Z6d%Jk z#_X$tRdXg|eAdMYfH7SS9uhhf^2nC-*-U?%o;{S`{pWqok(!sb7QpaW?U0fAxpUON zv-^AX(RjCj#-)FxTU9vs5GXV2tIOA{jeP^Mayz28X#W5KiziJr7T=^BlQ4H4 z;>Z+{V5h>tK1HUIo(aFt)f6y5g6wZ)CLEQ|zWMv3%vPIr)wqYWjzwvuk_dzl$5E)g z5LJlyP#tb)2d_)Fji-_MZq8`#*c;tFsI1z_@)W5HUOC`8uZ%Zg%Tq#s%VBD{>1)H% z$WdUfppXr4nVFrMdN~yRS5qhi3vur-_YIk2l&*u}t1TFD1bNfQACbpVwUyS5G9?Hn zfctn4v!<=9+ccY3d>XuiNhT*Jj2mk&PbF1X+C@oOJtVMKwJj8(tD=s2P_7gbP@8f9 z_vPD}?X)8IhSWaX)MthdLo0ijV+Dz&K;!fIbX+@cA4P!Qo2LT`QmqAELnH)L{&k~< zn;^2(#ZOE34DUS@boB^gc`VHv3xI9_r)iPeC?=`YwEkH9iKcoC^8|MO8(KPp9HFXn zz=QjIsa}W$3V#mC$wv1703*mfIM;n7MN-1xl>pj15p!>HG~cZdb>Pci<<>D-AECN< z9DipqT=2tj{hb>wyJ%&hSZiVsG}1{laZ2vZHMQuDR6xz8wSof$vi$+}Ov^?FHD+&u+E&Rcf4QDsjjKo!=$S*8aP519PAH1X#bv#}A>(z7&Gh-hS4T_v88 z-kVhJj!9N(SCkY&%Bn2fn_8y2fz?`!5s~uh6MeAqM&R(w0C>)@Kp|WPqJlX00YbnM zO-2V*_x!>>K6b84<25$W=v+D8haI@-H)nC;G1FgvZhf_bf})~sNaGlS+-EXi15tERv|FH1&`>#PC%^ zD#tVx5lk965rC361QC1t>2OsPBQ+HSWDs%)BLoqUcoD;(jJF@~z*JZABgpyux-Wa@ zEi6wQ!o4ZUoKI6qhM>JXi>VSLByj05pQ`@=t?a@WLl5jp6!WK_A3lKFo$JQ_AeaWN zO)FoQ40IDsUo7b%iz$wn*_gs=9vNArEo&`QQ8uM4-$p-MeLbmIRY(RG1J;${_7l+@ zo1u|ONzkwyDn}as02Mt?4_Z>4Y$g8y32p4$rp^9g{gc+S%qg*5weh!hty~g5kx`Y{ zo0DyBj6}!)D=nz&h50Hpr_OM41?g#>c!aNMq5IhXbwN`B0d)D7+gEY2QPA=IfK z@u6Q%4hAd3ub_1+;nun=qhqKOAyEvp^*QM1>DIlVKoKC8xnui@A#kdvQyW+haHyqA z05uWDnd&iTm80;)tYR4pUeJAM{-M&ORq_iF!!5Oy7SszZg^sODfA!D0F((!2IfQUu zPcQX)^y6O{tit59Gyc!pRHMdElSDEEYXWWq#UZ!S-q-Dtl)R3fbsx8)Yk{Iz6|hdA zN6(M>Df#q+#=F5iZ9z#MDXCVSL1MvJ&W1lDg|e1ZHu`%I?o3Uf{{T)pQDsAPDrt)T z%5<2k-WWRR>SKp3g{!EhkW_lxV_9 znkHb(!_pU@d;K)45ve%fS3PdtBX=xuBd8~VCWH3%U4K7*Uu1fZZFNr4#9>!2n(gZB zg=0yOo_u{iFAahI8>W1wJt7q~wG|m0g6WG~YOND$BysL2_g9?1s&<=ArLC`taeB-~ zqC%>nQBnp?OOD)d$@1$s{^b6|TYICs^Y1loyP3D!d3qS5P>31jn&e1GM<+~SBabho ziSZ~Y$EtkX-J{rh@~PW#?!2W5iWjMDbHPs2rI?mK>As8n+H( z-#3W~zucr~>x5ELFg*e-0sQJupIt)PITw@pQUx0}!2(Z8nVCehvGr+O78UXfKsW)= zkFqGB{k3F|SC54;pf~=e*KSC$KhXO;*;NZK3e$x@pZh%nIiBWT_6&5_jZgen&Yd3} zx!C*HYWzLQH?_T=>F!v7RzetfYcBvx z1Eg2t9ldCizkX(Xv+hQvZpirs+Z)osmL?i9u#hhNKU+ zg8*YqbJgj5LaFWiuODR5_w{X65=Q-uR3b1phZ2anvDOnmWo_abakB3-O6T@r%4e;48XryrkCXSf!U&$6}r z1NE&ONO51%;UFJkonK<~X(sPoyVH9^a^*MEH8wY6Y@Or0=_evtscX|~;_GwMZRwU2 zY2dAw?8I@{5bE|8KE-y&UG<*RAqexxsIBA+Fj5Z+5nBBE#cpo)^K#}Hr{->724Kw^ zPZE#RP(UA17#|wYRekM#%=sLt(IA!z~E?Qj+T}i>4q4>k9lctX>GM_klEX)7SKcx8d9M}H5v@FQ&II| zPf+S^&~BTRm9>Q6LUgP#)KtSA2Cx7EjC+{V49(OWdQ#Bi73Y>3cu)puWszcyLl8f5 zSqK*`{yxJB@=nho1)Y!b`#Q>*BhlE%ly7$$^*0meo@E`O|V7j(cdQje$l4VEPJE`Eck) z#A50ZXwr`lEEu|pWTwRoel_8wsi;#Nl@L%zO9zIgqM7Dakt4e%uv_(VO*EjH8cFLY z6>UwLdYYUAwp3#xij)2XRa7)_8oGKY3lAiwFp8q&f$XR2?5B_MFc?ZHm0cR~=i1qnj~Tn4+V{ z%^qG`3d(92X(pX#$3j30B!o)DlX5NXKhxdHvKxSjAakTCBx&*_o&@pq^5{e_tfH1N zZe8MJ1yyIOwr+_!|o6;`BuuTSCuI#=%;rwUhzs2Pwaa&+T2^+!7-r<-gyA}pY>y?@7+#W zhn{&0nmJBkAd33j0izOXMh<~^itAOuuB?wfx7I(+Kj6DH3e)#gc_{0nqh+kZ?Je7w z#-!DVjFiJ6L5H4}d82mF{w9zq9Gi3OLnk}(vNnUdhCDk_hzHWN;tmZf*EXU1h5hN~ zf?JREv@s%vA!fX@ibg@5ejCgfD=%{D0-)oeS8e?2_=~!OoL_ou_*n(YW)4ROErY5O z6DdPX#0PKoAM8D>hncx{aai|whuf)t!o2}Ezq*IsD_|-w{i)oTA2@tD#|rU@+smac z@9+MgtHnna6SjK#v+iRx61_g|z?;$Vm+{Y87nNj@)L2=C!S?j~rryzk4g4$)aO=bN z{{SwDd2iYeaqYJWB;7r|-XkbF*jV~8eS0{$28UikS7McTcG+MCmG^(R`@%aO=! z>iTMG8co}{OtMRj!q-(}qNa+vj+D-_)s{mffmLn+;6KWoy*B5&i~Gx|9>N-(CV(?} z15PyK_VtpVdvCngEc;9B_0J&kcOmVTe&O$Nh~v18ncmXgfJr(mg^D|AD-8~nC5}kx z7yREBzqhBzyfr3wsQ1R+>P?Hb7ZukPbQo96?YzA_m9-JpXWJ#W6C;kt)z&72j+UsU zRXh;{WEzPmJ;q($=XZf7+ofH)DCrpssT=xLT7Y;89DpcBdJ=zkIrfW|eVE*?HlJ|z zyWep4YvV5Dk1&Sj76_#+{40YTk|G^NrHZjg?pavV746fs8+UJ4*EZ(E)aGcbV~H|R zQOz_N8c?$YRHmi9G=ii=#fmk*vJReogf_Legum28SROnX+_W)eG7nopmZ#0-8n+LPnws!Z z{fsYDLm+~!0}&!TjTt&fy?~nA_eDy}YTy>AAeyN1#zqgXSiQ|s`?w;8{{U*{dnsgs z5RVH(7Kx-*?r#uRE{cOQMMI#vLT={<>dR6Ux=Qi9Gmz-=ZQuIgx5#UKs2{hK| zps^|dVnV1S)u=0{xw@;c=r(mO{-nT9nc5ZRc&PKZ3uT~&dT%T>$1h1u7|2mePRiPz zNc167b{@mm_7`aa-7H$5ZUu8sT8=pTI?R7X-x25L+p|>ZhjL=$STWS})OA#~GBhlu z-b$JljU$~S@;e>@K1k$;kd^+UNPCS%Yw-%u0DP)AuLI}Q2hP`4JD=ai8*|H_QFCR= zW(BxaskW4sk(tqyYOMmtIAX}np;Tmosj=xsTD~YDXeg5%Q!>`j%P5MTDs@*eS0z&a z0F-zLeGHly>b9PJgsjv^^cd1|JcrJ_Y4YlR=84YVX!6LdD@=f+fmSV1R4ef6#X+bP zt#Q$v>)b9!BqX5Q*xcsmk{H}pCN~#XUSW<|-a!+kH8j#BNf{nDn@hMi`q+Ctw2kBi zVU3)QGz9+ufN=D$P=7dXc6LQB_lw(G1Y$H9B}nQ*flyh1B%108P$}tC(CN80j^x|B zW}Zym*vsQ-nv#}EH_1>@kDFzqh8YfcbIQopAe$1`_;E5#)$?yknzJAM#npKtpS8!0{+Bb=iJ4zv$n3VLYj!(IJ zlhPp@pi@At-S#bN4+>Wq&rr8FPU+%YNWc)arF}SqUq7>lTP^^o4uxffRgwy4-2#KRzcgU{6C)|#i|F*KCXJyk=>u|iU!R+PInOPLFW zyEWx^kZOHK>@IFkwRe}(&mfH`WNM6gV~@)iA3Aj_TU$jE8403{{kh-=_(!KuY92k! zmz6*?INBIwnzo?;`${+v`tYIED@?+B^ou&DAjTG z{{UOu>&TqAcAdRmbw61t)ZThY&X9QEV?9B<@5~FiUYOxw^pS$AS@bwmM1kO+?s;JfZkwx>)Dt|vNzyH?VY~*4| zB1MurdZcFZ4@A0&R*32h4ZjEad&JhbRd0xKK7C8#%0^ijqj?Hbi245jvDShg@TM>2 zo&JTpTm7HDoWe&RRCiW>EPr_7v5-1LvHOa=$Z2gy*@?>jBOsGKW=1%viW9+n~rVuBcEZ;apkkP_%~1hFJU2&ir3~Va0J74&e*@4C1cIj&;7?2alaWS^sol+` zVc-ncVnxU|B$l`qC;hj$FL<{rC~!X7b&&f7(zI<8J_+rq{{UC~UqWT>KiB8|_t)7U zLPOG;eU-Mm!>@N2Lhkq=gB!ZuERG9vvUw`@PVb>s7+udsiqXq7bh9u@xK+P?jpa)l zf$l-}*Pbsq2by;6^3*d#t)^rL`$!m#Yxar;PBe8>&|jQ+X5X6j8_lX#(9ac zjr(wZMD;?u<7DqnmFzv$);)uYlL@>whE{B5PaP;N1dgCdNs-4%Z8g}ey(7g{M^J>v zJv^%FNIv?*v0rU`!?oG&+ik*4VR0JBj=2R`SMnnugOwnup$Du$vcJ39Z?3kj(k~Bj zh4i#%$;Y7LLtv@%A3mS9zTlq`TLpDpTv0~yM(qglO)-zi3n56#h%Pzx5N&Qfsh?^R zDG|q0>%e~BKg+2K!c>i7p7P-%EI|q?&Iim7hyAe!BN*t{?M>i!1rV7`ad>JZie*Ri zKA9~W#u=MYXxv zmMX~QgB%t#Wc|l-ip%bG_BYwvA9D9Q`;EhPSayp88J0B7%%REB6p^MhBoOjssh|R+ zbZLF=cQoI$k;yvS$EunmT_=DexYdG@S`n6^0)P|Ny1Vy$?q18>SsmZK_ceCn+!fJETGfl>)KbCk8kmxSSW%3xha`f{ez$A`%WM(YU%7tVSG)zEY zAQm8=ZO^k7vW{%flR`ZzIz=wwG#S@KEHlJ|_H_;m^Y!T+yEnq-DrCu2NYxV3 zQBuHaTuH@f??K@0s=E<@4ytQO5+7a76cb+<4`(Bu&Be%)k%>GPrI) zxNq_Hn35W!k4LCMMPDP1u4DOYcCKExZ*TpHzbUD=mtO4(9CGbUeoQUqyUSr(jyc<^X_R!lrLZYPA*w6uyiUW{wicsR$`i~n;R5BSYt4CFb zf-2}&_+cP#t+Fd98eifOZjAP9 z!%a<5Mq?zy2i#8UVu-+kdI5dT+^w|jmV2x2i9M~#E5IQAXPsJ_OiGm`8u2s$;E-$9 zI{xI|_dA*F;IMR-Hz_BG3MvuAIX+{LZAlcS2t6Opy#7#I2>$>KtL>kb8%#DrnQ|+I z>slHru~M;+C7_Q#xiVCX8$8O$ll`xaf}33Xj`u%#H-FbnpOWq9$OxbSVecScIT zBaEnrbI`UIaAOwRqu>SxW`en72QKm48$4(ho zki?9E>%ap_o{VpOpyb`oA#Z(UJN(4Vt;8JD9zgIXtB%-T%};vQ#SpF=6DN*$5>q6! z6;yM}4y9H#6%-rhP3fGLPrPd>@z*i{{Um8Pi&Jg_`6CP`U(;V^f<3UP0Q}z z$#R(%((7=wlYpbFst>IlYC*@J=h5oxPv$SvyOOFp4f9W5v2qS0g>n(p{{S7^PT@-> zM3oeY6=e%)`s<0;{C%jl-r=7}n%+p5`s8|KjvuqAhnW8FJlV9XTx^$+?l1veAK6X$ zD-x~wF!^;_UpqgawKrYQxjJ9shTop6enU=R$o6*n+tn2KoK-x&K~9@@ZsiRfMoPY< zAoWxsNYS;0dks)T?{$*b{JFplxe|zs(XsMRB?XjD4B)d|X>gz;tWf>#D#YZ4o#Rr1y(FF>n z1;IbI-8Hh3R4Jj#h6Cn*)%$wL?qBwok~S4BW6RKMG^;q&&7|YwEyLx+>t`(8Ux- zQn4yLt5fTW@E)GM4P)h{{S~Xo}C7ic=|5t z-93werj6A$$7a9x!XNU*lUu=($t6}+hDfI&<7AzMfdE+hVnwjJ4AWZ18$HX}`C^sF z8jqJjP5apY0B?DPyhhn$ww&qiglKGW!qH89>NC-e-Twg12XlPX-#rxvXKm~r-`$;4 zLz}|q@>m(?N*w!cO8k7{rlNwT%Sly5Q$VD&c8vMT*jNvE&-aYj6m9&yyW7OZD9oH{ zX-18(eG2M1$7U?Hi8aSnVv{ zN*Wpp0C*5s&=1Vlp(n39Q*CAIl7kZ^eQe|?nn>tpN_F4@8b=C1Z?EInk7C`eo>LTM ziyk;M{(S=ZyOFnxD@MG%5XT56fV!6afavP%P3c>bPp`{(WT__o})Ij*Iw{{UGr zG|42nZ}RcL>!_Q*DQ+Cof3!=pTIt)T+N|72-KwZzT{^h;Qk79t`Ddd6)_s}0H|6Jf+`3&q4FS(KD`?#BcSg6fmKfez&DOE zh{c5KN9de++>^ z6yf8PprBb=Py&hoto~YG1h)tC2>CIxI(i&EWk*(GGFbi9-P@WdoX~Bayu?*URa+O{ zk>P`IZZ?Qe<6^&+rj*DOtWH7f*XGVWa7p^y26O(SijPYCx_6ncwo86kxSx5lhUacZ zT16n#l1#nOr8AP?6Z|Nw$I8Dz9Dd~ZNzoLT?xNaVMX@oPLu@MG#8@u1+c`W29Vyqq z;%Vxrr>n|I8MvNtK4ab)EZNhJ*+e0J5*q@FQ)^P{kK^ZH64gUZ%f92;lO=YWoM0Bp+ z6#ZM4tXcaTY2hhksH5wA-bP~}+}NmK5(U`%j%fjw$Hk7RJZXkS2`_A0qsR?~;U;i9 zTlj@AE9Pmy`H!C#IZK+8dRXl4BpZ;UH98|Hcr=Ce1>QJJ=8-CrSkizGUm!l-q}gSW zj1k7Vq-g@G3hH7<0p?A3c~_+UW@HMAiad#IeQq|ovkg^CQid66YbcM7s+wqtUQUCX&^_wHLAO%-+rEmK5tD;66i6%`>$T{==!jz~xAxgeDH z8%Hd_o+DU;b}G)sLaL3!h-@!JnQZalHI^O`}*%@x1Wz${^!NfSn$ zC8kD^!!n$PA-@eNPK}P;_>J*5HzrCwotw#LD`WGs(qnrDmnT<9w_qZUm1)ef#}gX{ zb$k9vz5R#nt@aDkBJKByEQ`b>fr$LL{{SwS-hS~PculD+pP4qOEp3}k9$mfSNBNi4 zKuF07MLdA$i~N)Lub#$I=4*BqjmIW32dQnPlY$|do|b^fWd0XDIxQu2Scu$Hx+Id3 zWnyeShcEvCMoA(u)69LJKC-vjUw*c$`S#mxY^|Ek!A0Cmd=+UaPZe0}M6NtQ%&WzP zGt~}PQf|)C?2Ii2FCuv z#w(4+`Ws7NOs?Tn3h^eDr_21Eb!yh*m-!cx_bzGQu5H(9w6lAwiQ7(-5+{jWW~xJg zG?9WxBOQGNzASV;6XO>`b)QS)>yoysY3;fgGr5Yn^w#bT%~cqy&gG{yQ$0%>tc1_w zR%R&@s*k6dC04FtO{6{{guaFOaJ=xto^!IO`Jb7Tf}5N>{RR0xJhcjFz}>Pj)#Bd&9`=EL40TU&+*@BVep$_ z(_b zLmGVjI*EU~<9gzc zw=kJ)6T^xz3~g0aEgUFjsENoihFvHejV)y$Ulrcts*pruV?m`<`EaNnew|_V^UJ>4 zv|6{F-VMguAuEaQW{Rq1uZXJdO%#kZ4O>V$g-9dj;plIdeaTOaS+)k|sHa(xp~-HV zDh;QOrfRrp>F26Pt&1NxNhzR3cL?`H92Pms`@$Edvv@DHe@VA>LtQvgCAK~cp{dm6Z z9`L@`Vb1nDwYwAH!FlxTj~J4aW8t%%CV-7`y*&XZqAA|pyHP&CkF+8`m?mU+_qcI3-;kLlWNXn-tzp&>3*Di@F|=|*iv zssKVNz`cRDt(97gL&Ip1cR_{{TNht;=u# zWa&Zk;s>A4G~xDiUv|%TQFT9bZ2r{9VrlnO{eNFR6D>_Qt=(AsDa7d`x{l zXQ(o3gM7@2PARL_hPWJQT2tgIYs0UoR>aynKdbgO(d#{jgrwV>A7J2d8(V4M@zI2( z#BIzSB|biaikjTY1uQGA-`6C%ovukf@xFVxZmuMrc{R->nwh;xIsX7-tC)^kgAq^9 z=k|Ytum9KFR#^_VHzb1JQ}j3d0sgnVD3z$}LGwLiyl6D2raD0OUtH`yBN?|e+yP1Urw9Sm6jFBRoAN6@2wHW?jKk%A705#o*@JBKI+N*+|X=?g|c;#{x*oxU{ z%(W4=*UQTVePuO8V!Fa1sE|P(jaL`9vF6*&iE^e5**lNp6d$+c_H--T_rn=as1*K^ z`h3S)!)`sH**!J7ay?VsTT3;vH(m<5zZoS4W*-cTQ$tYnl>&;f3qf5$1wx$?#>|HH zxd+*1^Ryl~NLvr`k9g6Vc(k<5$TamjWs}FZ&yIrr+)jr&T0! zK@DAL!({a^0NX$$zmQbZWu2)mNYYd*y4vLFBID`qNahWc?p%|+!mJt6KNdeNEgyII z0pZ8bsJCU`hSkqI5oIc}xrzMs2|Gcrl@2q*h~d?x?Ht=<@-t#;ORYw-__;vxM=Y_m z*?fRq3HlI!+kSoGCi7q}ZKJ(}4-TKGI1mp5Pd{F==V!h)w-0S4d`k8oBEb3my&4>S zV%F0|GXDU(BUU5&IP}b)^zJ}MxY}6EQZgSS{JgrAVU=cyBwhr6KQZ|nbo-0QO^dIk zuZ5jjnrP%EC($WDz_5+L^vS36pTYN4Z7djc=dDIMTYRSY`+)hy*O-i!(1wEt@-wgS z>y6plwz_J1Dn0jsN0LZ32IiVl9w98O?TpGyOHkIx@xGdAn8lOc!~52G4)kms!!ti9 zTs?JUn^_u_kP1}9-{`0^59%lpmcR$%F4o_l!}6+WDt7CZKC?-7ie#h;<r zQ@9ccsfhT~xA(7U_6{SjcAYtSaw$<=k;%-2HGY^QSI*dCIrk)y!^wo-WwqT6mWeHGDWD2k|i(JP`vq!u2ovZEw7DuKQ!lJ8iQx z@~bmRPROG}Mv_D11!z3ohyZaTXKs(#*v_@W;x=Z-rI?77(x$Lzk1dwSRl>34GZocj z6^gRC0Z%6;2yBsB!`~OZ!sea-0Nj3M+&QOyn^okdi5mX^X9OUf5X24@5FED`VqDao zv;NDK_Fh-mlWew(Eu?+U?UN&l67o~xB!EKjpb7;CRyEg~UkS4?wOg-z=kVBUWh_Q1 zGC6Fu1_NwjA)JGtWOB7Ml%`{Gt>u$bu^-mn(fzg*z$OvUQua!8|d4H%LgL`GPTl&R4yh2UDutriTO(vRI zMnyjha6A}vRz6bo7BA(W#ohJRxFm{A>9(j>u==YfQ!H{PByy{% zmAuys{!kerkeikPzcwU(PqvM*S7%~r<7fpn}gbYLuV!&3l_%-P*V%lE!Houdx)a(+uOxchfTFB?=s(JEqmFtR_SW&26<8{& zBrQ!UidKd;XZ;97CPL+}GgJC?Ths^jx3&rbq*p&b^?xrek0QP*{vpCrfP9A!&YpgG z>h?YX#T|c5&ARcZ^Gm#Uo={U5<6|X6SR|&x)5aFs+BB?+aDJfkZ+zSP-0shL?rzz# zBlg&BktrUJJ2c1ksX%^1tgQBC7zZic?rh2udxv7j_+tS${EC`=y(vGKSI;bu$8Nl+ z`03L5pW&Uyx$$uw^SkkNL->zb;Bt_e=Z1!Ot|>bUaz`o9;E6HRZ|1O;NQ#~P-F=ad znl7T}ZfdjD%NEZ|c${MHWj)Nm@wbh>FZb*AS4y}s54qd?H#?-sYcOd|MSPKXEj*4s z3ghw6jXhHq-u`62IJRXpc-VeJ?tRgXhMj5Sq3j%f-rvxrF;)G)Hsi(B*R9kJeA>9Z z@6Wui-F=GomwIP=o=bu$7}T}9%K@+a+i*WBQ>ennm^Xc@b-1#<(I}y=mGa-mCwm(JrGFTSVimB*M$<0`54Tv*J`LCLq>NhCQWj-Hwx0<3WAl>G=>k^$U4 z>>kuL!aP>D;*1GjsU&0Y*G8fbom;7Ym%Yg6o0wXAtLRqVhM%Y0#QD&%PzRCHYI;WR zZ;%~!zZKB$$$*US?yZK>7eZ%G*~iY#g@?Hv2x+ z6cD0?P%3Dng(^)xbf!&CPgady`a>+z7m>2W@hAKr>|-4TRU5TtYndLQimI~^z#ms1 ztH{k`$0v{WKFpfsvGVlj-W|FXT7{;1l?Ld@xs$_C#1%J@hqT6F zf<+HTQEl-ul_^pMasIDPmzdtd-ZCxTP=5F^P`s#cPcqMRnO6u;Kt3u_?W z;Cm^O-pXc?t}+1_CWF);@^Rr_m0WGHk#8c8i3gTDPLuiLrx?3;ebLVp$zPDAdUw=P zD$2#EEf7>`szl6ulCdV`lzo35^fv9elz|$W;~-Lp(u0S~r0usxR+1nmq3<8t{d3)T zYCV_Vxc>kZQ~~3|cC8Rp-TO|VnME|Rv8RybF)%@@Hm8$PGO)Im=h!=TIO!ZCWrF$=%V9pc#n$)XlqX|x9#XD+&>?3J!QGE+3k2;-?XNZmou}sg(WN* zExVl&A2d-`(A4>1710J?yP~KT55NpL_6WJ$uHX_|Tr9B7Qm(mHUn~*B`Xq4~uTSkw z9G43qS~?nlKs-G`!4>l81KfLZ8hV(%7-MmCGFsbI}yvIa=j zijrBWW1X6&sl0wRRh*X5M+}jbxH`E2TKD(O*>=wZal5pcjUr+wc#&LxDp%94ifI9xt zYByk{eJ^qBZDD-kH6^N*_02!a)J42)3i3!+G9&}j9SeBe^F~s7I_jz?W<`RbPnO z7`&ft@61kk$iok~vz3D%DIu$h<>q%uj~Pf_R;HlG(83IX+B#ZV zdT58J-O5E2QK{(-UEy#L-5aKvv{GDT#?Y3NA+y#wZTe({l1(}%rl_Z{(drPzN z+s3A@EwdF&_-t%~nx{JOG;}gm9t}P?NIaDcpz3De3;zH^>{+*O(Ooqy3GfuqwJ~2s zub-Jc5OW73UUK9X@^5k??o$m*0BX2j;*ywOKs^55hW)F&bK6fbj@%dwgqZxz42DQ% z38^X|H}gSJ5N{PtEmT}d8+u4T*2D^IcYCWzqPw)4P0HjNaUNif1RpWOsKbBdy{DKq z+ufsgvlDHytr=@Vt>nshtD(xU$Um6rMc!Lu;Wx@j@VlerkHejZ+B^3NNVIg>%#7xh zR+=!yDWb?yy)IZ#>vnGpo=~LN5v{!Ng;%IQFOYQW*fn91uN zX7(?cs|M8%JjFLH+sMxZcUG%$BnAF5f%PCQfW-=j;#R#i?Og8J>TRPo!suSR>(7t9 zeNYx-8`78usPK}nzhk^tx<+Vlla#j8BS(HB8Owp;T$q)FKp$ZVQWx`vh(~{^FKHZjR-e z$V?m|J*wmt)IWx`?gD_|oad>3mp#7aZP$5i?{Kj2_hV?$wDBnMWQ7<=VQPPA!1!c> z>5!&|oho|gXv>SpF5=w#gD1N8i-7XiRa8j0>Iq+lro!WttPsH;(PU-24s4^3Yj!ZL{pVR2DqC4FW2U5dB@+shp@$~m3*=|4<4$2<`42=qwQ%jox|`GEr6477MCNG={%Nb;HiG;i_0vV3a+i= zsoE9IBZK@hawr|Y%+D9-GVZ~?!FHYzoKJ1)wAMaSA<6Wu4L*KBKlR7H<+&rV=ldCL zFU1x+f*8W|^D@R6f9B%Syj>UKH4U)8lV|fY?2X@1MVRQy&ZgV$@mB60#O{sJxAxZ5 z+hQ3_K1U^4Q4M}aE0RECE+V6*ndMM4gK&L~-*wuptxSc~EMS6ZKnEW_H1(+adN164 z%-dtUE4S`Y-N|wg#~e@f6B#&ZSmD&nTek$D97_)BZ4=fwU8V7};%8cXKY8 zy3uSMOPU&0img+cxQ^%{>uY?eZiZh%Uilh49t>&P*jya zkrX5L^_2S+n%&0m-rFSBu4u_3hePrz;Hmt@I(peZE%*N3t%i$!&r!d2`repU*0^2U zj;CN_`-&{MC~|_GeO@ZC#DD;hTzgTp`lXg>-*~=o_S@L*M*F?3HQ@^JYdm&s?hPIu;IR`A}LOsnJEpPCw5rfTYM5LeE>6%_q~o?RC0-`-K|uG?j_ z>^o20sW#qNg4{>oTYU#*009MIQ!-;MDOm~bH7BHwYLEGYd>zT-C@Q-Hdgrzz5yB}m z)j0~D%j^2MAu5wck(Y2&Pg#Sgb~Z6j;UP%zvA49-j&S8?L~H3@&MSp=?fFA%wC1;Ct_6*D-N6{-7{$9PPNT`wT~EdbMsu$J0Ga;!rKhKl zvwG)m?nNv-nO&h@KHjfr81W&+2|Z6lY2Q0C_c9 z{?4G@bNh$#oy5~g$h_%!V${S}k*&mfy*ya_DO6X?q=%z*v;P2?f5zR>BEy-?ZXJPG z!4OBgFm($=S?m}bo*lAuVL|-1o(27gZTZJyxS)9?g^2uXkJ_~zW1lkp%>C}zQKj29 z>pkAsRMygU*N^yA!Y8lUUZr-wQEguK+qLnso6O^g&RE0 zQI^8eRk4C;9zkN|ZyQ9X>z{e+HBh0A&bfF%dGwtuVyus~0 z^J%wxo9$he9e-QHrj~==U_n76MZn;bDp|X4Z?IpB!)?Cv%*vo7H2@#w-F<8g;GbxSI zR8m%&SPdtwigVj*ZEmVI$L@`{xA!hR=7yoDHwG6Qnxiw*v1)mZHcFbN6D>P2DAu~% z+uXAxamuA7i5(7T${18|!3T$zTw>aH>TnTg``iys^9rR7r0%kiM3~4NQeUZ&ttgUEp4}{F5|OyscUG`Sr^cVO5t?uXn zVI|^=c*1Z^7Nb!bg&A4gkUXk!ug8CPOx>Zmbx^fL8#`}(%@)^!qCX6&O)RZEwV42n zR%*v~D;@4(rwX^Xyl|1cX90M54_}|>)TOCnR@KMM`G2d|qPdsKBZC}bR*Y(5mT%s6 zu#R~g=(1cMKePuNdtYg4)zriW{{RQ5^UwG`-ibF0T%hJjZVW1qt8>5%cRC`JaCeyd}JIb|7kcHxNz+DtLXJ2>1-!{{RBUB+^J-;VmiE zu3Jj#%8wum#_?p6!?!tIepkl6IV;s=oEOSayzu(VevQC#}xg-@BM9-6mq z{iniFX@Y%OI*7R`X8Uwu;*9`fqs+Q)5A_<4&;qk%<=JoUDBp0bHeOUSZ zg8&~v)vi&v)LKy?R(P*>1ZfS$zYItmkEgJd1Qt?95mZjv!C&RL>kB^Z3@lu|MJO2quvuEYipoYvy{&2q2n$DFjUIP5@V?%3aO3Yg|Q3 zoW@Nl`bH|^S3D934p!iS?S;Cvaspf-KW|DTvAu|Ddr1QN)BN2#PXLrH#hHC^x7Nq- zK>83zwE&UQRcdhI)n0!xKjo{`A3i$6A%xsGEJho)@i@8v0MUnN(b3aW=Qg%dDdMbu z;*~;5Su@yr$f>^GYI&K$M=5B+zLp0&X6Y@P71n;7p5ex$jDMM-lw``OS9!09fzNgzX*Y)7_tls=#j@jhL&&Wa%m)dVf41v7*b-E0WSd`RTfxuETBK-cZ3 zR=q=#e9qX~+rpAZNOD+QW>iZPDSCP8DWkl>kdzWdI<#`F{)eBT_lGwYqQ`dK_DR$i zig%8O%mz5lXhjO2Ub8~d=-=%dM)d<94tsdz1Re#HRMcXi)Dh8#>s{gZN@?q7X$*xV z)%!*`YIKBWLZpEmYICOi5$-tVU8CvPNepyRUs{p#ubTSxBl5QK;#S^yNe)3AC>#9E z>FdzytPcj)wZ)CY1N3G7t8ZZ6D)c-cQ>B*D-Id#7x*6b=mNb!A0dNoQE3`9}D(y=t zUsZ@?Z(8y>b}0%TIO|`ZN}rPd02uny=Jwj9+<4ikHb=-T4kP$(BYOyHCZpYP(p|9#dPZ=%AG#;%H zAsdJ)#FG|t_qKa)I4|!DcNW~m8W56!+T)IiK=_uTp}r(J6$FAtzBl%7PW%Vky@9m8 zN$sA{+Fv0mcRNFqz~c6OK3TUe%A}-@U9DNPH$`4Thio0QS61^p)gF0_lCnt}$f^R& zzV7mOIDO%_j#}Kg8+_a5_U;Q>qrA+9E0!n6@u3RR_}Vn84InClq^UI|zSVoF%09$w zyY}7AJ4MoS^!F!N5i_jNC;N}!N(Y8v;>380-Xk`!2A-As!}-W=`nnN@=nkaXy;qB) zr+6zj?(&vR{{X)0%(}#L&rjpV?RpByosWqlr|mcD|t>6`DoS21&K-R$iA;1y9Q4zp4<$tH8a5zztc zp6=~#^{a~~+WnKeckGeI&r1g2%~aK4vCHaxIL*Hlkznyr0(eS#XqNW;`R^?tz zgXpl$8R4~XD15n{no~Q%)mh~lO%lUVgm#_BTO1lT$nAp2pY+$gM>bk$-*=*HZ z)ce;BkEf)LM2e1wbHOcL#gQPaQFTxUzK(s~Io3XE_RDWOmD+uN)c*iUD>DI9MF!o? zc#{zbIFe&0CcRU|&wNU9|C@^bAZWJs>01rXN)%Yj8^Ej-A z;O!p8+r4zOH56hzCN@ZOn~t#7(weDambw~mZ&JEUvElMaUpYS6t-+Tt#oU z?UP&wRyxSif`)^%jYKwdnhq7{w#$+?UBOFTT!<=oFLUSD$WzacOQ!hq@s|OHj*_7_ ze_`&Z-9GOtO_De)6>MfO>LsM3rH(|Zf<_U_Vrw}7kID9cZ(IDAEc)TMvI7c6w+6nX z(@Ekh!-qqwA8qVBIK|sY>_Dlmjb3>R=Z}|7uhv~g%83V9;`E}gjLi88>F;2T$S*CcJmH!p7%oK}ND#|)27 zJqEcgg@=|S4i>UXVOkUdCduQBhSncV;HnHWn5GF08h@dq|eT#@aY+ zZKFuzjRuuORqa(#fD}*<^YxGSd-($1N$wcSDRv~9*C28K00+yb?U7Fw;_>G)lfxbx z6!KHc6s+o*O1Rl(q^6I?o=KuqllOF+`amb$XHjddDm9uB^723IbbGNc?_#%(;8~%e z&K&UoQ^4s^c!OJMAY*}(9ZJQFpZ0Af>>J4Z|YGZ$!mQ{_9dR!s^U!mNZ<{8hLRZdFV>VJ@K?FC!QLps;3altYv6p29lv;b>eu1$vU~c{gX`- zEYHBDIB@mPM<(G~+TFGAW*^``pF*881r)ITsIPwxxmtK3nt0YyT!QUsor(P``hfg% zZ)C1WF2(eU<0hE@00&hibR|5+PwnVQ+8s%-dkPAyRJqpKo2rrtYVk8xIjqL+Iq$_O zaPZ5Gs#cQi;4(Lj3Gp*6i$`|6wJQ2G#BgcFe=k4IpKn`KNp%81f8>8JFYt7&*juM^ z^>*gN^zUwBr>yH8#Z@?|rk;pT=31jsj>hM3wG-&4ia+8I0~JhK7_(|{hU3~@>us{$ z_WRAk*+JbA02MS8QVS`jP6@}AG0`pkgT&2o4OVb!DT@C9pU||K_c7nfSL1BF6fH0c$UwOE1hSS(OP7vXq|l8f zFh-M8P~h<(kA(fT&q}tfz+It&NYqcSQ#r1x0ZIYDDLFW=MQr73F;$rSo;igrPA08t zD9n*Y@<%l+sVzN6j#cp9DS%)!l_Xg4>~CqJc%CUTtSEEjc#LOVP=YLez*KVwxMpA03+4GQ1Sv_=;26?Bbo=2*CwU#D&i-G+=rG>r88xdIc z_|_E)5vT{C08{N0>J;}{M!1%EF4jgDP&HT)#GKHaDL4TC0FYCorSOO3UP1QsRFYJQ zvwKQtv6+e*iIrrj#;TZTaw{F|>sLyP6xu)rRKMyY-X44D?eFeRV;h}}Wh}12k|qG@ z)JHBEgCigbJW7-&6-K!DeX+cYCr5>_I0CEL9RB&lg z)y`1%UfrzQQ0{74pjF~Q{52lc-*m$5Owp1KfXaPm(iB|t?;m8jTX5!1*%Z*Nb6=OJ zK1b83%lff@CHS&b)eCnCY1yOrzD?v;jd8=JUs>*K-bQ)1He&I^GkCE0^(-K#rH!=7 zJZf#OS(s_p$zTuT+Rdi^=TlE1>?gEv0D05x;n7by?Av9u5p3IV{Z$o~L-8{lg+71` z)5{$h0l#q+NkR8>r8`tsLq{Akl}2f#{>qX-ATb0V$FXW}7Suv;N!VwJNelG0~|7t17t*Eo|e{5*viQhtQv7rfD}jfeMng!2bX* zQ}aGw@qG#)u(9MlnYSroNq3nRfd2p!o(P^{2Nxrc6T}XV#?Q%Na2TpQEe$MK${c+- zriox+v4jHhO*=O-Pbs^}BOg-|N%lM2uVA)~Aq$}uX^tQ2K4+|K<|{4FcE7pYu4ifP zW_?FiO?-m-DB!9%3J#Ze?aN7#jVdTA1eB`Iiz+_2<&Y4vG_ZLkkSoOa zAD=;6&6eWL+8d~8IRKDF2p(1W{J8biM(vR$G{#6wioRVQKp4ahkVhy6#W za3~L#+t7n;<>+FXIT|9!NYoFQ^QWQo=mW)e%jc`Bw)SE%MY!>`6TzUJFxSNm&zhR% z{%;+LPs*K3#r=fN^(Eu96Rw+uBz%oMK7N1T>Q%nvIQFVME}CNaR~d zPfGNws-dr`i28teEE}EF%MG=$B2$9HkL~jLo`#9Y{J*ka?!3pig_g}2$rNlmV<))O z95ZUfV}SIodO6)^L5tbAYFtGlwM|l@Ns!6EuBx`E^CYc*SczMR;|EHQ>TXE)X1Plk zk`q(rTg;y`{$aolvDclh@41t5pK!QPkP<|3j4CgX^sO??a!<;Gp%Ra>ad|z(Q?;(_TnJ3Lv(~yfndas;t(EWTAEv|`5Pgc_-{O{YYi{M4RBERXJcp%EK>MCc zzp>fi-*+g)R`a=7QLtpiO996~9)5VH24c&yJ~u!G^YivZ9W<83Uax zUY(+S7GJ^o^X$?+$>M0`j%GeEL{~y7oG>D} z^x@O)=j{#8xT)i(+`Gd&o{F7Ej+-fys;h=E^#nlj7@5DLGP8e=wHN%!cXb#`&B|Fq z@C?O(`vl{huz1X6@~)whty~w?-Vb1n;JYKZ-2y zylj0*Jv4+BnHTjaVBgRY>;t)PGx+*$V*N63!~EX9xvx{+#mJj>;bgZvCg4TNj`$@M zAo_+LN665RS{|WKx-cgdKH>f$OmQ^uy+qZfKqEmC>M^p(rIMgp+871|`$gl&An_2? zAIy{F0OMbm9+fW9xJ7ikbdWOKlT9bn&8x#jGpHIhZK*12KaD$wL1+&P!U>VtX%uidu#2dyIlG0+`RTL?zwxF?4}<{Zc$R^S>86J z%u2t6s}i#$Y>y_bC6_&2k4ob|m=<4XQ}=H}cZGj;ZLPyE-%C@nyL$=Qv~bigYPy;n zuGrjFQ$b6XSuV4~3~1byoBL01uZ~z;7thE8(h12WfWCtuB}utj0$NoG4*WMqdT&`Wc;Q?jQ6igZVbI99vP^m zTyJ0H@fh5VO=`y*w&=sl6zf+sG>GCgh0-wZsHysUSr0SsYeBp1j!NSZl?0#SUp#ts z67xUZqu4iTKh~q%+dFHUmRAN%!YQSVQltx6fl`XjS5a`yMWA8PUillI>0Qg2!e@H7 z3zyp&e1sGK0DJIxEMURI_qPufWH^COO;1TQjO7p8B0}n*mDh4ZyVSc}^2Ija8%HZw zT9KzdL<~^*V;xUk%WXdA?3-rkwDa!iZGX2y>-2NQFOJ$c6lt|HI*I~3LS0EBx@ZAn zuBwiX2bJ%@;C@-Z01FG>{eNUc)5|?hwy-_Ss*BW4h526n74idUyt#~iF9W@+Dt2z+ zT$NXg5kzyi`ieY$SIhTw@M0>cYs`P;j%=#T7!@YUc5Uapm*7zKaaAg_qzmH;+rKNBAz)-!YGv%Jsl#~}UQzU?+Ulv`B0p7FYG z)5&&Be??(!3>J?efr@y9N=y($2Dg+FG^Vy$7%!e*%@@06#%KD+-@3M^O=au4U*PtE+TWn=xrMT%&~^6 zZ`>#FLtNMa?yt`K;zshxaRSDoq?Awx%$|y(`(tvhN%Sbh$y?!2tuw&21d;ROoYbF}K=$z6bhJWmBceqS^1P6_@=WfURdnk0 zIRGk)fV}$}?3+BZ=+dOQzyx3bf5GN`dH`>GvMV?&0s~S($s~WM0p-y*?H%~#8W>rH zeQYmJ0+%iJc<@*fR_9EYB;Wf|8~q0}k0|o$h7RC;G;OHk;(zmbQ^$q+l}`x| z_{)tW`YFTq{{WZl=!i>SJ!a;qtB+AIi6f@~J1C9-$XetPehEDL$aJ=j4XP+wlxh?9 zob`={?pwZNx}9oO6spp+qSrO0IPv~f&qHG8l7|OLF_d`)GL|O#WBrk=s)2S3{sR91 zPhcarHOApGXzkbgbB?67+*aRihC?PoRQ|!xC%ALNB`1;A#a)6*ANL)8x?M@qRFDb( z03WB**!OMQjjHKW#AH(g{aiYY_r2;l``A#{fP<6vgMvKI^5NFfpYWdVf}1M`n8tki z`4Wt3sU@zX_}8-PF|yV&)di@a%l8Imnpkwh6)oDAZ;R_`e6@D6)3J#C*XO$%ApE6e zbNa@gP**e@L{%PVi~OiO&q}#lmUnH@KYmMYN-+H`MwJJPfPHu`qSrMv>vEm7+Pf2S z)(n0xHRY~le;pQ13FszwjDTdPNk@ucuVJJ9Tv+NSlj`c zasL2U_m^53?Ag}IM^#GtwTWP?kdVakN=zh1 z1aL)wx4%BmVEiLx`w#j0s&fwLhNe|zrvg9C(n_dq-m#bN)}{9r(UN5oMJ}^75Rt8G zyGZns52COp7b3(0eWHJ^+FQic;@A_K@gL?tJ_n;1{{VLH$YL@08;}?ygMQ2~^&Ce+ z{S9>nZy!yQpmnLEs))2~RBByTSt6BrDJ*1ZW&Z#VXOPVt@ubl;V_{$RKHh_KLoKY* zTTZl*PJhlmN6W1?{{Z1nUlFMG=0C1}XzffsK8c$yy?@zt)HJC}S(l>7s{a6WPDP-K zIAxy^P?E-yNTyjMpY=A5B)(9QcPMAuBtNW+sVn79H0VLHZx6SYM`PfQH1s$>=lr_T z({ssBSmLHBFB$b{Tgafg>Hsk}B$3Gk@;%9WN=pKmoqN4_b-rWpE>p%2`eQT#yhcCN zJvy>4iP;D@ze@iAcMGVl+IbwM6z)|M!%0{ETaJ=K%EDbncT@h*p7D>~8yR*^c>U<8 zd<(dd$Dt|O;CgTe?LB12vYU)M_qVWZjNh+iERmm33D%YM!9Qr}NgZ8Y$j(g$P6<*N zr&t;w#44jIu#Mh5D9bWFr6ck5JbNXU+CB2cO}h^mt$u%K2h)M*Mzc$^Ub0-F5r(Bc zUZ0;4`+7J#BXY-GLrD!qN0DkHS#h-v+T}1k*&(Q61*TZY41SI|;M{wLH=Vhyu4XG8 zG@3Z_2Z1B{B>v7B8R})&w?(;vIHZ=kg;0}{JrDGN{i8TI=t~Cn2EhGo^|=0^{#5%S z=toW!;nLS=Z#nNJ-ZyG4o*6+5zw>0 zHva%oe5Tnjb;oY)Xmc`Ci3ZxJfuW(@dq%EzS9<-Sy1a6 zG|(`OD=ECxK~04n`gnhyD{Opd|kQ1JU>atE^P# zKWllblcKkiVOPH8sEa$Y3fu=`YVyWDAQS{vj-f?KRjEA^eZRQ{K0hGhMgT_zJW6mF@yll;tI#M>^A$V~&j!6XKIuZL>7kf% z!CUeT&!*gi?Go8ABxj>1-lH*suB?3MdN7|G_BU+yS7cC6)q966*TWXHwVCe8qsiA{ z;o6wFWGM1YE-rZLD<+m$+A4Zcs7)n-(zhTt%?q)OqI(_tZif2aN`Y@8EP_K$6mUSs zOJISXj=6a6SKF*o>~qU)BGHWM#YzwMq!Md|T!MJxtGwQw&z;3%cJ9?&_DgzKZQNR7 z=iR%ej~P$Bb6Oc{5a#j}G>}C_MO9X*Gh^x1e4!W4T>FLjQ;>OYmxcVhUe_IzcM=yd zM$XYMm+6OQCrBkjoGng(2U!N^bll^$n{vBrmW@J*SS?Qq>d>k+H7b0~1#8h>uElO` z+f`FvSy0stH1ah`o@A#*kw&?Kq=Z2e#)WPGx~;hOGoN#{vqgnFV*>yR{{XX3pPxr| zkVOVjMziQRSD_QFIy-c4+08D|p_4vAj8Bnpl$cyXp${xIIlP3FnCM#9x{_pN7f^5P zHMnm&59$Jg(z!o63iNW3NcABOIMe(-eHiQ~#@(riqi5|d+S_{)tH%{oc;DcwQ7l@A zmN;rg=Dqh)WXy~W8S+@_Jg#qHUL3e@N9ua`>xkS2{!Ph5}k@%*}eZJ+Ru z5sfvwm$kQ^O1`map^l3cjZ!GgtokZyBN%6|QC1y6dv4SkAH`-*P5sFv7kbvt}1UKN7!+ekhX%dh8CWH?z zBQ@x8yN=``+T}Azp_h@`TYOm($8y=W*g>V18B#=d;y8D%iua`_R$ zl@AHvH8!SYKQ20W(}z;AtqwmQLyD)8D5+>739QIb8QcB@RH~3!rIE>Iu(|qvJ?`SS z61=1mPnY-s>3-WB78X|aFc2b*KrLEl%+u8IJt=4-#uBs1Tam4gUo8a^Myfql@QRv& zg4PXyMj zM6EtXlCB7fuMOiQQ%c4d!h`h$DYvw*6v>kcF!T&-`DzqDx1l|y&6LrETiK&#&w33X znL(W(PnWiZtU8WFy3m7wkDLlbrR|{ zJj)31YDmy~AMbeGjh`fQrPVh;6)i5DicUBzGqJ#w3JBys+F@V5g^_awl$##uBof=Q zK_m7z5O|tu92*q?aq`YOt!Qf`qK=K{@HITrG_geLlGJ!SaH1Hc4I1dx>IU}!kFUI< zxv^;;LRU)#`#i}b?fD*&$9$&ND|LS3BOX3f095){%b`0Fm%_YtHFVO&c4VYlPuw!F zOGeX2CH#-%mc;RKdymhstEbLj z_|hxlo_47cB~*y3ch>fJsYQyYj5`Bx1F07T8~ZDnwbnfYM-TRX-}tVV+h0W>3nQB2 z`TqbRPhNxxx5Rs!Zbi0tGe;#fVt?WLlOyD)%k7%sR4O7vT@nhUp=zS?7V%2YsfEZU z$>NSnd37d7@bJ_r>B7IWqmwH5W+zIg5XUtBU+3xLXz%za@w~~prx**Nrp8?Y)6E^Q|%oD{leMf-FB^3_`ivZf<dp8*cPAXGPk*0A4!vwOf#b3Lrxc|!6?ZuoAcjYK$M~qh(RVBY^Bc)Gp?Rx$9v}TVJp?6LOW18D6#Auef6m+Y`Nq_f7UX6@I zf2z`cpnE+17dkE%Rk_0f$4TNx%}p43kxqepw|o1KaY5X9$yu|| zDbih|hFUtDenvBn6V;gKdE(Jiips!DH5lBg*h;XZfar28hW8dEg5wix^S!0P1}6cM zLBZ7UV0{SB%c1`OGVL>S1Tbz}aV<0;qr^^qPLab<^B;&)%ycOBX7iesh7G-ksV!5P zM3QQXc@@-9%KA|vmNLM#YYSWx=m+}yXL7uvcoDT(#YrBYFSnwePUYm1>9n!C^7j$Rwy%rKO5F2$8~>iUz21tWK?RmazVo_GxbKZ4^umj_bUh7Ne* zy;uJL%n#-li0hrVQ@8L2H{2NteH57bS+&<>W-+F^s+$A+Hwq*q`5w(6;Q{)INC zBhtPM3;5@fny5rd%xVcIz<-{Zyhmb9u{%R?T5ZjptIKSy(Uq7AN*vBsLTfgLMp+v~ zcwD<3G>ljXXFfaHMJq3R_v}PATTPca@)qBwTMKoL>fHrQkj5x36b!V8E8>cGCveJ| z;vd}K@3`FS&71!Kv;O*TI-7mIdG^c62vmyVX4H1}VrY?;0NF7#5BdhW1@yrn0L4H$zxtL0*o%9^DR)&Cx}bVY*r%BJ z{{Wl$_0wIm+xfqL7vlh%X1gryWo{TPS%*w6t)h5Q zg{F~AxdN2SW9(2ox)7^7hL%0kj@qjOyz|mYT~yH(@x~H4B#BEB7?)VdZ}uL}KdeAb zmac}RR-Rw+eFW{jx}Ekr&GgCyYam4jiKzge$eIt&t~-}{&picFQK_e^5IfVzSsBGb zp=eEzTE)Nxe<0i6u6L5i#yIHo<6qg<_Fh?vE2tXfgWKx?g$*>;hmXt8ppygGjl1X? zSqnpwq$V7lFgkowf>+5J{Y*0HHvERT_CTAX-yvtjqlo_iFW7n??wq2V1<*+7_D`7G z)OsJ7{$huwJ>{L-Sj<&yd#0)erJfemNbZeMDyX`=NX$$v8RSSxg*@NddEE_SkQQd( zpj4kq4=<7Fe#v9GOLG;**t!g6rbC2ZT}J?e=AyOe9{Bn2{{ZBt^8?-0opbTW0@U4e zipfAX{{V6Bm#W8g&ev5lcwYGwUTPsOISjtxSZ-iquf z38CuSdo%tM&5!AAiLdOYZ7vV5jUXeRe*V5GiY`B#sy}8!v0q&gosYsAZUn zs48Zjw#c)Cr&Mc}yZ-QrEp{!Y26?|(b&9^w0)&3xC&mKS!MwRLb>2reZuykLQ^PDqU& zO-zv~DvCf9;0#pNVxAdlDk?-2^zlhOMDxreh6o`>l4+)vMiIvhQK@ETAyq*qk7q_h zLeBUDB>4f7Nj^iUo;!0ik;4oHrgjRdqO8nK08lbXBmf3UG#wYZY>&pTl8|Td80YI= z*pCS!QD;8NpC6H*9Mwo(DH6UYqN`YCvC}*f6fbbCaD9XBt~M?4q>k9Za#et005tQh zMF|weLE?IuCbIX#*$K9d#`Sl;UVEi42DXwllR=>dGFdeYRyhH0Lvd6+WpgCLxse4Reoc;vgacbRy97_%R@tl*%;)c zs7CwT#%mvpidtwBQIV@7Rk6RkiuUf``nkw`ad6>?kjlVT0;-QBNjQzqkT zJZ%(MREK6hMAn)|p*%W8H{5F5lWmsX)7-Nx@?0yl$s5~D5m);-<5!R{b~Sclpr`|g z%_#hi`FW1)J=a^kmv3Qq9StOqQq%2isrIHhVvWm1Rk(8N8jAegR+eezrvCsaa&)1D z1AJoV9(up#ySI?Smb-A_6nqcPM#i>2W|Z_DWS=JNcbuookn;5W!FRYQV$CGYQc2*E ztxkxSf<_4d3X)EGtnSV2Y=-;H)l^9gR9LxcC7PQZM-ozr43aa6XO0phRa=r1kO3u& zF(=ppNg88B!VZKbf(5C`=mf9H$4wPQM2@Cq^)XPWQCQd_eMwtzUe*VXYVGY_XO1;f zp#K0rxBT4_-CoB6OE#*=IQdi15AYMvNxFAqP*XeBG-N7=rHNdb=eZ;_k%FemtIfs0 z=jrTav~0rWRagPZqZ(j+hoDC5yShY7#A)&XNp_$E31Yc5o{{S!L(OleF ziJqG)m#mXjM}lbqH`1D|G1M>4fZ8OwMylyWYwf^Hf z)z&s|&X^x(0njhEs!}O@?Nc;582QbXMR6fgBT;b2SyRaRUz6;0xx~(%7>QcEJgHAV z^>OMj<-3^bWj79`Pkm@X)k*>Dn(*OV^#1_3a+1Xmpw%o|VvWk{GC?8`G?>_pT1t__ zeK|jydoJ585!~F+8j?6rgY*9YWBi>S?|YNO6I)cPX$G8BkCFR5cya2+{{WPq^5)#X z%qQe6H6CJ?qaD!QVLb-m?XAZu%MCU`M9U^CU}EYN0VZE`O&*yRGvtPhNdA^6eUo$l z05>lxZ6+%>Q@-4Su#P$h29>@`S|~pgkT_SM?=S72zb{SY^hftSxf;juzZHpn2jX%o zMF1SI>*)j6{WGvS&u`&hOmJ$1F)cWbx`oyWTGE9U}3x+bE){cBoN-flA}oq^EK1 zOf7cY%5Dle7%}1=^fgU1!Hb#nW~^(va*&Rx?l#mC8U;0d0s}i zE9LPL*5ld6)=ka5oUA*|EBP89+t6!&RkPf88+gy@DKzw<6%_j`*Z6+mLE<-n}5Z-BrOt`* zjU>xP^(gX`jwb}u#LFVJJm@%N`iA^i`x$Rr6^8k2^1%rgU=3PLGDpO5k?4Io1MJ(~ z-p_R$b4ol6=`0Dr@)_-KA~=qYX3gI;d75}t>*Af|K=4iJj#OqQ^vw}E{D`aSPxT{E z_X+O%B>Q}=TXL$VgmE9~tLS}wan#qcZ_wW&ESDje@H`LMPf_XVk&cBJq*+ulkU_uX z5y7>=1cE=`eSL?BrAMDaaYK-MdYw&IEizK3xv` zGq@^o^zh?%1QX=2$vVzurI@Z(nNo2vhC0bLu!Zb>5(Z9rAbk}i{!A)5sa)faNN)G| z7x81{)*82WY)Z;rqwI;J@(j+>r%5px%J|Z0RBsKQ?@dKjQqjsp)pRC_%dVo%18beR z58rNV^FAu$Pp#Ct0h>`d_nQY#-^i40G&h*k0(@Oaa}RjI9-#CsHUpTRUxe1c^Xpx z0OdL7VJzl34uLSoC8L3x(GrbA)XaUZ-0Wq%yOQo@DuB@jJ`gyOG0T=7H9DY?lSujp9D4~%6vzrJZ9`u3!~^~e`H#+>9!CN({TS&dnxEU+ zf5}??y({W_V|&+Qe}w(=;`aPAfi^!CN@0RB=+LB*c-l0AC{UFVfpt=D!`cI565}Rf zFK@P1ud`bb%n+f7IORnC#? z_WBMOuMVp-eq<=BWt9p=NmW%W)3JqLL%i1-$~zGWwaxj|wiov!ZP7@9O-m>PkNUIJ zam*4$7<)!w3leKg)Z(Y+MoIG@XGMl;si^WY(bUMMo<+4Z$`6g6HzX?nNghSLhX+vh zGKp2=4x_kn_0Le91@AkuM>=q#6r&&=*D^ zn}4o9*Y~1?gHy+&yK+1sRj=p#{{YR=vf0Xq4^Jdu#-^ScX$W^9q$mjmnE2y;Z}nRr z>OG=$?x#XKRvsAAv_EM)Kf%X8?DTFvAa0M~KO;KAlCq{~vAd?Wzh~7{Gb=2A-YjiS zK8fE?(Ek7u@MNT9bAuMv-h#t-%z;ZN!ByO{Zwb|;|S_TvgD1^aEQDN%N+$ZDu8`xd_!7!{?0uk zJ0GF*-Cwrj&+cvev~rY-k)Xs93Z;_p!+`L z&w06f+#T_@Eti+?qPh^gtz8nvs)Hq+G?>A_Qb7#FD4{(&yKrXuNl@P}DKebVz+!%$*PhUY>O(c}^MG9mDY?*5VBGw3+eqG8ybX4Es(8Yt&D`lOOa zky(@^akb)+ivS2!U;rP3z~|hbwr*>36`j;fzt7jGOP;;Gg6(bvf=IUWFX{kDr82BN zK;c2d$WZi#>Yk_XT%P{HL(>~Cd~Th~C4CJZ9k#9$BUUQs%hg9mOF=xQIOyeuuC73u zBySXl{5cA@q08IVjGH$4_U#P#(C(wUm?%lApGU<#e7c0WN0fcp_WuBx)0_DVYTY0A zWNj;5Lkyk>f|ZeHXA2yWftQSyR|8csQM2Ds{{Sri0Os)?!L8i8zu|uJ#x^hPmV6an z;n`AW^1`MF=QX%pu^!}X@nngD&k)~O+`~o>!Bl$C615Ct0(ExsaRNoK_2nPa`x|i z+U^}04~rX8jHMh9cok|9`#&zTuVm*wSLVIBZgySH()(+jE8<&E6~t_;IO~Pa5m0MF zGg=TwT({rJO~ahY{Y=ki_jKl~u2z+I z3)q_aKIma4vI_A6LE5$QQcZnFSm(NZ_dTrI`R2oDv9i27B%zjjv1%|IHdxqJU(3-+a-qGWhUEi42^2qiPV3HQ1^OM9XM@n!tcKI-LdRGl-nDp zvbR-K)YP%JAhiFQ41gZOvTw?RU3!7aPAbZ~IQ&VF{^wyM(SOP!*iBFsSWRCWI0x)sbxf z0QgVe^BVaLwQ;IB92^^*WQ(N*yJ@z-*Z&7)fyupqy&R?lkb~dq0>FA#wJiI9SN@j zbQBtfL8hVRH4Z%lO#4;g7`uw#JynB7;cMsuMA#ru2K|RU6|L|5x4)W4^7GqOYw{bc zsQyCqHq6JhM1LdtPcnB|+c+8zwx>Ve?X8f98NO(-^s>unt0l+ES{1vJ0cFGAcRudi zyUYi0=HG622yO1oUTY~pgfkkF@PbTXnuqj~LtZKtx=&`l=RbdI^^;=ud)@n)cQ?c~ z8>%Zc(NKV`z4Rkf%2WcWbrF^50?sN7flt@JC${e9##5gq9#BIXMAaDTh$-rjDg{{Q z$H+t`Wl`$T%l`lc_lJ9pp7XIxZMS{3(U*Y$iqjwJIP0hX0M(7BdkuZd`?{Fi*FzmZ zG07T%)DCzMNb~AN9`(n+U`e{BmZ$h>X_7G%OC>^68dC&uc;k_fIKTR@&#>sZrTCse z!D@a+l%VKWF2gD1VY5M@uJnx5=q;~NHK+MHSY|u70YMu}20F4(3h9!zXsHpLpGgTH zo_4wVjxIl^vjxBLpGCE^JABPQ!C&x>gD~s?ki@~RkYI2Tad4co<9__Gsz7sGBZn11cQPD5Kq(D?!(EO-uHEB$-) zQq-<;X+inZ?dg9s^G7LizReu`-MiUZ?KbEMn(|bMdqpY(5Lna6LE}w5DZiJWO>d9p zweog8r|YWy&rQ`kS}3zEOHKGkkeGQmi!)lv2w7F6fk%~JLMR?Dc z^(O>VgLT($ynnv_#(Tx=9gV&A@DDU@Hj&=h!5SH^Eq4g0j|`Ol&WzGT`ihAlI>(Xf z=XX_QOySY{ ze%cs{I_-($Dk-TfXns`%Yg$x+L&K^;{%cjKYTZiH` zCq;FJGqg~+650}SPZOk+{ni?wop-od6p1%comP3HIA=x zCiBfam9^}R^48n;hW`LvK7HJ|18}$;%YS!r zF85nviwuczF`3>w$5IwKn1*2y)x82IYyuB0tbeM9JU;xwnMks5J8m2hGIXX zg0cLlS-k2GS#!yL!0xSdoWbtTKJMJXzO@;md%KZrt>{<84KJY$p%0v9y=&Xs-y-rm z&oz;$rJhkwS6Nk4_K`2z!z}Z;y>)Brl6v~N$F1b3VoMTiPd?xqi^*=Ldx>Rdk;yE~ zNi0rkNy#Mo^^+=*!4y!<oag2LKdMDD(he4gd~{hHG)w*Hue2k~K+<%ZCNN-V15g zB8+PiNp1@OZTa_D;VuD@sb4QM{$c(ekxzM{nPU|Li+K-UxANiAA0wGmGP|=nc&(r? zW>V}f?Z{R`axcdp)7ho9iC};L8&@ClbVGT$09}g`rFeP%e=ph4QMfmfQJ?cdYQV$N zSa=|{$ha&PS)FamaHrVEZP?mz@#%t}ng0MV9)piT3+>;-H7XilMn4GtbSLfTuX@9tUU&R%vZkwg&`07$Jq-=D}IJoOvz z+v=!hl0wom6Hhb#Z<+kMEtwphW?HH0s-Igo2#awXDSu3HAik6X{lB?R*3t_&Rv1=* zaXw`FpPx~!&BV8pG}5uucn=^w2SM)stXMEq5c;+h5X=<-nhm` zPk_Wy4Ax^QDg?{#9m$d=Nw)@iVyI@WpZw_n>5EcCwn)?rMVENoxufo&)EPA?rcV@3Hpc?G3HB_Ug_g{u@J01x(RM zR7q0udFt9GHYH`6MhZTJdlA`N{VW#n1{6>$`)Yax?pL2*d3SbGF2sO+DM4Sbb^p`b z{+A^|kXDk8t_jxXP+1f_XX;j1*oh)_zafAl-VX_5kg-PuSFECYdElbU69e{tfcf>E z=YlJFCx$zzVXjnPNcy*_hopaBr@fX@#fMc0?eL*Lk?WLl$1({bb#x@@bvIVG7giiH z{{V>N-+>G&4m#5-A)^W&fV$Qz-IQVyL1^igPyyr|T*guL{HPrJAd;h)VhhHCzwai! z3nByhsV1*ePxrA-gl@#z7@ok`8{1-MmtGTkZB4Ram;SACXxE$qi9t zBoM9v{Cg2cJhrk&a{~c9Y#B-6QITJlL1+S*qYk8@BDCXAKE6laKmHT;KfrI1`@f?% z%FmR-!94k%wBLf8#f|J8gH=^3Vl&i?h3VtSz^G}mG|I)PE24BhoebG4%G}3e&09n} zrJDft(<)an$UY@MFEu`3gV7H6w%zQP&1o_p1%{~H{v`hZ2BobSeTNmNMWd;=^>0{q zUdZeU9~)1#cOE+^(aa=hrlgK_j=C9EA|0ciib)WG&70cJVAZtfr28~-S*WRu>h6{VHw1cp^R{T_u)Lnq~RBeq8gbLmO;l?oQdebaUOg+FE}md zU9z%i_Y%oII!7r5Xk!{PfEQG!)X`ML!|Q8{Sn+f0eYk8^`}L!EXcpuOmEvjg^;7)# zj)1ls+`B!(31lV$dt6|CevCij@zK86-PuK2Vx`Nv(-|90CP)BjDnnUTDxjr>JdDTn ziz(y!+uSj}@-@w_xvW8O2XcNT`K@@5mma2FkDef$Bp2i@ei=NEplWbGK8!UUW}2@^ z)`=rns16+&Pw8cJxX}LqgY^FZdiNg53&wkt(0sqi>(qx0#8UyK#;!bTk5GLNPjSl8 zuxQw;0dPV3{XZbthxmJF5;%0D$n^J&&emfpVydI4sK?dQop99AIf=FNexLh2Qe`l^ogB4Y zK5~`uGf_`ZZzMH~TLcqE>K8z3JF5%w0Y2s1ZH~`&w->v7u}`;=hKYoMho~w@{ICxW zuO-}N)m(usJ|q5L^YwpWQOHaaHNEbVYVN``W( zL!8sPY`l}QUGMzEa3I>@9C4}Kj@aW~FC*|(A8De3K}=TjUtA;>(dwD#03YH10E+X# zsmE6lL-FHb^#@LN1`;T-o0oBaaJNoRb?<7}WAjx{j>FYdXvI`b6q4bvlvBhFIwhU# zuOTef9Q@q<+2+r1ebnURZE-E8(z~U&hSoMZRSb$NC=?RP>Q1t8ohky1%(3$J->`Cy z;XUkHuA1D2W)y8qxK;E3`3@X%MS7-qI|<$^WL~Dim<6h)lT66X8kRD|(UoUTN-}}< z=j-pG7h5`buk^?;=LBPqk^cY>P$TX#ECW%;>>~r`{?9?idvh5lnx?o)kupgw6pET6 zG~^8;M3id#r_-&-^p+?3`?~FnhynpnXh)rXUoTFO!@dX_MY)lNtk=koLMdAD$mqOo z+Sit`ClWg(`us&r-Xv~Elfb45CUaRF6;( zugf{}9$Y#Dw>)pG%zYo_5^6-U{YU^P1N&?AKbzm{>_=p9Q2Gv|9$;3XnN0_XYf64p z`+a=tUW7is&Qj%Zpw}U*ub>8wq&pbnMu&)}B^zAcNOYDrQGa)yCRd=sAKUZ$Gxqea zmN!d#%P?lFmysPV4iptQILm5U9w1lG9U4Bp%1bp@*-FttOthvZf}O1$-O^+#j93Ob ztWQ4C%MeglRGRT8p}nleMxhF+r+^gm$IPF$y&wMoi@hVedqc7I-cuPpRtIbB{Qe6s zU%FwZ`-vK_5t63NrV|Ymu8~ybGL&Iri-du9HLS<~oOMcj)$A$|-L)_L##d zW=fS99{?bb0-7Ej!;e(&@~`C|PkejaJBO{di)DLvxbRgUVYnl&O1vh?*?C5S8NS;; zTv02tSyh5`kWtYS7*<_#i`(8s`&svK-TCU;&zQM}?Ada(qf#&-=eSTvJ`z_gr#0G*-2KM(AdyN%0`(_xey65w3 zQ_qh`cDuIl-Gfwy{OduVm#;<>;y1)El7BI~YNM!nvY!{b^Of0rmVT!>Jp-+19GbZvC0H>7c;oHlA{p0Q3=c_@tt2WIJ~ySOc{qA}s+7A_W;$ z3O7$};M_O#zJ}w&+U6ytQSqbktYp_xxy?Tge7c#vzy9z(VlX5~%uY<HHWF2Ph`R;1}sfG7tJqvvJ7(&OuMJCtFg#$ssdG8qh>avBz;$I#J4)fF{$ zHC55FK~GH#WtoWqK=--ih({#XWei9v%-|3J^E!dy)B95I7Z-NBX2#b|dvPkq98ffY zq>;{*MMNO8F*E=Ql6nO;=V1J8`9Ff)J1+@a*8Rn{aj`{1x%R$835?F+9*VjpF*LYr z&N-=TF|`WeM5!A@Ta8z@vb!z+0BqdW;daZ^m%`!zpwF1#Y2{H)hy3I1zq%ow4lo@9srxkpk>)W^vV_U|9DK#M73MBY<~xYrC1tjrSQ%&yLj};v;Cx8KRz?^Q zNF3d<+;K-7Q+5XH)1_H&mX}tKpaqxr1;F4FarO2qp4ZY8~`@m8GAFMS~fT;_sK0um|Js6$q(fCz8Id7y$N_LdhxxAOmw84DblbUZ&|XR^pQ4I^ zcor-dJSYGl`P2#%IQs$0-2VXYb@t`BbFaGlqjKe&0dZ`%^F8#g-O+@LTMK9jH8aT{ zcv6uo5?wx^AIk@#`lq4(B6Xf4s{TD~zmCb8!&6k}@fdi;UVnL2Q7NLM-y5@Y)d@5E zlOwrlBNa<6bn{4&$`wkbln!}waJt-fYdhPE6}6Su;97;!I4~8!ZXkYSl55vGzVaJ& zrp4~(HFD0`&k}F@HH7*ineZbl14#yv+pZQSIUE38l$NQf>cTyoid0nNs4uE7`5XMs zJEx+4QtnNOKV0IEU2J^3II8WjkXNVAZq2_?kkwP}>|SMssVBm9q#v9d!RQx;#uU%U9TkbLKhr0g4Y@F8@Ioy9-_giBs zT}DGeX>g>gT1yD{)+YgG;V2}LjWxJFs_ku=-W_qbdpoZ3Pm$X@qJih4mRMQ}>KeGO z4R$LbO#IX2@s&!^O1!S6x|UK2AIZ2{ZyQyn>$X0-c`HIka++mG@?|(aM~L$4oE-h_ z{{S-kShzEiN}MVM*!UVUEebl6bX`DuRd7#1O^xw0G7QR!-DO7N4Jy2(CePn}FNUMrm>eE$gtKGn_kJfSPg&DX8Hs6VV&mCxlZ;h7Ct~ABf0{6S^Zs7F&6en|kh^h$XQR4Dz zw0lEr#VC%ObM2g+EoD6wQW%*9O*siwMJe%2iq^Wgy@d9|cR_u&%Xqf6p+M+#9y(5> zW>fMck1$BjN{8S3?-{X21+L{~%eS5|V-3l+njtE$9cvu=5>*+IF-#Szki?JYzF>Ez z<%uZQJwt-j3|g?5)AylCxJ0P0lD1eI^K<}@XPalSUfpd@XFGJaCygbOx9uu{0sPNF zZTs)x_lo9tlWw)$w*9G?(^Z|NX3qc`;il4j>Zwud(sym(w+8age;M90kQf@@>g9y6YNve(5VYZ2*1DTgu;4HP{{TyH548c! zD!=N_Se)B=j#^B$X839_al@pBf3>>*0A}SWahub8ZB46?sYqtW((WA19wDk$s!1V% z;A**{Qk7Dp0B>zV-rH;FEu>!>`zv(AS|Fn>~xFh6(BGsj8x>h)qv5B=FV2Q5jIeNGGRxA(0p!2yG|u zeTpI8;qZruD=j>!L-PlQe`lvaiS~Q=C6+0zUN=Ug2U3iu(UpK;eMKrgI^$JQUi8LF zbd3o~90KRohzS;S)KQ#&u;c6Ow&QTRx=jUwsi~mz{QAAL7HK$HnTV(yI1}sIT4hpauj(VQnl18eQj&|Bbs>Q{X*1>PsDHm`w#ek zZ$nERuHxi1zlU3)EktT6(vMoG^b{jC94lINUfsp>v*XWE)mG7D_mn%+a75C_76)d@ z7U6MFk?WPRSvX{q9ZKGj=6!C^sO5g1;|=rNZduu$NZ#;WT`Bk?I`jP}_yu?zl07=f zeo*!+pE;rnS=VhFcHY#imjJ|RTxg1(Ap?rkC^ZJXRj+)1HBH@Jh@9-)mJ4CwWvphM zW2#)P>B&-;5Q9RInI?{^HBv~8APIj=gWNm5`?J2^iDIzPXKH;rq&{B}z(46mJdasD z%71rmN!VTst=(U8zd!)-J7E;bq+{Y9y315?9aKMP{Jh-zvbL(P9X3K~qCy1oH4vk?_?e-l^N%nz6I=`UTmqo$0;h6p2p6$6$r#Ti9DOOt0TM;7{@X7>A2 zO4^R5W;{5P>CqhfxQ%omRYj!^Y4gV(f!z0DtScy>{j)B$mZES8l~17ktUv=|K7@`B z)7al`<&z;pah)`xk1sys{vYSiKJ$H8#D*+t;!mI0Kfrn|TidYWNhGJEV^La58HTXR zu1Rfmb4O-(=ls|tfot2`sjza(vaGX>FnMG7C_D$x_H`cbe88&B6bDq*&T(H>BhTf~ z5nESNT~PHkaO_vfny)){k;I?nn~QtD^<^3Lmr|( z7UYxu+SlNZ@b|ZB4yvG&&_BQHBA+u&M6BLA2mqAZ)MlR2vX8*hnn$s>Ex_^E%Q+p= zHa@|R^Ys&R-P}{|_I5@807?X_Q;w#g{z9EZ+8bwcZ@tTa*xN4+lH7Z%cjo9YJ8N#@ zA!^K~TQifXN<4iPBnr2ZdWqx!lVGdKAOd}v+{tfi4A+-(DnSw!cWfw7DoH+rq6>Lt zlSQSzqa@N%6-`>Tpz_bFA0R8`*U%H-$MWjhUjRNHj4eey26Ml=5%$L7?(OMK0!dQ^ zYs{}lu<-Sz1E$p3@>K}d#R8G+v zMk`>_Mxj~Q{tp+wvVES9V*;q{QA6`1%ly3;b2Ve#uU+`NYF|Fnn*RWh4u>;K849M- z9$i&i#3XQ}m(}zNjbZ(7{=c)Pj9_u|^r`4DC2Wy_^UVkQJzhrBWU$fWe(~Tr)Bbk^yx>z7h2o(`zTM(l6 zVi*1Oy}u9zk*i$)0GFilu?wYfjQr1E|J2()zpgg*L7(kbryBE3mA8&4$t5C&7|Su?BZ?^0 zvme5$A}#*_zz=J1GEEeJgQCvnIH_WPGEe#X0`>~N<=>l+cNITnOw&V1zo%fRAD##D75w@Z?=-O4>~_)ps{mW<89%j+IvDd)$4`r_ zl0#)MynNf1kxGT0)O2`$ z!P_FgaP;S4%NP>vUEB7$O&&^QSC(z7xYi`3$TlZ@!l7E!)+d zo42a=zWUi2imVRf!d9)MrmUrJOt4BnZmxp121)6vBP|s0NRlBc!28WzvvRTCEG;)p zvfxW&ItNA`VE+JsgMto01RRdB-*K?L+V1Du_ZU1o$j+BvFOdh$NXnm2+1AiM%SXBs zvVI?I=#r{R&FRv4n$ED?kx4s!)SG8IXR6xO&rvX_l1h4NIW!bl%D0TI#+&=X{{VV< zdG>B~ySqr~WqzV$K0(GLA8w&v_T6+Z*dA#d!|m?dYb@ID_Tp{isjEoB5t3tfdP)$yiF-uLPd34sT+b+j@4NThNJs#b5R8?XA_;=X3~{{Y5mCW%x? z-e6T+{{Tz)e%?QCQfDsn&x8^)A=17?_bC34@eh_qM;B`LUNbdKv>nvrXkQ$RBad33&qfcg zyVoVRWwmu~St5+ZEK^ff5>jYn4;wu#K$f0Gl#McJC|OD8+O(fEZnR^qD^878`&#-@#l2IE<>w#mf-4H zssO5^!dBEa_S@_o*TECg*2z!0v8JLztVaO%KnTCx)>&K9fD0Uh<&V7&IBmixd7Esu z-0jB~AE7lq)dn^+^*~RV=`@xqz^ElpsQ&;q2lxQ!rf-kso$`Vl%{*HwJ%he6&hW=J z;Gx~o;;5j4W{Fa>BZ|$_(Pb!-1bfI9IVI8>z@Mz!WA~HxuJXjqe7Dwj3J>WRJVU^m zE5=Hi@D-;KT69ryVSen=AdTi?Dp|Dri6(}$^QKRiR{_#r9X1EV&Ze%zZM?lE=-+u< zT1nWO^=a5vzl!3V2YE#Mh1ouT&7(S~OXNZk|)= zjgf9pk5X#CpbG=_BaeM7n{Sdj)lE9anIwo*aBh*ClOy*n8d8OxvJWFY8A9_BqT1nz zff-V~+nznLkkX;BgYy1;2X{F&GHJ^U{{XAYqTiFL$ZIgyR6|E1&od#&)cA@kHHk>$ z4I(|wis=6UjjKqa;}Vt>&XHgCKc7Ik@8?d*WK|%V7CbAA5At-7uS!X&^#1@Eqn(}I zgmA@OFNyA?0L=<07Z(Qnds!B>Z}%C1pz{L1&!QX0hIp9;%9@jbsDOCm(uX5GK-oDc zFx#ejIOR&pOrjcbpvwsJrRSz*Swgc7N>tj~t}X3Us?tIU8dw_n9)mjt+*@}40C8^{ ztdUQE2BF+4%1AtX>q=K2KCHjt&qQuNkllwpTvb(AuDIIM!(G0&Bv65^XN-(~*27CD z?Ee5C%9x#t{)$Rq(vVw1v?=dTyIX&?JhYOeX>rYWnwHK6ILF0tFyr9FNEE0tJrEEz z5tAO-@^$w-Z**A_ZDm5~1d8c2QIkQQvE!Qg?&kjhaEd)aAdSrtK;j2=LlDfsSGtC# zqlZEkLv*Gn!-mUOPmh^u(v~VH#i|Sxw|1rl$diUm0o#W{598SeolK{RAmiuf{(g<@ z_9nj)ZdMknG-fiz&%>#)s~Gduq;MdQKDFlla9bWNrSfZTc2yNAq{DZgTjFzdIzpsN zymnOI-F(oMkmzcO@lB7Fo9lMJ(BI!g{_6a~cVBNWc1d4U`(5KG6{!(UJVpG2i2&** zof~eRTPY5s8?u8+14F1&*R{vb6g^axe&bppC)^g2SgB!n$z_rvuP8?XPGVw=IVY2T z54@O2{7SO6WW?&nk%~lp-WvG!`o(GenXOSB4L!q=8qz56S9&5on1 zsfMOZP6HDI)6-;kMsU)r%?97WQ>)8607=pma!0sl+)FvG`K}GV)ipZ78so^ZEJ;5g zK|Y;s!<#nUhm!YBY~OA?J-!1glfbrx?L;1I>@=YBC$FXV!as!lOYmo;@O??vxXNm* z!@(72VRj_6u|>JN2XwjyugvAESxrcxhGJ5Nj5mgoomCWEGZ8M=wcG7h%V!GJvRU(1 zK4jO(c@HkRmF{P`o9DT_#Xk4CN>a&9E$!=A;ZGm{#-XUE9URa01UJ+1YmcG) zi~By;K}8HDIQdj(^RFCr8UA?dDzGB|0PGL=5%~WAU)Z|N{yFWVnV4$ApY+^6pO;D5 z2x2MMivjgu2h!w$a(@E<08{SMUPh#Tx`F<$=U%+1PX#BWM`r9=4$$kJ_tzOoJTx2U zX=k>zMBrVizl`IjqKc_TrMptkD#$tdufJYfCgov!w@%_gMs;e-=R*(px$Wh3;gB>axQxWeTxoXFK+4rZES};UrhHBwRH3#kC zs1es{KK5SYdl~L;vC?f99OGtpTl*+CJ*`yuml4TOW2z-t3svprQ$jn56k7Fu6VDb) zCo|I2>WYf3X!Sa)38Re`N6>vs{&rJ!0GoYJ)7br)Wtob&qMCls_Il);Fv(?O63+!B zmNN7Qfh2)n$PAPDaq6c30G`)F^^be}FT?G9-?O&%XE6KE9YMCc7N-!ETf3{JsGyr5 z*-fLD5oyFnlAeWNtfrb&g0>eZLrJF0Z~NWW$+kr;nyc!R1`IK#hLoqmc+k{;kmP^d zpOdUP``wOV*g1!AyMt`~*EFjXGAekJ2UyjJa7(md^{G^9Q@jKu^{2=3z5Yd=jq=;( zm0rc}jD2oD<3CAN<2QF{@4RegDjofesb{R)I}d2q&lifKzjm}9Jex#I7Q@iOm~-e6?+ELq)vs3 z_>P1Uo)`?X#%cP1Dw2(;eI}ymKAcXn!Su3qe#Ty;+c->q-P?V0{oThl)WKk}RLe(= zpv2!3qUY{RgvHV~QA}f&>c+C{^pbR+2|z&g^{4F(mZk?aq;OQ$9=lGU?BhwHr$-zbLCQyPId%Qkp%{fHd^^Y=+)S zwW_b$Id+;UBd@|&9a;l|^wK$a$kf4uT*JznPcoZXFI1(}BvM7DqLrzQtAx~H zwO0UV`IDTQo}sPxnR$box9jd@=8fKc!+yGbQ%^e=c^ZHM#Q6XK08juZ2T1&-aET>t zD5|qdHAbLX?HsZ&iDhGUR0owj53jJ4vMPo?UuQynzSG2H6(p4be6TJWxp`&XJ_1i(u4}Aqa=zd zvaT{m3J^n~WNL$tn_lATeE$Ge?@iCv-Ho^Ew$}du*;%ZP)!le%wNYD*%wlTZ8pwS5 zK$enLT~RuEC56?Lm2YyHyz!2>=MM>?Qm3_n0ILD>2hY!rM??NpU>bV zbIsz0rI@O)X9Gwg_x76YR#;iJ5h)b?xTpsQ)}Jn?eY10qV6u(~tm8Iu5PUjm3;_hL zp^>NxRD;K_r(eY%hgc7dIjW52GqE>5erWc&!P0HGHti-0ZdBt^o&|&wYAf=SJu!eZ z5u}l6WxR^tn2%}NV%w&gQFkNCRElW;9R6m%pWD<2@5kOJarcj7ve+i%oxaA+F4kWk z>Kh>W&I0I1WWO$s+@rbR;fGmRR z+#XBin^>(MbxCDK14K2H*Uz|i@%3zV9&i59`@!!oI`bbk-0V$d1^wg5v)*X7Avi}^ zW7PG~6gHI|)j1}ny!*fT?d}TbC7|hUuEp)_Ynq5)&u7y!Hze-ekYY)9gApK&{mHz)PLRY{tc`GWVibI7T?_x^J)PN)dRC3CJN3*6|76^Z^4w;@Q-g#gpf zU^oMt!<*+ia}O{%ZO?R;ME(GDp!oz^FY-NQA1ixv$vl%5j#=f)YiF)x)2?EDOs}d; z`S%WqhD(3$O8UB*xNByhlCBX=JJU+uX<+`;Z6N_wWFM(fQAqrI3pCD6L8n7gnpcf_ z53B3pqzyexh2?%mqFPy4ll5k~u|JdUsE;dAa(Zf6QUom{P=AM@<1xAm`9sN}kQR=Z z0P(Wg;iXkz+IafkRnODe&92(aRMM(WPYQjXKjri2Ieoi|JqZjrFA#szf2zMOgNoh5 zG}0)EjI&&jLRvTgB%4IUfpXud5>MyYk`1vDNpVR30Ga&%0Ljo+<8+bVwW{7;gX{ z`#n#P{#^pME$L(Ko=qw|zTcM;f1gF~ac{cpsWkZD^pwX^$vYi2bA~4571iKU57ABk z0LSs}OWQem-p-QTkn;Ht!avXXo820qTW zRQ^QY%EDfq$Kd`^cW&E)KI`6?7RvR$-^++aM^$V(`X;Dcy!6xEXgA*RqBm0@63}Da zV;W?hT{yk&hdw_sZY|229nbryg^8KL{?*euEBpvY*zNKHvhOT%{CghX`|EOt{n4_^|OSVVvj9DS&WnJ9xVMo@b!WGQ%q#5^uiDZP$j1fCBG^(08b$M zi;~qDU21g5DML!<{G*TM(c!(47mi-q#C2C7P;vZ^3ViX9UMl2^QOZaiw+_v4u?wFta`EyFJpSLnMAS33VMzQ{a&2_WVV{s&Ar4dlV=PvKhODe}}CB%$px?AG*zDq)J-v0n}+=lEtY!i^5Mb{{Wpo z?x=yk*V!iPcv_ovuXV(P15Y4)zSHOEIuh)AdZ;_K?`^DNt6wwxRP-KRr={l9+pukH zB`ziwStU!)TTr6kb6YKp(htv#Y!L_H6niqWwM#p6fiifL>Q5ib$b7md+%I2nyOQO_ z0m6?(90%Lxetk9XT!Dg#DPz#aX4g6v7g%EK#fP zy(4(2tiT!^{KpTM3jMunKm6lAmR&c?9fv=3bp{y^$u6?QN+hDCM2cS5**Nr?s$H#C zbg7$l;o}b`9#j5z*Gk+;6Cl^xFLBQ)ZYN>g=O>qLABoS?%5We4X}1Xnm&Q06r|14n zUT3jg(!wA&xD&RY=%_MdKQWSomZtPa;O8BaSK7#l6wh`900H619BBw-YDujHMf9`Md7D0p_B9cQGd90jj%>au$WWmEqE3aP>! zHI*1=ma3Yt=@E>5ODiNH4yI*bz!hh0Obx*LdohCIOLq?&8drzr-WQyBx5YhT$`>B|;7gmQx#_X<$ue=jvZG0~>m%y*VDA!lQx@f?3Y zB0gOk-H-ADj;uhHRceRy%996baU_IkW>zgxNgA;_g4_-Wu=fh@{@c$1k)ej8$ck#9 z{!D!<^RH6|#qJWmfYbWa9EzWp6(48i(UQS$+6;_KJw8G>L;4e3qN1J7tssf5rtW@$ zz;AJV{=;`?AxF0+nKTq5^7(wR)R(vO9ktY9gyDRJPM~w^^ZAaKboun~tdqucn-3*D zre001QA-P0T$MKVO4jFDMLGH7{5>Bf`gm(2q0&zk?*9M>PjuNjd0Yr5jn4!qU{3^o zsGiNiBK#k0v~GjBNF6LmV}F7`epUYfCr`BbSBmVOnFBFLfy`=-MXq81sMG!$edswI zZl0v{vBP#IGgwm>xKX~O)I z-59z*vx+!ij4KUs3c5Bj23<7|QA0aKWbq(YC2ZEY9G`Cso)zkhif~0wLw?`+BZ}NK zX+yZNl=A)56;zT&-@~%F+KQJ8;HavKs#*%FIbmD5m@{i(qzj*Jtf=%K>iwO1BQ?9M z*7CG+1A?TfADHXD-ixL_O7+Gcr?>9r&+Xl>L!6}CI9RZ`1A=@eQwfc&iad){)sZLgsG`oHY!ygDH}oB3K#m85#^qwkHsxD9JFQsK9C1aQ?nY#r5V zGP`o3p`w>S1Ott^ApQrum)gGc@JtmskCZgMGWOEf{;A3{=l+N~2;K6Euyum$f#~c0 zQT`epiVtFZ1NoP;RP@=kGr+O{I;&JLw)Zi!wk8%dr z??<)!vni8%ds&Z_%uIlPwouWEdg|yGymGHFM4GK_M5+fAabKPd8}c1i*JE|(WbB&i zicRy^JI`oUQcCeu4aK)}7|Te8&8~X7M2VyXo3^q&$vbBCu))2Urc|f zeZ3xjk^W%+03g0T_2yHqI?B6b&|z|0n<2UdZg*wkw+?d`lgU!j(pH)ZtdNqBQ_3i# zbxEL`M3*W+Bzui{v)GSseZuA&K4<2e8=0@;fnn0KJaMukGcKiE)M_HCMMocArJa-B zes1NRrsHYYHyGfxd0CBBi=k?2Acj$z3RD_r74oVux ztEjRxQ%y@>PgzMaR6&rYt$~uFn!1v#ERo8L9V7vPxE{=R3lm8okptV6Dpi0gRfP(b zH3di{5Jd>V=-5gnMU`8QK_71sOyl3S*>u>yY`+p%qBXwUCl=<9lIqz~n7yR(o-4}f}{Q0`(zbh*i&kacl$6tmRSa>3TDAOT(>yy*TGV8Bom6!1O&reA zH873VMMg@51OXt8%-Vy+uS&MgW43^%6+;jF)`*v@bVq z3q7>*UfkR$M@nf#V?@SSojOSX3{yP}ebx3Cp840>?Y8G>-nRQ5TiYzBxRxoI#J4lT zE2f|b(JCZWc5KKER+;O0S!z5I6n#2FGBkkP#7WYn*5!aKIrkwKD9ssQMM$roo_giX zaQLVhYpQ_L*Vdk0Hr8cf#?n_;*HlGMNsfX_n%cP@(7{O(G>=&Bp_L+r5vh;h3!iMf zo)C9;qNu4qAUM~`p1mx#+vUEwwY0Q_p5kW;hz42703aMmCj+M4xxaQ!?0I3^8^3Mm z>S@9?WhN^#K~-4_$eNL*rHW%vf<@#VKHb~*D_NNRE!0wqcdD=^pD+za$oU=}F5dY^ znt6F+lYQmO>o{DU4=gew8XVEe=`=VZy)25CTLvnB3;-+*@AM+v`w@@vl?O`|2Z#e! z2blH$0E_4{4uetw`FV96+8RjNipazD6&jhC{#hetBrVT2;CpXeP=i=WCx)-^)BOEB zt1Zib7!RKh+Ik7I`8w*V=A@YD`#&vP)9_wsfz=bVcPb-GfJhpf*&W2L@-h>{KR@`P z)QPlMT3gz!%woPJ5I2w~1OvvWj~Whw!Cw{~s|1o6WSXg}WP%|eWNL^=Fr;yVq7*_{ zGg+=}`1VR95E&Gjl56`%41br;q4~6va$91lrZta9V@e$@@e+8FaY2e_&!!sP`G~2C zs~4Ha(A6tEFwc&zqJtv}Kb2Y^B@J{H)TU)!GOI|Z#8&J0_Q~8AzBv$7c@bKEMxwrd zE{*MZOL2lrd;PZZSjY@kNZq3(Q#6t`jpg0n?U3|g6DuxB8f{VX{4C9#cSw~ImnT;Nb={aHOj9OJrQZoAFVzua!F zyfL6O^E|96PlU4?RMvogbvfulc@z*W;jv~nV9vU(*Rq!aHa}DT@$GqiB}f`sO@4pz zUY!F~2?si>k3szDpO;*qs#yo_7}be3()yK_#D=|q7X#VdrtTX`Tnabwc^|ZYm!_t* zD1S^6K4U#h1RtRu&SRb#1yV&nVd*IZaUFN<+K#o;W=^Z^Y2ATP>RH-tR7q1OSnf+P&^Y87xb84RFtyN44oLa=b)6p8{oOgonfWLB_iKFwcQ<47 zEhM7&k*WUE#LBBVs8woUcO2tWU-(c5MdM}fu9^7_)A*`=%@2C)>dFnu`!beXrG7(l z?6XN79#`HbeCYGOXLAxC1BP2 zdIWD)8}8A#+HJCImn*(OJ3%6NY+Pwy5dk0&MKy&W(1Hjg9;)A^{xp1y$?naWxF+iS z*50GXZauf0j=y)*W44mZO+%KXu4$>4H(NzfJB6k;3YR9s>PNJ@&$+yjwX4TJFu^6l zpN0}rt7h8Sqs`3RU+@D~r$K4)byC>;{R_cF+YJc9Gntns6BV_hxlJAT?O&+|<%L!vPb> zYmbM^pe^q(TwJ3b`>{DrA^66OP z3a8Bf0FZh9T?TG$ku@}pR`dS=SC>Jad$5udBYESdrAXE{nWQnIsRLO;+9aMuKSBT( zKTl%4yOx>4j|{ZL)|9FFSBL}U(0coQjy+Xyv5IE21MKr-{;G5aZVuF$+IX<9Jf+Hk zTU5n#XaEBYOJ*bf4Pbw#xd(0J^a3}&RTTUy=U-F)Z`;r=`+I8KgT}vxqqPpB`G2!cgZ#~KEp}Vd8@<;+ z&zo`nRsR5s>h3?1SMtW9?w!Ss`DgMA3d5)Nc4dFjUeLsltyl-Q+smTd(L9X2?}jw39@}NaCmqBqgH_8k&nJYebI1 zAf(#t-tmuVga?(Qsb3@eGxk>>pHhzZGcv&(f{%)f9Qu8}f3u@ovi9_m$oY!0vy@h) z!?C`8c6qz4;%w-53#k4s{`Z7LUTshV1vzqW!&Qkt0|#l<_+P2T zf_POtyAXH)5`Ez0(?ttAOCVLL83(CGf8bD>CduDjn+xq>9*L|$bS_-!Rhv%gqE8WR*UtU%&M`jbXNz@ zKELTl9+kTvVpHvCn!2&lyKq&j{ncgKM5akjsVV7ROS3Z{^OB!bhx!j|cKy9<*TinBIM}@KcD))E{o>tF;vJA z{FAKlv~z|A!5KfX92kY!5e9Ghk2@S-5gmgUHgCbM_C~7~?(O2BGsfx-} z!=%bZ%nuusV-g?RGEHHwSg&KJ^ZvuwD)KafXN-#f0F->spHc?jE8JVg;M3Rb`#gu+ z*04X#$N6ey=(kj#JN_tRYH2s-*~`)IKHS)QZW$@+YpO95M_T=#wCU)Ay5y;T+g56p zF{*g)RD;Rp4?X);?p?Fm9z^E3gKhH0V}e)60fjsX3E~ZZO^*+R;*1oZ} zyrnltC0QgzI!l!xi58!T0Y@K+Yve!nY??W#z4{t8cP-?4(1)6eqP^q9j0(YK`SnJ>8(`$YC*;`)@Sn0 z`ESg7Er#uE)k$MksNhLZO)KctT;`zlSiOn2rhUy*QzTKvLsR6ZWm;I`St;uj%p&15 zw3O33ppnSG=GFt+WnrWOGtr!gbvLI)*KlmQTN*mFS&Z)LDp8nANu`I4(m(;$!L4uw zjkqBDv{JNBsSo*&+B!=$ta7fFTGxT|2jqGsJ*m_cv~yNfM;t|F;wqmMh8m7lR95KJ zB9yD#zxCtuZ*q4nb5h6P+s&$r4_Bau-NDfaW*_e@G2Nhzv0`-T31Tm6amDcExgGNVktq;sfwSAb#V)LnbB z5YCVqN~W4moj8zu`aw;Oug6NE(rS65BwPt2ZC`?fg*Mb}`1T`?>e}fI8Co;;9*HEj zxwddfWsrTp%cV}=>}>uDMG@3W(Sv63xJeJH_H-&?m?`JfKEI!2`R%&Py&RkKW+g2(#PW~%M-x_+xmNs zw=ZukgFE;HC#v^;+W!EX^XPrI^VF`Yi$8rSM#tnS{zK65iS7yvg(N?E?~JV1<9Q~G z&lq81?Hx@$r;QuxH4Fa$kGS&pl5TCLlfY3dG^ha3{Hmt}{hbdjxxzW&kHupg)uAL- zp0s7|r`yoOx3`=VQ$-~;f8C`-u1S@JT1Hp(A(}F>MWg^gZ^0hHn}*LkGP=ocpr{-M zl74hJKbJ!tw|$M`O*aMgG2(Sow8Sm zx|%YOdR(%_AQ~hG^Xb4^#3`Ud1|B<9iP$Mo;g>bM|%O2ST3O`4hY_bpm*D^`Dd!u-h_^pU$uB+9F7AE z0deift~@5!6EZz`siCjrYtwQ-k}j7OPfnWZc1Oc5&7+=f)9HSnsjID2cFMlPuiCk4 zon**-IqU^Es)Ufn&XoYT7xaPbW3~H(&U-$Cw{uPGXgDd6nQ8u&wJ+@*5a05)!MSGh zWwwyliAAsN02=gL_rLPe{$Bg$p{lmk4(-_KR8;u32W~}`r=*eOu#!qm?@PFAG)BPs zH6?)@fycQQZ2QA|iDji`yS2MP{{4kP{jnJT0KwFKyL%tVo41I5hI@G$nTl5#@-$-W zkF%gtEBuf;-!ju=deh`~>7tqn(G4Cye{3v9Qx{d_LiAEglG{6qI*N*IXVgV9>MLt= z?nm0b^}CEEQ+4F%T`7|c%%|-N=tul(phef+(`-xludF$i;3{NCG-)a`0Cb1b;gYJ< zBz_<$XgUCQNAfE9V~)trCeQ4ipWmKEdWj~f$?grYRZvI_%&^yDG6=GlI&54hJOl1U z+rIT&iEw~!J0|07{4l8?ADXy7%b*?4-Rqw%?xw!B=8GGtq+-pjWr>)R@e}%h6ZwJV zKspEa7xJe5U^_;wsney?aluUr#rJz(dTi?0Wn@C^(Z!I>Vyh-+YmgQqNFK!Td-?4? z;FNw~co_Lh49aWsDvUp$MzQ;U?q1#Dl-uB*6^&GQQ==0>Qq+GBixczc70rB7`G2)3 z>Ki@rySgaXA5@JceICW!87eAgL9faDR}D*BOpgnqva-u%`h$CWT%7ss<@1lD=N-9& z4~3>hKW3NHgIv^ny1Ci8$s=KT%J)eiBjEw@>r`goetijh%jHkY439%@FOMCgh}>Dt ztC^_VvK+qo*}1>(&Mt>-R>zT}#=)Jcf&)`b)im(|HDXUy6lfG{kpMsUstnZ*dDT};KC)J9=z*d&oWS^)mVqzXw<{vYo?=EMj<(%_GgAGaMv z^GM{#WLh7XpdT#ybkeyL$A6V1@uZQpf}>oLz^M(Solv+W5O1g(dvTCRx>$CR{;$uX z$u}r0P|jvh!0-qBKhZosd^&U5$reX4`Q%R(1|)smEj*2_A0y)}3{KY?k_iEO{X*#; z!TjgA8(pvWS~>cwk))BtNBEE0!?b>9p&z%KXyzUG^9wCDn;zv;!KNd%N%PT{C;ce- zb@a;qTz|{QqwxO#5&k4^+`j7VIdZxFs@U89ryq^UU^enl=CgEE+lHZ%w-ZBETlTAv zsAgFN{#hbmS(Uz+?>8dsBXb*-#nsW7q}8QdC{j33g)9K4t_C`HoWAxx=Gu+_0FgF+ zU)YyzvsSbcO%&6#kTs8tQ0jdb~V_azN6WD!75PaOjyGno4!IGLQ*k z$fJ|b_K&fY_k@=*%snV;!}9+C4_H%YwI-PUs@=TWsz9TBy))(c4w4(fmTlp)H#X6m zEmwg%uN7B`OqD1x)#Br+K#|BJilUd#8<0HF36)wmDp*|mM{^@w*<9K@<})&t2hBmi z;6-cZE5Opd2>EV!`EQx_E@O{wj_hss2{Dbbl9e?grCUiE(B%mX0|05!4*1dVUvl+d z$ZRg{-4*!y+y>gA$mTG+i)wB;sLpFJ{{XQ=jodqWx+SjrHlwL`F(XKZLSZ1arE~%!+0%;Ra2~a zk3aQ(-%h#F6`Yp?Qk4nwH2(mL{JL+e$^lI*$>WYtG^B3ovPc{$(vlLoe!SZDwa*^) zaeVV?eG0W6KvenhSZMXisaki#UG65icqx>Bg?ZLaT)N*87?hIx*d@n6aU6N8m zG(i=MPa_vP2|7rz`g;r9ULqN2#1uW81q}1ZNSfvs^sGPx0ucG25Ax%TAw3{=Flg0gz&vrt&QB7WcpnsqC^(<_h zxg56BatSOFu*wE6gIIIAbXQl84@}xX#$n|IOo^Yb%Xa(wDZq2j;hiz zYEwv~8iE1x^9MEJE7MhL$4ekHR?{SMF$c|26*WX$kO4`VZZG|9?Y2h)Q3p@i(x@F> zN{G*h2igzp>X|-U{{S(r)aicN&vkadkE*HZcGEQT=l3;iRf8oAl(A0-+e0;N4~keM zW=RSOR!5A8^;p;kzH?pP*L@|Ovs;ZBCCJb1KEILjuU#tpzkSa=wD%X=t)HLy+W!E0 z@h`;|3wlN)A&6~E74-rDVN#`4hPriP+hgVjMN{m3sg>Uy#n!NHTK%(y$!;1wv7CL$ zNk^2dp{JU@8eiblwY3J4Dyd4LWK*Z=2eA}<-OIL6MJ@L*StR8FE8{K=DruUL{;G9^ zyus{$KR-0{1&1o~Ht{yc4easTywG?~(4>s9v+5y36#$%(Up|pLulbPtM%r}J)VE_* zXM`&&NfrZdsK3|&<-!vW=Rs!fo;9@u|)c@oWBNz4lD1_C6H{KA3!`ZL?U>t6Kk zBx~h(?U&YTh*$nN&(Sm9U(Q$KrG8Y>Z5_G2b7*PRsq5{EE;5E ztOq3&@<-4BcTanHRppWG66#qzj)0*0WVSz_}=e&^ip3^9KA-!|w$HFZ-Yj4Q+f z6;$G%D)dzQFZsY@sPNUX?LDQp>!+kLMNHMX%!AD<`63cY6)V%@#dK)Ra#55O2FH(J zTmJxhk&>2sA@j_Vf&7#o_^zgHo9?%^T3mfb=gjiCG^)o6sK?Ejzrpi86ivbW();sx zVQQztW3c;Xrj=q@MkfnT_C=)fknD4G`CnB!ki?3(y*E4`VN1_-`G)8>fo*RJA4O&( z^J7eW$5K|+>`x)>jIAVBH&PEdWj=JSBM2$-r`y$Wb~k?SPQ%=F+1=}vp~+`*<{0vM z8Pbi~ZwzXX7l;gyTUbeYNj053n8c&BE>cK-lN?%0Cs(U`+-UAr{eePRPNRJCxSa4oCpbNxNm zZb|mqvpFVkTpJZZ%(|I{Ou9#-K^&W_@gRM%B%Z2EIpUepEG*-XPuT zqh@NX-&9w=_{JZ-#MrLS{qSoam2#<$JG1)+|%& z7O~az_KNF}xq`r|&0$!7jyf`Zq>dl3bW*&-VbcJXUg6h;Hm;oNKe_B$bXxDGc8~*@X`;m6;Qi9!Ua>BlYjXeu`e1|}L z?q!;CRs}z4{{RSI^Yk0m*H>g@^H$VNJcQhNT#$hM0w)NApP;v~UA?uvvS_!6D*T5Z z&yPWwt|p!J%^_p{t^>>R>xxpzB$2ACU92sn83`kh1&18}0I>IVl~q`l82z1TP_qRJ zbNhd1N;-UcK^nBAGhE5xDl{qje(Ug9@$?>_rSI&fS=v`2D@szne~|wGK6)~a6pSfq z7OiRJ`Tqd1j;{&ILGwPxWV}=9CTxSyB=I4)V1U1PWBr^^lKCGAd zbAK*e=gr>1rrmqj?(n}H`tLap_unNElA61HXChduA?xkCP@wplq83KT)qq7MG@4NP zopgfv)1P7Fs~K(V&_6KTM@WYijd&R!`RHFVDsVcY>?eMf*{&s~*AwcIM;Q;2{hn>> z!`H3WcIMu~?c7!iYi(>j4j*q}G4wls0f5F+B_#z0E{-_qG1$y?G$1TcQbK`LCxTXStKfz9pZ(Qy9UR-wEp)cT# zA)6;q7sSz0Q#-VVM^^#osFG$1Ep1G;xm)`jZ5F1nT1I;)3m=d$arj2Kjj4T7j(xZ<&Qm`WN1}63(5&pln|l>%*;Ka{YTxkL=yaOG_cF#~tsT@J!)#JThjdsjHlrf~k3=I*9-&azNnw zz`kMJTI-ni7FGp*t%ZF+au@avyN|H$Xq=I=T+W4VhSv!x=*A@)N1x<#PQU-x+TN$C zak&hPwb_i$VLB(NlI68l|#86Yv#6Z{KLFJT>%<~(|G3Wb4`!a?IZPP>%1z(q+ z+IXIcZf>qF-^96@oxH2SeS?7M%$s{~nsmVFlPOgCL=daR#l#-v1+Fl_{?iFY;yzf#**D!_~X0EzZlaZm#f!g@cnp(PDFf%4Bl z*5nM*R_ZjDIEQy_lci}vrvM_W$s z&zc}YyDqs9M14hp9Eywnk^Z^%6TXBi7%;Odsk*Y2`h&r}y@uIY8zP6HTCi>hpc`g%*4F9Fc2^nJ^z^%LX4UTs?cYta z;irlm9^J3qwHmjW!ZHPHZW}3H!nvu(?906}|_ zEN|~Y%9@7HRFXB66=7BX09X2}(RAJ2F@ws>C0;5B)yI)*C{Vc7Ey$8M7y{JaFh~i%$N46BQg>P1L^+&L4UTbItgxEsbhBSEOAo2K*fH~G5J&GIxKt7t>&hhqLw;2 znpn{SK_hB1Lg&&UX^O1gKlX=04;p=sHg07EM)JxO5^8-2^`{E_!TWlTcb;5icSxgV zpy68Mxtc?@P6RG{hLdc9yAV293as5I601sx6ZV_Ba zR5%U~3i15CIxm{aXb?7%RQb~t{{TNx=<~UZVPChZn4sXrF=s#l901mI9R3ftC)@0< zf$nUWXlByrHXo8`i9vu`;p+8WLRHVK2Jh^z<(#i0V>*@XvO7tyLoUdKGZ^vYf8w#y__>C4 zAb6)gpZIgqwwHRctZ7nq`*nK}2`glW_E%-RD<1L+LR%B+jesY?P%f^GG;Cy!{~Yq~+IfQtEax;^sFMhZ(Q zr=Jg)u796T6xp~XBGq)@5KWAV7@Jrsrnb~cKkdDwdufujiLvtk0Ar=`-rGtBn}pAm zM@~tTl^9>d%BypI5)Z}4Hnqt1)jCuh9Y(bsI??W0lyTu|hzbJNrmCog7wW1)hiJvi zeiz-U%S_|1RZmZG?%IHgvsB9IKsZH zR^zJa646vZ(qihr z-Elk9(-WY_75zS?U&rU&#OS1vgVu~`o{@Rp*4cTvA^s`X-EWkS(ChyZ$xwc19N05s|i?4mCVTg^}H{TXL30c5Vx|(0)Cf+Vl4~+36PC*SH}60Gje2 z`0+gy-14_BU03RMD>o<1!yo+v&~uvV4~Vl?NmWbGePxZIFK^+PX!7**6%_Il6wb8q zwJk(5=^BG0i!cNmaqUFD;`5xZ;?K<&Qa|*VH~3e}r)_z2VX?M0mU~6KR_48^fk7vY zK*oIQ)q?E5<{93dd9$|nU3K?jWp>`o*!Zdqy|nQLvTDjKZrR0AML~_lQ7uI@vWjXL zAVgB^&0*_fZg2j$+}L>Ty1&yRoC1NZP#!WRkYsS2ZGs>5col2`!ac45*&Wc zi(lApYFx4YtASEUq_T>W{@eVVdQxJ)n*RXFxulI>er=Vgg%V*?Q-H^nm3*4k1W(|e zD@nlAz!K))L4S50<#Sf0VS5&#pX`(T-7wz3ds0!5^5f_{M~^Sr{8i!BY_Icu`B6?; zski>tgc%kV3$ZZulchqRQ!kp92;IKli!UG0{XM<@x?JFdmE2;l{Lzp6-6TJEFKA5x z<*6t?<>GH&^!~kKr2cYWC?t+}t9vI27m_59h&C1yBxz!nFk@trIkg#3vs`i*ac^%g zyS(Tz`_?c&=8S*l>96=2y_?jH{Z@TLf$`?3{{W3}>7OzD-abX-ziqo7o9v3rUY;GH zh+2Z$PL-GZnkgM59-s5JKyPAr_S~NBbCijpw@CE=0L>)-05?WfpLhQNYAmD^Tk^dm z#!RvrQ_vQmKRR?DR{sDqp8Bu5$-kfs407p*1&XI8LW`+ge%@iGEh<6%N9l3xDfcs) zn?JlG_5R5}&C&cm)AAL#(;mr8Q~OCcXXo=hBQyU1%zNZ6RwP-wUnriWCI~V3?Gda{ zc#ElymI7)fZ|K%V9D7eUxct*7?%fyijR*NUS845+BH0qw+XQOd2`uLveB0MO2DQIF zenwVnSo>>zV?>V1@?o;l<7N+t!R2e_v?FxE$85vO~Sk8;>=h{{SaT z-;jASc>Fo}V#-+S!broZ`$JS8u#S-!ua%v-fu^pZ+r5d|IJ{+bY}qQhSo_W~t8Bone6` z^7B`zk(rOIf_eUj*>m$2`87n_#oJenW|Kdbs&w=lCeLU9wb`vA1BQrWU)e<+WB&k8 zo5mOshUtoxg2u3|H6$^$JZhu%d^E6AMLWFTuf&)`dr`ERuqitAf9e7^gMg1m(GTrYaU#BYpLCHR9rzz6)nq) z`DU9+xFO>UJg&N2Hz0#^?xs&c{vNG?PchSaZVap_(NoqvIy(a*(}aswi`cUw2K3+h z`_{AM-Flv*sB`6ODpN&WZA_?Gxml-nLQe&VW+3tXebkb0Tdz~ohfVTVQ$!BARA~g* z9b5|&YaTd1?0xtvH2@t|omRTo4x6RU)1w4bB%6_}s@yNo+mmDdKSA!|2Vhuq%Uwi- zDLvG$`j0{W_UuL4dwU_cYGIn98YtD$ij<;FGrNeRjLJhSaqE6u+*_M_67tV0&&<2k zp34O59Fs8`+O$vwNv9HMFfpEpH@;(!XxpdUB#5%09io*d(!2n#pQlAxJ2wlwvT)`* zA8=!)z*5T96kTggHchd$MO*fc=%}P>Su$5;1i|H0bsXCE_m&*B?e&K##20GY#M`L@ zRn(z%15Efp*FfXLKBV*#u-*9^d5ia_xZLL=Sp!)1+Z2*X2(SD|lqg+IsRDjDh|kx_NL^2sE+RI?HR2W`tY zGfHN-F|?=gF)V+}{JI?5d%^5iFT{(o@+JJtFf~A&Jk4d72hS=iUOrtTsyoJP#G<1i zy0?x(p`#J`YWF5bAnh98Oiv@_r4k|nY#5tf!`+WBU82@M2#=OO!UsZqyYDaUPi#{1 z{q>qwr~FbTP<+qnGgIeJm!DE8duE{V2l0 zX}ySdTGV`~f5D!In?JnX&GQ2oq2@anWZQNt20QxBa_Y54&E0GC9|vOkr6C$b}~-QN&GTBm}S8MKSqTtb69)XSYqN zW~@&fzri42eOr@$Br-vD8J5;`mOtp6{>~$)hjQiJ+iW0RSxSKLETuz#r6&jSJtCpQ+(y$M z8Ac)AON18S1O~;Jo&~tSw1!KEca9iX{D9Br>Hcn!M`%uh_@Ux|$@%o^AxdvdR}wYL zGcs#(*Z$4!zu{r+mb1Km=^#2s^8K88P*B5!2gLlUdW|HkrH-Beu?#fW-}8H14|+>; zgldNA8{81prypE@E}}~)xg@a)w-(?IE;VuV;@;FpZfV1hOtj2JX^xZiQw?lQ&!}7K zMaT!9ZNTA^Nj$70f;0e@)g-I{AJqF$ zA_}Cpkg3n@={cWM0Kb=8_k0oP_4xVmTcx_LXof#4LA2q|?)^a-zrH(}TREH5(WvuJ z1x;Y5^?qae+ujoMcJ4R+Y29}PdfT+6Q~e};sZX|*{Q8n@VK$Z)@#y_Pppo-zn*RW+ z%cJA6G0j_8_3K3%!$aYwr&bT=lPO$TVUjYJR+64Hc@4Nzq<(#%+hQ*vltu!k2d<{! z`G5)iofq!&crb`e#Jkj<6bQUQ`%XV^N4sUMdn`1tv2k zTaYoW9UTRIMNyW)R+65QS*B-@U-rVQT!H@a?#RDTJRqR6_JP0};+6C@>e~LD)^f#k z5cL@&NvR-ufGbYEcONMK0Gb~C-o1gj_OC`!w_9yA-nnWI?=wpcZtcrb!JeKF)KY-- zcseQ7NdY|5Fd+E{)7+o!Pu!o9d3x*m$L<8XFs`|oYf7E(DI+QmhG`^5XK^s=#eGt6Kjh>7 zKJbOUHv4+X(eSU?);VR47~W}JV~Qm&B#uI&Ao{Ztz#jF02`2-ss+M4?D#YM)(zz6^ zrH-nSK_xvxvs21}v`-Pbq>+{a=>Gsv*0CQ?Y?lr-C&T5^)q}%wk`D32dLQ;ZI%uk9 zVxSB7*1+6`V85grkO;WF{=EB7AUGg&z90Z3o;@e)kj%29D%_(kk)>E02EDFqRNMWJ zKGDj$g917*faof~*FJp(8;+hu5z5we3!%hkSFZK|8{LQo&FqTt8j5gzY5uP+g&TaU z+<;K=&-s2{odNrWLsUqr0wjf6H7ESg04ObQR;vyG`T>7otG|qZC=c@JRcC|*{6nB` zbz+tf)sUzOB!x^W*C@o2WB~sFwO-(H{`2fVdjJ)X0Z&eZ+kL@mMCUZY_4#yxnh2`l zo{FPbr>ll)Ny_me$59(YBOx}ks=dYk06xnBp$DN(&wkrxBQ!|SU>!NQFnvO>SWR(a|NliRh zt;f^Z{iiTo+sLv0q?n9*i~)h zc=N+72igq@{Iz|(1erd*tf!V?B|I~xl|fTX7%B1+u4N%g4Gf@Nf?D5E>}P4ruu6zl zMpmtKx66e*^YX7jJDq{i*fJ{$abKP@_I$wTI>~K=Oyx^S3X8B3LgjRNkUqHe4J=0- zo;mt^6WZ?HDuMuG@+0lwdJf#}UJ)RYqmDj6;mZVk)R3Stkpbhsz;#fB0!((HNB*` z*|w{?mbFmFHC!LJ7_a5ht9{>ewW6)d72!t6r>CtyK7_0`@m7b8Y$X~|nOQZwmP zCgL$IoFMwxHx~93zT`Uz$u`sJljbS=X^Q?`32eF6@+u3PdZ(y0{gwX!KSK5!ymtL~ ziV5qUf&7L+9ei$)BR?Lg)Eit{=Hwgu1>bvrxm%Z#J8>e?l|xc#^5|P<&f9Imh}z`F zYg#zPe%^%~cITnUA1ysq6?#694LwRYAn*eCoU)z`wE=Ho8?C0|+pLH_^;N-yGZG&c_{dTbS%HIY?;^#qY^APPS`o;{X*BZta^U!6Z_ z;nMSPg#Z;4`47xgXQ`Cgx`>bYK0-^8U=l`P6gQ|cN=1qKf(gI2C9sMA0JXLh`H%9B zlts8t5&b)+1LRNndQ;Kv%#ATZYGIsAPMF#=8;vLGex!|GkZe7bO|#ob8%%7Zd4o~@ zujkRdzWsRsTFS3qBgg$;%cTrkz!uY22wz{MqZbO=NnJ`gQc1rC-pgNRU;&0oaOa1o z%k%klmL0`R#A&E;jQ+qV4Gb568Obkp2^1oblrLiwaly^~rLo z;hXM(w-;w&#{hn&=Z~+wXn!?5d&Z24hZG+^v7DlC!leq32c^mW(H6F@FZlPek6INy zd&Z0ki5E}X*D+qC@iGx^ePE73`g6hhd#;oGC#wfjQV8qEB8zdUe*iElZ~3_Oem&?Z z^v7G)wH0BWy!ixG7j?T_@ub*&K{ou`{qNqwl71X@R*^7 ziQ#^h`up~V&u%*Rh@PW|Tngp8=sEZ8B-5&wP&kV95%Q0FD36XWa>M8c=Ev%N-@+%4OdFLALO~s3lPMrR zgbQWV#Hjp{b94E>;QO$Idi6%SBjH2C&!~qfA$v6FhRc3HBk^;<`ulU~&YFcJbiust z16Tv7vS#VxYqe7y2IMJc=HP#3>OQ}pZmpEg1ta76bw=Fn(2~;Do|)@}+p3nHAkl_$ ze-7Y%2dMo^eGep`caLkHM$*QeGd}lk5^7Z>{Q72X^C34@r-c^$%EX2uzyYK;)DP+{ z?Qq!$6gru{L!#r%g^4H;SLR9d;nQVi_mf)q-Z>Sa((U3UgIiLvhCHYj`r7yQrX7ed zV&I0=jP#mrWS3A8kW`H0^YcI9=`}9%X9O$E^0(@FG=;ctPtx2d;0y3QnWn}8sZ|O+ zKh^%D(M#{Ly5~`I#=q+QohLF|v6QKLnBi2ntj-qvdc8%#1MzG7G_~1*2TVnY@~8V9 z7F=$!8dhMWeELS@x3vVZ%N$T{lpGq+ zgX#|&^iy%Vz`=yq0IA|Q*P#Bhb#1sc7;zL%SpK;wX+&-SHu8E0`wQOQ#W3yr)l z+qUjvPypPn$oacd_Oa+ad%bO${{R<&ACijy03pzGS-LUR4n{WzB+?7n<5NnPw*)Lj znAr39_A#-y-(#nVxwSnHdH!Rd?Axp|oi_GmkF7M0q0??H(*uU4GE&A(!V0-G+fM)q zWoy`#$_!s5c? z!h}Q={{X>H_>XQ$65S??n^4R9f0)Sqy$LoBWZ$`NQ9i@CPh%$<#`ISClr=~H0Bo($ zorvsA1sp21+iEKL*1*)QTr)_1p0`Qu88`eYulOHimpruz1?Qq!JxXfGfb7f?|q2i8c5@SG3$Uxt2NEh)QJYN*0t@-!H<`Uq8$Inez|7^+wz zpX;Sh`u@Y$7Mqo^DJ`2X%mTyqjCGQGH@ZBd%&?@JH!;}?{swi9Kz#~GRD{=vaYqB$w^(8V=qiosj_sz_y8sWklz%FKV&e?-4e z;m9Vok)oH?Ngw6tqjA_a-OAnVF0CSaX5x;D=xhBJ1P{ucaoV}ggxb5}OzeAU@wlw+ zDtPJXa`?lSeYLo#+sXD=nA6WkCOdIZJKEqp6H|Z)SGTh}i_PBqZg^Vk_^^;$Pj0k0 zs}Y)^rw$>#M^O|W-E!wBb8WTMdn^Xaa8`~Y!&<>|pudKS)e5u58kGcxK%k9OBQ*~F z=ndlUkFCdT>Q|od2zL(LqsBopTmj;&jSLWn{AzgIe}}R~n{$wwwfV%2|k@)Mz+o|0*%$Zg8N!sxI{ zC6=y;J@{mK5PnzL-H$fh#LFJ#5SlT9zyRa?0RI3kp^k0#50`g%rkj^!Hdp*YF=m9H zOr3H4ppZX@s_yJAv)-L^T=>nyhN`5InT!)KX(_8=LQj_;T!X_~6~ENk#raX}d$-(J zZYn0UxK>JV^9TAv%dAM|{z~RfP`GQR}3 zsAF2zoHPD!+tJGDy|+t?!NFBqPZ^PFzTzm!))OOCBYCAdtfgt`(IZ}cEDyO8m#r2H zRe4ZXRe#$aC-M{@BVMAuXup=`?c<6=rj#f8E5Lqcr1U&c$^}EPB&x_=gAl|Nj4B1> z-%&s8J&9v9diit^nQIsa)BL?f$W0o7b|jrmz}7$y&!n6G0BiB}_S~!~$2~s+8k!7$ ztIw$8Tv5h|MT0B5FyOSGq&OFA*nhCMKIxPI4jzA>PEqLzrAxrkFabuvQNF-qa-Ml49?(zLc|Zuk@ofTE0^OZ%RC)rC4O_EH=JN(X=bgR z7Mi|6H1$GBUO`D!Q7gMSEXKt1bM^O?HXnJ*t& z_K-;T*Y{ECf*8&|e1C2S?eyqhhaVO`j*A@t3kE)xnvOdQE}CeBV@eycfoihjCqi@yb|4>u#)M_kZ!wHN?;Lg#5!sT)`l873qZYcO-j{XUQu{E_Uk=>~(tC!@P5 z4~PiB1N~p@bO3G&EmEqWch(47$ElrzT$64rj87jyZ(&==#<~j9oeeDH(g`MjeEJWo zs1~X@VRZ*lD9-8oL&`L?*Rdcgi`(#hlt~bJulRU8L0ci9D%&85uB|`ltR$>r2f!1H;n%PPj9PqIr};;d!qpgk7uGvFU}Cb;Toc%#IJJ z8}bjm{#{UtaOt|Nc@f2tVlIf!VkANq`p^MwV4EH-Z+;&>v`_5m4_}X#48V+8#F0LXdssEW2PN=^>P!3^G44pYZ*i1=;?#6120&4Mil9MWG~cm9%q~ z{;dLuA|}@Wp#t0=V$Hvqo;5^vS3qlus}I|Q`*YA{`We~4IkG@x%Mu#=19wlKA@&BSRDMSF`r(7cN+@?WH1KL z;XmX)oddZYuqkRKGD#&PM#WVtWBYwpZ6``FxeUMUy^bw+V>D@{LxMP|)zC)cYY|BL zn4t%Q3RkA)+Zh=HNR*V-h^goh&LVcy8Nmp;ZpJh8w?5R3+SO>SGourlijPh|Z%K~V za@A#pT|n|QKeMJOu=-d;)YWvQUrd^lR;#bjDbvNzKhxQaceNVCsNjreqUmh3oh=lI zYnqDn3OZW425IQ4NT_dx>Iy#Z-L-yon?C9zae6)27JWhtbl^CYa?ZaEWiO*-w5`+8f!zp=H{;!#wt zuFR@b!z6~>lHMlz8-0J)_CY5uU0cdf!a*NsAJ3zt-mT|NVo+55hx{Ep(QhgyL*uI< zb*Ks%gDuCT3zoO~--GQ8`yId|R5_B0A061z^dusbSvzz0i40|HK< zIe(!1-`aKAv(*EUKpIC>nXa%Cjz_ zFU9`=uePMyr3yPLLGvA1Z$(l(jMBHB&3`g>3G z5a{l=6&`=!r}_GP?l%HTtmcOwZ%%RN>j6-*M(WH4mI_>yUIDNs=JwKlhx+?U+jJB) zQV1WH`o4WD8>PS?DN+yF`#;s^*Ex4RLNW4)9WGgbaS;lADyoEn{;qC6*Y{M~V`15- zH`!n3<@R;9-leS^DIc<*FZO!C+n!BcKOAL1^)eO!Uc}zO@o#PorD>~Cug|J}_iBYG zx_;iUO}nXp@tSud@>P~CGJZ|Ujx>SC`2Bsjn=GfeNGtns)gOC{;P6Ql^`?K-PP0>P zx=$LbMq@YiS@}MbVaX%`fA#I{xpsNA5*ojkPDQ;%qym&bZ%!ZH>~+@q+0d|&e2f$* z2a(>9cF#eO2{1x6LwZmt_rTA0XP27`1_*mGX^Tur{&X+yh6Y-)S7U} zrh1ze?V)uEByJHEo616q9!2!rGZ1*N=i3jm+$q$oH6JdO$G=;$_;MlBPBi|1KeMhw zbW?uXEx>ftbOc}l;_Y@8xv~EMVedz1m${D+eCyYS`4tfXI!N*#;m=qm-Za7nI_y&F zRiuecgJ}Q@l3UaMwa@hS;%svn2W}6@^+`E_40ILLF-#B3rbpg1s6h^_*J1~j_ZIru zYzH3KuE#T0pn>*uSlircMFmgW(_MF9Qh3xoRXr-HCPaAwXIqd^-HFmjAM1NrZ_9IQ zC1GbLfdhxnq}Lq9R8VA9LBtcs<)1E+6+MSR2@Nh)4YgTNf^?75rIk(2k^McLMawrX zD3)jQ=$>8u0R^t{=sh}Ns_e{gRaBCqeMC5NjIFBoyXz{NdElSNvlzKj=#p7gY2{z= zQ#~M)m>{JCv95hT*y)O|v#ElpNM>eGL3e1yxd0o6YoQn94`vYZoV6vLK=c*=09ATL zFEGVHMJJ{jzR!xDKO?FkEO`Ouc0bWqfCwK}`g=LB`< zi>ZhBPf8u52K?;99GibJvv$rlpRk8bpg%PcEC?}P6a?axr$a6i<9`G)b1W-sOpl>SAB_&S&#_t?v8c&6DV z*jCj51HiXQRC&~x<7NbLVsb0p$ENMw@b|bjl`~iGuB+X6Ok_b@_`O!i$yDHka=S*7 zN1CLkn-ErK7DMG4{-ch4)AxS;U>Tk(nA6RMs(x$<9cWtnVa?4IxZHL-*_OIuq$SrC z#7(7vry4Fi`U%skFfVwLTzkl*hY63SeJAKcX_s2*=Z|cq)!WgNaghCtPx*Q>Z)`a^ zV$=Oyu+o3!+ARKbuk-7Soh^*0B&uR0Z^x33SZ~MWqkl=a``5K8xNb;0Hwh{8HU9t) zL^poU`+aoUrsXZYh#paB{{W5^>AFsguZfyWZ9P;Z3#;MtPZM#^5LL4&yM8Utw|{$I z5lMtnuk_F#@KE$0m)RavwRW3jlX2T;t{T$vWB~sFq;n#X>M5QaI>a_M{{X~-(bQMg zB!BLV{vv9GAaTupGsf$G>Olkgdrc+Hgq88O;}Je_H9zAmQT+OPK3MkyW)<6c^k2j{ zN4Y>6zb_u&!*EZjQU~y!o3nD{zk}9Ak-$|`WNDQvvDH)sa#;B*@zO0-IChLBZ8UQ< zW;5i9)_W6gezcAOa~Ze2LkrbeU$OMKp~3Amt#IC0=(C#lUHSQUaEE*4ONci}G+bNF zYDLw#p4o({+_ah?7PlPe#E?ZbN;FWJ z0-sb~IS1hTEit6P85jBg0GEjW00%-@tX0^BW2jRcIM$RumqYd!wDuor7^h3o(nmzGbsp z0|k79paH{B9D2JS_xSGj4X2ka$uPkmj_1g;;RQWaLF2%lqOMA@xv>{lv!;uJ`T+C` zllFsA!;c=X&!r`*i+(Rz?gVBr)hwHGxa10jX-D@7AopUAbWszh=kX% zTR6!ghvojSE{1%_!8XY^OLO>p$D#H4dH(<|tXp*F4amOBm=kx0Exk&Oe!}C8bxXCA!6tOX%S&SPHNFP_S zivjf?*WZb+0BPyflxgm*8_4wrwnc#u=|IYcQdry_HsJD0GaCzkLG78FKn9uV=oHAz zDrikQtiR?>+qF9vq_O*d9X>$jxBh+{Xp0mSOBN!MIjXYG)2xw*>8h9{Qm_QFwYa^+ zS?+DwJi08tp%Jbmq10*G0W1II<-NJ7L& zAon2D$|@*DbHl0w#%Jp5CWfj^en3qfVkpL9&aBU5O3I=Ij2j_SqOBoh?T00AQY&>Qrf!lmJ;m1NCN- zLu-957%hnW06F%;t53VC#s}#)u?Xqjg(ZnYHL*O_*wy-pcMs zD#)M%PxXG@jx7ZrSz=bCe=3jJ&^Ne4q;(UBRc4BN74>RGb7m+kwp~E;zy$jb-3C== z3)~OqPK9=QTf>i4P_IE&PGV%JAn8!0S#>FqUfN1(96FLNKd<%nMKQ~oP=7!6dJtQ! z6)Thczu4$C-V_ZxQC9$fOA5sPHU9v1M5GYI@L!YuCjQDV;%Cty^B>^o_iUITmLg6K ze{V>fbmoG(11mBolTxT<8q9#kb;eJwHb)_azJu9ZN5hl`IOuuHw^}Zxv~PlS)0*Li zRF9r050!c(Un2I+Jtpa%cxcsV<^n~wj}U_-vs6?!h{&N7%CifD=_C(oFs#GNsiMYH zC8R9ba43G!jQZl4=!)(bWps?q9E`a6UVwjTnFOAdunIgYq%dMh^;_H6=}v72A->cTh^XVm1PF`IL4BCpDO2}1MhTu2VSjN1Yaz8%( zUp||sl|Me2tEiaiRq{rIhm6FH6s1&xRI&ZLFV_4Y$G!DZEAr_Rm8F_T(vH_Lxl-Ji z9IFjPAyOj0D{I*Mx{;)cXQr4MaX;qi3tNU0GS5{Ug_CDpBPxT&%H6yc^5&>5n6`DkY{Q#gC|6 zN5?awkXFR$8ZD)W`jc~iW)|D*NhliRQ%rz=&(b@Mo!%_0Y&?k{=IIY#vzi;lB@8jE zdYPb_TPeNR0?YKUu=XIf-vpiOaKw*LIwQE*be$~%fPaLa^?jWuD>l7A7DRBi1QsCO zj|4eEeM|oJ^!8^4?-@PJEB>!ui)Y$ilu$?8(|ntHSoEQVCw3zL0BusGkN^SJzlO0K za($^?%^Iv6s{a5&GK*X^w~BJxl|vttJ22z(ykS3c{b$#0I%&@ZWiRz z#!CLql0M%!6%e@<`+9~Tnw_;pHAOVM3+S2_2l{G`!~=hCnG!)qjafd>f5X!vH;mO? zmA=9c?HxJNZVkyqqwO=*u_?c&?-|F^&FG(4y@#}uZM$8;{cXB3f6~+Wigcze$8&@a z3jRPp(|@0*NO#`sr)6VZ4MmGRswt`D)L4yWv}nGo4{0Rj?V3NC^O%w#^M(>!M5@HES$TkHLOqHa;z%>;7DwEGYFI#|5f zxeEA^#?|{r`Fe4OwrfMjESTpKL=}V6WF(LDAE{S{L38;xzqGH(uoYxmp``x+5(CHV zBc)5t^8&2a$58ZgIDCjbDQSDAI9tgj21y-=Z}<@m;Mg_Jr!d$X{{T z#{U4Y9=-i=vc+Xg{K)H)cK#ume3=SVKz&M+4MYL{)SxRC7vt;ht;si_9X8HS%ys4F z+Y&~rlmqRrQ0lv59?s?*y*eRLW93(4W6HPoTI=ojxjN)14`jsG(w#LYHQH3@yieQL za(31s~ARD^U6WFC7io@ zh%5sXCr989cO0J81-9?y{;c%db4)-Gx5M`T0IMBEZqtrULTtK7tUs`_D}#PCltcYL z*Y@z`23i!dAdgy8`JS3Q)gE=-gZUrxb;0{`Am&K&6&ykK;Uh^(t(1*kxcF^Ne|BC= za=KdCek#BIC+#GYlT(n9t}mrLYDfd|~RnvSG>%;_kSN_u%^Hn~U)~|Bd@CHYVg~)D+E~i>1wFpu9)N_#>-7A%>#;Q z+E~0PDgq>oB&+!(dndoyEVl)D_UM#cXHtI`%?ZdqD$w}=ddV+t{py^NvUA1An#xYm zaNue{ai(%9t~37p!!H)7;j&N151Tzb^3!d>)%~r3+qkXeo1>2vmD)R{XfoRuf7QGJ zB$IExRx?ipZa^Jz(M(N3u|5f2!oY{LxwAi0Z6gAwh^S>F)|^ML^BqV$#mLt-R#M;E zs@`l(mY@t{QYtlpP|=WTvMwpa4m}V*oPWxoZJG?%YJ6zM&EYXWF3>+bpYU|`NkvlOT1SGJ+Weh!IUl6y@;Dbi*GcE; z?7nOFRyt*shx%%NgZ%v%MGUW!RZs2z015v9CsQTGNlz0<^VG^guyP2B{{WpvK!I+5 zz>j*1d%Aa2Non$}Px))p?`k7b%_IH2K{abkS4^QDJxpSD*Yx!1F)fwA;Qs){J(|V1 z-#8)BWK;Y~Df!o=iF$104+X==F#JgDjq8R&4<0$_XzPEIzaYAfvKs!f?k>;RGDg-$ z+FS2(ZP4Gh;tM@4BP&S^=&!PX z#c#RpGG1A!!d-~37maDA?I$9pp9u%jog1tt^Dp09f#Rn59n?J;@>>?7II40R_hl~C z?4PxQGK#dlrPuXaYjZ_V8H<^!zVVsO+&8l(xU<|wi`Zkh9zoYje5oR7em^t$^ds4Q z(&l}Q)%IQb=WiAGAeE9Dla@BJ__oJ|0)#{ZfE;=-n@e^7052}`iWqj^Wp*#aUGr2U zj-PLLSdX~+GP<^Q{{S@yXKgG#BeC{%3dnScmg3pcX~+$Rq9QedTYw$1deJNaBa@&>rKmp>`tKE9%K6pN4_?-W zdkH&`N|nXZ^4zPuSs4%dC#&PjdN7ou>L7s`^NG<&RU?-9+}+io8n* zWeR0M{``Q;8R8zDBC)h5kE16CfNlOC>yCfe`yra5p1lgBkx0SmKz6PdC!}OB*xIqC z#igW+%ntxsSk)x}bNS=hOs`UEdPLH?wPRvF&X*q_=h}T`xqBC_w+`E>+)s%KEljq3tCZQw;|VZ-BUA4-{?<8YSN@3_*#ab3WhWUR=p0O=8el{wvtYDut;qpE&ewF zX<-N*m0olU;zC&h$nBw`Lc}wTIVbz0uPJebw$|prXYf0}4PBJR?wm$;h~sK;^$=7q z*+&f=@k5ZuS5rr>I*8>AtjZlti2*@@JTV0DGTbR4!KnK%creI6mqKesH_t8Hcd%S+ zlgAstW212gQwbNf(Ysj>5Na#KuD0iBZoar=!)|zI-Mbv#2r>^EPnE{fND4JPlE`#a zz^F)QCpsB_LxJh`OLw4at?UZ98C8^+V$ByZe`_*LN>xnTwAV0 zS?e;>JuL?(pb5wN&h}lJxbo z3<;JO0!SxUQUM3t9-A%x+b!HTP?+}^9D)xKr_=JtK4T-Sa=qOl`n9o@t7jkpk1DqV z`SAUn96#cacArw#)Ncte+1GdSgUo)*vtrfFaVeQdH1udyeHHx0Ggxhw1V zhZ_FR=g=6!c1`j)$n9AH7~-wNkDx!abotQRf%DyKjd@w6tHX(Q^+PxbB0V#ghsdQt zVko7JRP%5-_M>N*&0wBvou9M)j*{~=s@m@og%n9CApG!Y`Ge5Y0w?*foawQ#I=vj} zV{2(2o;{kS4`>|+oSd<2b;ZKQP1G3qW@IMfMmA7CI)EQfr@tBsk}>{Xyeh*7yXWcB zKQ~uox+RmAW_IUEIwBfPt}k{!U#GI$sW=4~{{U4wIk1G5p*3$W^8S8ZYg_!nJFb4t z?xVJG(3HV-hw&Y?9YR)p%o#k9nmH>fDWZx=DI$g@PZ@PO^Y zi+Z4;sI7aC+fhtXzI}Gv?uG4)e249HTeaMk-M7IV(HilGE~$G8e=>?KF+dg z^4XRuD0rbDVM{@rFy|=Y!cgqm*h9gp8#%YjyTjXjh*U<+z{lmFOm?B-* zkT=KMuga@<7h0u-iQ+s&qo6p`MI(=|LghE}4(Wd2?5&AOx1-MCGuZ0*l8QaUMwD-q zuluO0nh3lS%}iOOr*fpoq=o}evEuWl)4yEV%Vb?=h=WG}R8$;O29*ANK)mtyKKCcv zK2hB_z0ONZy{v=c8+T{$l7t3ez%?j9G*T)FC#$^2ipVHgQYb>x%w3aq1LB>I+59idDh%#x@ zZ9%VV4sCD87asLWdFQH!A*)^;C+p+Vz6Dk~wE#tcB!Zx~*ZU&=*^qY9nLQZWwxS%K zk~J9ikg$w|aE|f<1AvI7Ba9NQ`i+nJ%GtwJ5j*?_m zkj9BoPb#^Q6qX=s0$CJ#IKAy*as~aB+{9Q>sobPz_UEI!In@}IsUd|a`!W8i^j7!& z>D!wg30o?yHb$ub0FdIS-&K8M#0gs?Dy2OuX#>jkUU<3Sgs$Eja>2!1@B@xN$@A!W zwp!ipBzP@Imx~?(zs#SP9*e$WF5>L0J$$qa4#vQ{#VtIH&rgt+o-o2mB7Yz88lNK{ zs)!TvEx0f+F)1oo^f7$3yZ2K@eu&95>02iHuahSf zi!#*DPg3ZWNWx8JnzYEu%%Fd)53(k=A&K!0u7xn~%NBzbqJ;zzLOi%r9X9-e+qqnh z*vDp)I89{^J+Zl(#?-WeRBtpD5SP^Y=c$aHI!LqfN9BB7z!v`iQR-UQw-~SN)^uS; z%`s8JtB*tcsnH6D9wn!&nq5*ulg3Lc&gyKL3Re)QH&rPli!v|+`tm)gAaFc-I<9bW z&^=nB^C23`e$0VNmP2xq1Z5WhI-Wlt*WH2-PPEb*8XxvLP8qa^rj9Vha$eUvK{>-Pa;TQ`sP z)mQ*pcu`kK1Dk(oxwq%tgkX|_gYY1K6v9OI^1jBGNN@CJrN3FHzkv8jip0KLlr$+e08pI>w+!1|88L~M!! z^XWB^rIln9C;u@G^8qMODQ&(_A{*@eCIssWBu z!`7eS$3>Iv(VFT^SJJ=W73nEmvgxH(Fd1Xj^k`pEOIqY9^$WN7dpNh>WkLj+O+9@2 zDY)6Z)Ez%8{{XYnW~XL4YC}|wG+>n#RQ|RA4Myr?Byq>r*{oaYwFrdhKf>7m053(d zZ4L=i{lnC8{{RO_`kkdw9LnPzO3XRbj>{^e4NGgOWj6X;U!P}@Z!xkJ`lkctG0|k3 zO9xUQTK@n(nJPA{YK+oDTNIjt>50h&jmdKC7yNkSdtV;##ei8OEAt=9og#guRY@r7 zeqZ6~s(raS#AG!!0yalq-=~giG5P{PB$2>B(*FRDYa`twFQi1esyGrlO8aYsuZ+M` z%|ZVF2Tc_lR$~sJC|qgRu1Y|l{uk+Twr{WJ+Ss>q_S}H0RI3kJr_;1=%r$e{?YvUXP0is z$st-53Z+5t)}dlau@Q$>7bgDzUu#oyP|I6`Q|hPr^ojQBt5N}vM*jc>dX9GM$8+}8 zycPs2#^91JsO?}CulW}q-2LXQLE^{z5Ax};w=(|#p+D^%V*U{`0waSU3a$85Ayk2{ z{tPeA9^CrW1QwDk{lAw@i#K806u<0w^$JWpiz5YxBcuRD;9D>v>cO=I(n0?Kk^6mb zRH!CMtM>HESukP*a?|YoeRFI?fD;sTC6&EPEFakmb}9hnul2e2QF^rj*(iMvTQ)8Q zQC}XT{a>G_TvCFim4JqAL(~tBK&40a2A~wFu>Sxbduxb+2U^qZAGfUtCMrjU)gL3n z)2t1Toun#bopgdoF!TBPf$0|@`*2*w6dg)y^Xay=l(7X^Q{~q-rO{61Ox~VsVT=*@ zBwX?}aDOA-gxaJ~LjKd&j9OweEsv0|Pz@`xewmn%3V|6Vl!JQ!ZZB_YJXHK=Q z!a8+O{?56j1o9@Nj$H!ES)*ae7eA$Wx99Qht#cZ+3kvU9D|DqlbsI#`Qw$o{_WE};wndf;&DM&3}hD^Iu2sL4lCZ(x8}{QwsHT=Gu`+pRoa zroA*GkmT^|n^4XY>~#GCkO|gUeN+HX`_T8HaT#h1{{WM#7+#eikx77U)wx04ZN~(&FnCaBDasf4`$bT-St_o5wX-L$no~YLU08Li`*z5F1qxlxo%J7UrLts53d}1OD5!?sMVTz z4xdf6oD)wvaq3d-olX}?7Y=w?TH$!&ZuHBK4zb=bgnI|DWx&?XZD))DK_LG0y)sYhAc{> z00`xkRW6o4Til;*Ht6*%xgWRvN2gb8Kq$tC{a&6_>kU>u8bHz`M%v!jkA& z5rx_sh+NneAgAeThF0YbzoYv zNTVgtJaQ=|BtwjFAgRMC%9?o**D;EzI*1TJ8FfYF6yOv1xo4TJf31fkdm=Y+Edy#| z4r#0W!=Tu-l7yV&0YLnld$MjK89aDn zpa!6^q5l90IqPE9L8TgA@;E5R_yFlqw)1s+Zy^mXvT5XG`(m;b5y%@{aR-cshVpX@ zf*L7!AEbHt%S(nQ=0I&%^w_qdrHhmi9y3srKuuZcN?g)o$ZWtFgf1ex0l2 z+3&eZR$6RE#q3?jT(q@V?77hnH*9Y#tk#LCYuii| znJJ3+-p1J!g{{R<@JjJrx z%Lw20aE%f#?@jqRRFBpdzI442moO4 zkI&Zr&XUSPRE46E`TqdL^i0=C0Swh@{kZvgblCYPm7X@$XV%3TLtRCJ7mNn5A&=z! zZ*OL?ZR(1xfl3P3_UHXyZ$+E|{0?#Py=t2u((6^m2UThXIaEVcW8XPBYN>^h3(yLj=BSBr*1L%~j^eStUq zx+sgZmcrgo_u|*UW9Z4o7Wsl>K0s%z;P$KBnfZ#^IPG`u-d5@<^p^|{=Lj4gE0aXr zp{M)tQtc^6E_;gJn-*5c(dc4`;Ifbku=KLGAc8%|mj#fpBv;fBLHh{7A3mprxmi>? zY5@5#D#PT;a-?~KkSR_SA8zv-ii=9GP*rciwGpDu-%C}c;2 zOnQfqc_h?Pq6&=ZG7)C-EQ+97#9rX>?MB`SVN*l?ul9Nw%Q40)Ck4rQjE6dGx2U|&g) z?UEbV)i(q#;b1R?hm#;^2`FH&Nm*KB$BzcpQgX0fiXCtNV&a(1k zD&MFw*(*@b+C6)lh-Mmh=vIjM24w^LIS=sx z@Si{0I>7II{i1!F$L3yNw$rw=cgIin9ztq9$ei#z5wXCEZRygRj~hjw+*?NxQ3gY9 zRZ~;$oCZpop{l8K7;KwCS4m%vkpf24_4tg1Jd4W$zM=Ia+$&;DrQPP-=thP$2DRft zKH7DS`{X9>%ExtLd}bO?l?^=p##SH8rH4Ve#c%G>*<6(hK&xLf{-e+kzPAFkQOEq9Fl5lgl7P&i%PTW2?Qndi!}5cG zf2sD8a6oD|A3ybfE|*&!OoWaf>i&HYADn&n7f1C~O%5%gs^0tVlBW;0C>EkfXQGNl zFl6(O;9)!oiGjzBfl%|Zt0DS_$e2axHVYpLlf=pm`A ziZk~xh~qN^S7w!e%_a4*RUViPBm)B^LglhoDZmr6+MQ9I007UdRZw6R<2KpgSNxc9(_=8h>zsR~$uQ|Dd>{akwc z3)=1?hThE7h0vg96{iFKtR8|*!;E@qMnaCI>1$}JV5*^-0cjSdmC~Y`vMU>jX{TSw z1db2a*u!Mpq=r~Zjv1|Ze7`?0o_ZF3j^|-5jod-)1xgjc^(ue%l7deN920qkKWJj*?aBo^!(Sb$29!Cc`INcV+q02BMSEa0KTMZYXGSg zQ`OreTo$=EwUn)yZa+x`1JBoy?0=51U4}sa09V`6dnYlHLmXw5<4`1ITY;~Zy~Vjg z1^uOzl4zvXof=xlp+m5$lZy1tL0MPyM2tUl19@FVz${4~oAZCiwB!(1wu*mkI$MH= z&Ahz_+0ZB4d%A~W;M%p}YTTt{jUERSgpplREFOB4<;4vu$P3$+B~)^Kl5Y1A+C*Hf zWGA$GpYslc{JCW=<#C}{EJ{1v{t@Uuq!#Do*(AwP2{c0G%{Ek z20g%f`jPyqKR&D8z8R?Jl=-bB6VqfU;Bq4`2A}e{-N^|bp@^|JR*u};*@#?LmFhuh zNyy>Q7riLtp~=+E7p9ja?^#JKL>R;CJ?O+o z4zwj&xpObVn6tdWzb2^8~d5N+>XAKBHlgTs$Vny4bu(7aB! zvHN)#+&`!@(9B8lxwXh{KsNe&)d=#>O_yE=&;3~GFE%}BAp#lv1L|ejKVad#GtkANCc|ffJXtX{eAmM;ZC)vFf}5b zHcbfv4=6IA5*L!oaG`ivfdmaMKDQyip!ebk;yTb^2s}qjOG6arg+@cK_TKykCg_0O zh0i1dr|Zp!x>B?~YNHf5>9VR1Nl-iu`V<3yLJ|-LP#GEQb#lVq>Q^SCtyZ3N>7uV2 z6@y6#c2>}@1)RDOd$?OGe?UlHc=xbfK>@naRAL#F9-&rXTSm2ySS#s{GDP5APM{a+ z6dpk5k9SFAPd=$6DB_xb&(ka5>XDo@g`<&3N@}Q9Ww!^^WwZ12{a)V}YefAb9C@iA z{{Sq1E|VKZ1%Q||f5O7Q;m=G}Scn~nYB;=~^usZUfoq*jPcX4>^^XJE*so+zDLK>q zF<<67Lp7vDs9{}S(KP=6jGyuzndQPpuj#0koxX-Tnp?!0zjjIre83>mv<6RSSK!L(&J^ zP*sJrf}Wkj{YRwUM*|LoB6Wq^Sy<~SrKbRccLZsDApZbU^|80JOKrvVF!0MLrd5M| zo}Cw5SVln2E9AnTrg#RZ+<;D&(!-JdHXhBFZ~~QSLHiF8(PLQG zI$|U39W&NpiXx$+go5|51&8L&ts4_!MZduNT?O`{SX?z}{-K_cTv*Tn;IAL}su9y` zVNn?Br;aw#8_2(Kr6VXoBb4G2TjsrB8>w? zvsp;JrJJ2!q$nh*)Csk|fO}H6Zp}w4U$B3x{QV|2=%T6{A2a^1^L3T+R{a#uswGmw zN{LOwsr^dasbV<)03UQ)%KTD_6Xc`IryAOn3kj$d$vs5-1rfWNW#z8S(zz#)tLgf4 zf3MU1@7w$;PuJ<~->7O4;vSpu zQls?8Sd9usz<7|^ijPUtb_0=b#lNk++v*v|#(JoQ6pAS8pWAY!L`0}k`YMZ|^=tb3(Ygq#Y7dy>kLT&uzL?0z2EUh3Dll&e z)I8=e52#C}ZT)PdTh!jvMYt>A>DBgh#G8JTtGb_UI_Cx>%n1>%rFardTE+ES>i6W2 z^{?+zUg#pMbLcvrLl~N7K9P{moCw|~+!|kSj)%kSvaK=i~ zfd1bv@O7E#?8ZP8on!)$aHR4-Unf`f_SlxANv$d7f6dj3@oXIV5A*dBS(-V|`TbW4 z7V#z2@*9O?aBe@t>+R%>G=GMlnd!H3tVV13b;;S9R6(QY__Wf7@7F->O=Hl+d4F@(#34nvlZ3 zG1GNgiK3VHC33>R_{4Xz@cjNq&>zRMeWGuszqN9pE~*^Y2Nda-t0|+9{zria$d8yj zKF*aG=;`WdaTS>=II80?DLz%WbsyyQYK#eFVo?5W4UgB`@=ZS3e|HtM%z_pnr1xmfX25 zB;Pq^NpHDdEW(wZ*l`-@4~rN4H9#PIYB-d;wJlqhGEUL5`gKmg0sy|KqaxtyI2^rqW++Js*rD{w&c~W5+!G}p0lDfGDxdlAIv}C9$%v?^F77YI9$X%HSps;hkvw1`Cnt>AKF@kq(-E*ko0+jmF|T)_`%)-;z3Nnp!2_$-MN*9tq z0C!$33OMIY$>)o6?Rr@W8Ctll0P_1t{{U5bLf54ft#Rgm$=4sg(G!Gd;x=L=e_ASE zQj)}6Hk*Kcr2ABsI-PZ?BhX;i{a>@Bl3r+2q=hHU=lw^oEXCtOtRsv7&8wCs;Qru0 zq@Sn*{lB#W4J<~AxB9qrn9WrNv|sgc>CYRv@*8ThpCO2IaA; zD&B;DKCMrper?cX_D)WVek){m#vYgrwIw_Poi}AnfJYr3VWC4!j>yut?nyeJO1Os$ z<-Ouv=iBDC-C{`O@b>1ZZYGrSkL2Ej_GgHvS;5Kw0C}-_$yf94maTWqaDb6e1rib| zs^XYa7ZOx{sHFgE^nJRgZ)C7rK83ULEc>5uRMl>s&rpNWCSN?sR$`0&O+6JMiU`2q zM;HT-VJ*%?yWAvb6HTmOM;P=(!2PDDtbq3a0A{_|xmLz4+FuiWx@Nk&f8w6vj^C25 zm0v0WOmsYLjjdIKS+x*7z78z-FiikxK|R>g>dnup_T%N4WSMI?_j@x&DcPwF^Q<&6+5b=37> zbku-p)CvkZyrx2j4U46cw=b2iq{U;g(HPdIt0$1Dj*5zf1kV(4&rw%0#ypIQtbI(P z+}BFRid~q}rh!2?sUw9>I!|QQ zYB}mDYGW`}K`f9}#9B6Jrl*mkmM3^#NSwtYmAbPp91=P9b0BEhk%brrJpb!WkOYoi+_eY)OBV7a%9EyQjJBhNVp{GA4Q!qPjwSmuj+%YP8bw@x$0 zqBbj^O+Zxn42+J9{{X;Wmz&Gs#GPxpyEk)gF2wkt`N~eb>>7-cRpj^Y#a#YUFR{fw zUO8=9lImQ=BSlq6{IxuBJTYpLAhQ5B-deNf3+KGGgj@3*V3NER;e5qBq#w@}!KlE` zcD=E>brf@3$av9}UW`DYA&E-jwFLZKZAH~N97bQit8%+vD?^#vdzWrD zQx}@V)yH3n%;PdxdJK&wS07sgJT+8Rkrk00O^82(?j^E`;O0w+8A`AW7#=kMR==OG zP#*HdxjNb9T1c`C91%t$pJ?IH!m5#!vn_(1QA9`3BC{(qo^7ao53w|agHR|22S7-a z99Fyu`%ge8cXuww>K&z&&u+}EJuFzdDKaqAOCgSYw2I3bQR9@G)m6NX0>-BN>NXc3 zHOxEi-LhEAb9pGDuAn^Ho=fU$z<-meU)v9CIiuW;V6xfye#PCUlt#`4RuDlYMBi0$6^*&YHC=lRv$^_im250V{^~E zM&Gx2_np#x#`&1kk`S8cTH$`$d|s!n==*2w_RH;$DeXM5x5F7QMhwoYr^S|oQ=TV2 zK$Ag59TR=wz9{hKs*Z}fIOdOBQp%Q^K`B%J00GY$q>PVKKLY#@Voj5m=e-cmac)d! zARG#ROXPfj&#zJ~&g*RgI!NG32c=DEaski!uj)854#&LRT9}?P zLJATA^YZ@ySEoz&4YJ32v691avW{z6BPvzEWh%mjNc8g_oO-+Ohd<5tH;bDC)jujr z*JJ6|8HT|2?kNp|^I4K=GDrav#i8L1|LO>x!lZBESC{ewjg zXJu}T4(Z3#LbI)I7bgXMIY}fT3(EtTQJK?71cu_^So@HY>KT_*5-WpDf(|~>*Esi% zROTL9o$Pn*p61T!7_Nz9WNLw&FsY?;kI$$2s+goVVHDCxjVyOyNPvDywT-p^085L1 zukUU}1#)=)-isrN!0jX`G&uAB0E+0ZVQ47(N3}D%n!b4}cDBT7Y;Gc-OEeQ?sT)>_ z8P?{R>Q$y7+`g5+7WNoe({S9SxRjG^4itG*f0DWAad#w}Cdp}K5(U4yt2y%ue$P5% z<(hOLZYn9Im8B5+rjJsp2Gku1a7jz^TM-(FGax4KDQRYVq*M}Y-w2p&}-p|itat&RT+!N*<%+2CRj8MRTPliJym#H9G zgV}9zK>814ch>SF>UPy%<^)T;_{@E-Um;I5EXa^d7w$Z) zV`@y7l1g}*J6&#GKp&89dHN4xYj}k4$1+f>3jY9~sdX<>NYR1g{%_^bQM)AaVnnrO zNo2)LX=E;J6($9k{*|$fG?8#UCj9g5LPL|JXRWm0=_R=I23KTiU0o8O2=s@BSdHXE z69$#0iL|8AT|q3iYagNZ>RaIICcd3DEyDv@bK@s+=n52yP708ex%q|ou}UN-;^I`lc8Gel&HBo<(jANO3b>W=bS z)|6X~UypTYSZ0*#Np^&RsDG>czMXnRkz6{X)g->DUs9`}B#8*&Lo|vm0T&-nueSU$ z4Jp&2N{WL~_SdYG;+l5}b&6>0=^{iDNh1u`jGNirN2J_<8vJ{yL!4u$1A;)VdUg9h zEMTCGUsC-A5NSs51;Mo6x3{t(8!TUVNjpEnl9`#JA-nJ zqx&{-f5`XXF_G51>5h@r7-%8$D@drz!C7Gp2yjY*>dMO?zZST+zXc-z=cbsTIU`q0 zGh=F&J{_e}?HDkGnmed2RQ~{J7%3m@J?sz&Iy!8Mu3n?|kM(-=#Vs^MmGEm&ePu`t zSP#=;6p%mI`%;oP&bl8ilQeOiLq$R3(;|6UPg-?>urfE0 z8EOHL+&e_7{yqQ<4xm9I_Xmr6aBeCzkc&a{^XZ1MB(j!ZPs=pw4A@B0HPT6PLm-|8 zBI<3ZI*lY;a6PDw{h5t^ACdn6CrrJhVL%*yW6$mX04G>R0U8xzsPZ(oxrR&gZAC?_ z%un_AbGWc_DnfU-HicA1%3cs^3kQ>^?1YiJG-{Eg>3(&!c4O)7Ne%kcU z(Ul`B`wf4=PO+{sVpd?#AvtG0|JQ=0DHXMYMsQtSB?U z{{VuXT{X>1Q5=rZ&2aiiP_hsRA*=~sQ)o6kU)sc)CO{c7KF{@W=^U}htV+H;1%K3f z#?)qL*tjN8->H&Y1E)~A8Ux0n-|T(ZPoaQQ*-w}IG(A_rE~ilLug|PB)C_^6u{S!+ z<8=(g+#9sMpbFRn`S*El0U^IGBmCV`C>!BWLF2>ypV`#WjcLeRB3zH6BzncQ6XbOy zFtPstU)u)gMk|y1O+PN57R=(975;rV_);ZDGdnX4B~UV}NJ#-TXdr3-01JP-drPgH zvV;`*`g-x{Mu8rZ&UGJ71pdr*!KnaZ8(*LYW2NL8fg}rnIk^7-SbMOVqN16{km{xp zT-O=(>NM2!@@ZiSxnkC2JdiF5+te<8qv~z#*yWLG3*w%=Qb^-stPu4a=sqLjxoN-! znImN+SZTS}=>pald%!rtHxA-&IEb${{T0iO|#M)N#vOGL!h^|bXD3Go^$5+>-r~f2M{fF)LE=Bb)=q5qW=ISrzfm#vsp0m4!2bX~ zg5BjoONq}q&{M}tPf-+8Jv>B3PP59a%<-ow3~eVmR0Ras06mJXEY1G_E+yQAnd4>^ z;%E*B?5O>nbNk-Q4ZmaeSAW{}%P8&ap5ESdL;+AdsrscN5h`kCRRbb|wfigT ze`j3QT8cSi$`Pt20xGo%7227|X4e{{M(NC1+gTIZ9iPYZCglW8aXYC5z>h_9N1 z$3CAi>Co%jzHy(E`GVVWk;&R8q*p34`efngKNL;g4;pF%CY=d*ESgcyBb9`d6=6i5 z+Kd*nLsFxVK;qTlEV5Jq=U4Y5PXRL09Ja>&941nbY+w^tbh=};*2V;51|BS z%o_E2{{RgC0GKY?O{l*a{%2KH?rx>7qkKPK_clU;UD>$0o|d%@Jx0#onAS2^b{|M( z5<}&u)h15}%x9xAMXH&E5IAu{2ClYk82Q_OcI(DWW-24+3f_m1asFsam}! zifNJ90H?@RO~RJ5`9V@dipXv`{{SCjJ6O=FQF3wq$55U3jRcZKAR*M$k58Y>Q-@I2 zXv%>j`Vg55AJj#GZ78=VSM?&^%mupwN-uH6JcsAeW6lUwb5$AqzRsZ3SEHfOp`-=M zGhKXYIRQfH4DZJm`h9(wL1N0oQSHS?uiNMc_;_?(HP~T52CksTGwHkd;!t&%oGSxn zX(N!6bvg*)ewRMX{+)GDRGL!1l?eR(dM+~%r&RzRUuU0A0;f`~ndCB+0>A?9z_B{` zxA>2s1Kx$OQhPuH{2yofje7H35(Y`HO!*45M<6$;Lq%Azx4KPXK3u8 zk%OPMofcf&h5T6<`#ya)<1@9Gy7aE1ESd(EhC)_4h}O)>AVO{}%Acy9N3#pfn%ef& zt*$ajsA0uVkp%w$KO@yPz5e%SzDw&S;ew~(b@NsqKO^LLb!(p+{&CgeX=rd8;%cqQ zx2fTZ7q-HNgA&a$TZvZx_v#t{Kv^}XEU?H5<+nxAEy5RZ=-*! zJbKO#YJTunR@U%X-pc!i%Blx~%s#HzdPdEOVjqPYfWolgF301S$S$JKK~+61VcqzO zsKm(@-^pR&-MeEU;?wt4J9jq7lYtraD$hkIx9!vqWR@^}1dNw(F;612!QoL{AKItq z)=JNRW9|){H++}OHs4sE+C?sqWsYc;Xi15~taC#s zXy<_G0g-`LUJb?lqmk&q(}Dj0SKHLT6}XZ%h_e97R;p-4MJfo&pF$}^k<(M;p?sp` za&%DE!6j*`uEx?Z#6eRNxsqx+R-=yC$X`~J@hzfJWfu05Nr#KBMAW2`K<)g6IDTCi zC4`af;>yD9qLm{Gk}&a@5lS-$Kd49@#f?cdJp~*4a8%(ocI2z4kqq-;=f?$eWSUH} z3{r(%LedtjymmT+TiQ!^Z>fw1#dGLrDtavU66PJZka@QG#T;3@ar&7q2!b^S6(ytq z0g`xhJM|{@>y5vYsiWT1Sef>Q`P$T7f7zJ4y(ip5lG~mk4Lp^wA~IHtMMR~&Hp1JOS>`*pbQys-w-mIiC9cof6|8d!+cUNc$& ztPLO^#uSdMZ~02^x{r^)BD-thzhLhl;=4nw_GJCB@zZfvNi|g2UXR^2Z{RUkqtqOs z+V#~j#ZMY8uNRX|)l>inGTB3MbGP$!F@*7v;4lJ^8;daKF+S(*(vH>zS_E6UK*UnGI;?&Su_~Z zXK0>jbfR(fYoDR_5byl+w(XIrGXA5slu$)Y4J*e3=6HGZDfYYW?adtRzQwjd5_o9I z;>y+V^ z^loejBzu3Bwi&ls{-St^wXdI<^(TP?)AH(6yuTK4yEpc%Fbxl%6YKKyShzP1FO2RVoBKejE+*M{qG)V#lJ!C0?p zk+4Kd=m!@g;RFGbj3WEc{o<3^?TL1+fJY}k-^9%baj9+M%A1)*MOwIp4MQ+2-J><# zjLl|qo7*!{nabocbq93dL6WwvYJwNReKD)CNaGB6RRKrfd(DeYn`_#vY;CsPz8D}_ z%>p8?pPdCs^(2yf`r`KG&0NdPJO2PPZamAs-d|rm)OC5Kc@Oqy024(Xil8X+0CoS? z*U#ej&T5{unohdyufNUgid>6QZQaWf{pMF`)4M9iM_mhEe3lBIQ7NYLz&HVrSYqGa zH|~QUK3rb&zqZ~DuQj+YacbR>UN;i)uet6L9 ze480q?XOm^J&GDqIalJE*?$QYk|Bi*v;yO>Tc2(33{@U?YG$zej|Wf+#gyCi@K#gH zBSr~|X(5q}GsIa-#`;PV$R7D&y>j;b%G;IB&&-=m&5rFE?uz0zjexHZ7!68urIw)i z6W3w+W16{doHnTUzE$6?w+*UFX_grlSnI}wsXAJiD!?${M@fyzf=ZWav;)cd!9^@$ zy{xEID#)@Gxdy}heXiQ~28l#0dpLc+Z>2qYkoN1}(^yHN91VE?06)v1yCscTmPjgM z62@dUZ8rN_kSqvO>Rng2(#P1k*65*GB6>AH-j|^SO%&8e1LS=V`n>vqf!;l-)OB<@ zjRpImg!6u>eesa0vD{*?Ep=WR+pKXv%?#;Qg8Z z065P;UUTGLTjslAYs|X^rTlHFe_AwVP~Jg^Bvzb32j^am&fWfP-!Jx_Gb@MPS#7!4 z4N*YUlo`zCFYNNvD-6v3K=@arrjS{J4N!*CyfyjvA=&d??6Kslxd3EjSLP@W?CTUa z-?|U9H#>||SZ$X(dZdMnaLHKT08oi_u=T?pJUZE<;&xLjndseH|tO5Is*^x%XRa+xD(|-}YUm zW|M8PxOie_HDVEpo*uNXr>CbvCt~E~$L#&Vm8Oy4l9q|$hHybKJwpmm{x%4&Xyzmf ziyv+75>ncE5r`pi{tklML@M|8us8=(RFAVimPbWLZ{cWmyqhKph~|;=H8~82@dZ9O zr>OGy=;`M=^!Tai^p&_K=ZhQMDI7urZU{9bn)><{nF=gK>XHGdFx4FtD)UNB()I*j*goUAyfrx|sVi$lf*CJmG*tu-^8VZb z(IoFYJ|bPkRguI|%~6ZO!5#)`niy7SnwuRIa8l$dA&6b!lCVm^+?&0JC)xJJa9yUe z*FZA0{(rZRLanmp;UJ6k|=BglwdxGk_k8Vm%(`0lB9#g^sDL;MG9C}xEw##{-e`WwZj<}mR}m&nLvnC zQ>v>e4pT@3F+Qt+NBEz5@C?jGPCq`k$l(ueII@m+chmMKK?q_R`gs4XI)El%K@ zEi+Tv>FF1Y5$ZPlA89UamfAlR$Po`;^?!q-jgr>)m^UkZpJ}#vw;5WBt4#XpJQYBx zC9no-)O4Yisw(`<@tCM+k_p(urW%RTu3-f{Q6OdpuCi%W0qF?X?k0*}YI*6W_qD~p6p#CTCYmz2{^ zqD3@{@NN_wIFrD#C;x zFl*HKvT#O?;;Lt`^+lydmvX8d)Yx0_ZZGxrw82A>(p9`h6xCn#Q?7DlLPsQyOP2+T zqPC($jTuH#Oiq6`765)dv|uzf9(`P0D6M#P3F@hJvVFW}9~oU*14hy}t5k^hP-*Y@ z9+7`-h$?vFt^G_@BADr(xYEiNc$lVz(Hq9*Gj}!&AsTc%nz=sp;WcOn`iEXKN5;7S z09Th#jS{2?keKF?&ZhgZqE%7>(Hk-;4Z$F=y}i04D~29jF{m{Pwrl6ocD8}k8D^rg zsbGw)bRy=?92*mF>(9GJwD?KW)g)%1B}YspR5Gj+pksX?g9*7dYwHn}BHWR|w;tXo z2ql)iG#-EjVPEi`qAS(tc>}wvvo4^C`>3U(8a+4DF&lT>Z3&{Jx)5J$tVoP zi3Yx$Kh@{dM3!4Ia;8h!wJ(i4On3{f;@p0#j(V4t())G07%e?#aX6&}5Dh73i@wS|a2-(A6n#40|@ z9+6450l+&ty3td`F#C4Ox4Lw zZECS1sUwn)-FSB#Wpfrqt*! z^&E#bAb*GF+wogSa8%O1hy0y2Eb5@?6(DrSJzl*AHi!nhE14HjwZ+t^Ba{B$+W6tq zs4z7iROq%zwbMx%{k=jm5vx?H7fUM@DtH#SAhFe}`g>3m8c_{v(#Z&`!EK4h!@;;<N7m-v-n4^A z%wT|hIP~4r#m{SzQR~B|N$QHdGu*NfXD-hZ1V85_vmk9u!;K@G^Y!+=I6+xQ;_{|* zMI}m|YjeT5HXiCA3dI2- zg)8PO^8Wx~ z#wMYz$-M59OeAV)l9L^FcM(q$M&tNv*!Her*g1MD+d1RblH3+^QBcD}6QrvGtSB-m(C2~p^)~B| zA%p%E_tetUy&YTO@%Z@hxXD_`i9T_PQHr{G2yYZ`EQ&`zL+(Dj_e1vt_Is>%z7@ha zbnzX_$OcU!__VObrV6ILNxPpT@=gBFeX&ij+AWR5CNd+16rdu3m4ehVnlhhIE71$x zdna-AUh~`?XS?XyhdZ`vnPC!o;;qI?e6*ER&Ul)hNSR$N{_Ai*vOvmf4f|>5J%?%M zUSF6=wO^%8IHaQvj69ecf;`A4fgNKHxA&L3J;v|tw*LPB?&D};A!2{Gvt#;Brn%54 zDddcx{3e2aI0mMIu9`(Snv7JL3L;C%EiFzvz?s|}gk8+|zc1WJeqN20{+9uCHzNrq zI8gOCZM&#amiH!$PS*7G2kid<2ieiG`0Mi1vOYaL*nCWpZtk$lR83L1I=??VPqu4b zwjoblk;6qQ)Kg({^_0GeWJt_4XadwEiUqB6Y_||3I*3$a%R@~h@gvf_O(|2JIq3&9 zayG}!6}p-ghj`JXTq2ES20}^x{Es+R_-b^KQ`0BOZ-{+0@&jyUJImpOveD+T@JpKP ze~sY;d#7t7gDyiovM}o;jg-M8tj|3iBTEX4wJ<^ZKE!;z%-0qZC6@35A;QXdA3(?O zx1%0De!XDdyFSQn8*!H6J2Hl+OUKAXZmb1zI)%m4OTa2i(zQ*7r#qupMC66!=f2Kg;LV81A;0n`H9aUM`0m2smNt zEB+5I2c~*zsLbZXGofU>vL6`M04?GAf~vodX76mmF^U764CCj~3S6&T( zJgDw9e%(AEdcm*<=uVsRc=o!|$jHitMl#2ww-T##^0y#G% zY9HbKeV(iuXk(_H1Lyv)UWwXj*H<36PUD>|VWbnt0RXoFNGDOhx8je6q5jWF<(v3U zf7Sk@)D)g*W)np$kV>3KB0I$*a7~n}D=0tH>Frxvq|q4UjaoCr5C}aqmr}tZ%LL4l zjtr!NKEgB7#)Gmqb~wd687K2XP(>ofu+&{_V*darrSMei4`MxBpJC~_A7GiAO|wQ$ zYOcbcU?h*_(8kl;?ryR0fUah0b%eCEIa|^B0pmv48nlKJP{ZQ;G zw5=EsTclZVkZtA7Z7nYn2kgaT}rFL8#Bn zbT&`DKPSVd#pONPr;R)Yr{$~@^XnZJ@T~3~&qpO41k@V~Yg9v&ooX3gr!km8uN0L{ z8E6tXrC&0{rL>6d#F9OwyH(rm-mhD!1qaD|&-p9!>0c@HUghuq06lG=N3}_5?PkMp zw=)SSWV^gh>r|GVpd*hMM77co7bS@3+H}4@W^Ucpo7kJ;mYSBIf9<@M2M5?yGhf5~HZQHjbukxlt`$J1S&w80?xz zwAD!M43zZ{OBvBoslvPd*ScSF-#hZGtOBx#bGdJ?iYG*v*tis(wPU~X@JeA$ZT{yBGB-P}kn?bXn$)D)4Jrh*T` z%0m(ANvh6!!NwYx^urVoCj)X|0RSuzss5J*TILATG;j3JFSJ%h@S`~2; z+U0y+s-0#}NRg$m1x<(?`&YI?Zd%^mPGlm#pTkOdQ#t5$Wv51|4O32|XO-x*kCENVkM{W-!4|x^JTT4iGt)A6Mnpac{{WfZP zd6W5dAM>91YqD*d=P=($7Q)KjNu9XTIMA`hb3ix_JUXde^j~T-q!)i%8TYN;MEEsm@)EJjwo4>*v4Ro_E~6 z!sdQr=FQS~c`n_IVTo-Jtwd3Z@CcO0txpru4{Tri+nKlkw(7u(kFWd%Hufr(D#2)f zpx@!@C$e+<%a|+2>SO-^t7otO*V9I@+b5PBagdhZ;79-qf3f#43v2>MLx`ur74-iA z0O>)pdy}(zZ**aEU2VIvdupbua77M6k_iPyA1ephMobx8MMk;``1k;8O+)ZUuopjj zSIBt+l4w9jWa|~oKr0%jQxh5qoL;@`@ildw7b>5?d|t9Ty68oFcPAj zP)q{wng*?9WzX!15{^dIAy=BG1Cf-|$zgUr zDumQ{3O(R=J%4xgu##KPZ8^!J6g0NK1;-33TtqbwL9RBZ634EO`(OR!*Y@#S+WVu) zelySmb+@oqBDB=@(;YY&?3HWey&L_T@=N2dXV*bTf$V+1NtUgn`?SGlWjkvsVI&5B z7F0tIl^k16w$=FlrxLlZ*k5}21}S9TIUe#$DB6a5arIGswTDsD=UpP6eRLDs@4er! z-1+pDn-945DZ0wKg}vD}vs2NMZ6dYC802E3p&ebfkMNeZ&KT@?y|eGSjLUO*(Zo)CN4NFQkb0A`&5cI&SLaI?58*&Bj> z!;hDjMPq8ki{Jf!jl|VS6$aqio{B|^aP`qGHQ_Zc6aMjx%I_6Gu(7cM;Cl;4;aypx zlS!i(&UpU-#n++T+fBD_a?F6WtobzPhk+v!w>q>Bt+ecNPP1LK8W=@$R!Vqn2Dkq8G&g z&8QlRdaFwyxf=LCL+wq0HnJqTe^Rylzv8-0eYrE;$1E@U5uAL_pZSN&syOUw45r)8 zXZG%EUOzLpvo*9;PLZT>+LmMwHADoKXx#_t7XcfBKnL8VZK7zSXw6ZDK=b^MM@@7Y z7HZHMWO^T7fqdjN)dCi(aZg`UAC=~YH!#$+1Zt=gG80VGablKN)9px&<19v3=6}^% zeEMnb5U&h-uaRA)UhxP5I;9{3Y%&P?9{b zYtuha-K#LA4i6l3pO$KslB#%R2Ax`O8&fi+O-0#51&ompwu=%-Byb0}gb2!ju5nuM zALZ%4t7T~%aQSgRZSmU_?i!$9?k4YSX?vH8-pcSX51J&cb zG^@80f#^Erk<2tkC7tfN42Kc`q1AaMllx85D@-L%|dQl@89kkUGMh`A);G>ZAtfao22xW;en>>U210_8}< zF->TmygbJmbXmSo?QYT8i9x?Mp5)6^?P_?Ehc~vu_@cx?G@&S~UYg}=DXW3eDNsaq zTiIIv=D%dOen{pQy5(*E0A_%1QZ~3}IWmwtkT(=$;<@grrdOyp-2Km-tnMuNtClxO zW3aYRvqXdx3=U-?oybWF!TuV0aIcNkyLSfd&C8q549!Bth%J`M&Q59Tp0U@M`LA{6oy_jr#EbRC z6)K1oNEOpixTpq|uK)*^NveF#LN`BqLk&c9@icn1snpi<#==BaK+fmr-m8DD?9Hts zATqrepY}Q?TiHL+5EUQseRl@!g_3n?C8WBU36LYh9ISM)N4A$K^|Nuu_k>2(b% zA3tI0>A6Lu>nx|s%vb%6o+z`}l%|?&hEfA3jK&nHh4nM5E5r~HA(G$VFMn-GWg^i` zEC=oB`0rt5X7QA@KF{@kpR9HD6oxuwjb)TC?lLJ1?1XFbM=~<2Do4lG{{Zh^)2uZo zG{>Jx9(o0)Ps{yYoj28G<82aCSF#BYjMLPkdeMG`i>WF?*nNMmKHrYqor*^^8Wx=4x-d%YD9KjA#bEQPZJ7&#Av)k6h^-nKkR+q>1yBX9<*-=0*%M#)C0K{ zW--^(MMg_`B;5GQxJVQun8iMMrFhfl>DNu0jYEF;Xy+Qs zr=5&SK(d3U(`(#+QSZXRjXzF|xS^(c(_W&2OoXF)R|EW=FM6k|yHCG&_Ajk^Q)KS` z&EI)(s*7#y95ne##ivrDTHJ(@y3^xvu-pkMYF;QKzb$?}ueIAJo`{yfl7H1qe%~)z zbXB@8T`J*rLmp2AJf$We5#uGJeeV*X2Xj zJ@Z$;_I9(+Wy*VdTuVSaX{xb< zdt@Wa0C4FnJoU~tj76t2U#@Zt&eg3vn4dw89ai6e{{X^xzm~Um!Bn)d+vC+@e6#Cn2pYDghizk1 zZ}#>Q8bH!BRqS`FtEb$Q=?%$~7g02=W2&717b>4*o;KAEW2vnHGzX1EYmZT1v#GC@ z{p#hd{{T(4=UW}X(t<{;WQ+i^fB@sc!23^H>DNPDjh4F^n4qe|W^ol#P*!8|v{KS! zakcS2iRtTTD-6x=O0*e;&%(28v*`B~D1;QT+IIEiJ;y2x_jd1r84%G30Ch z&rQ^|^iiaeJyNW)GDHZ{9F=l_Esmv9UgP`^_ z?;-RFOoi?Qg+MWYZ7dS`0dnBA3Jq=>*w9w5!GF{M?m z9jqO70tfj1eXSPpGJ;mBcu@Ht+2w*dNv>sMRw0KPikgpK&o%2fWJPIenVE`8{wWKu zsjL=4K-7Zgfxxl+`=uF(NI(LhRDXl#)4-}LG@M8#pXK>~E|&Xeuk-t#8Ijx+@TEN+ z9R%+j(kndKDPThX0BcF=0fbsE7>i!RoBJ<*Yuh$G*2`?3Ld`UR7z_kg#-{zeJuB3` z$iC2XuQ+Tw&pK_eh-@rv-dNp%)p0CCUxyI>j+*K?27@)jy#-g^(bLqQ*CJYBYiXV` zW0^=lL*!C_*!!*Zv9r6lwj&DI`#6u~PO|%zci6d`mo|O&HU+LAQsdG=+ammkaDUku z=t;zQGnh&7b(U`mcr|cc5Z$S#U(Tr8i~j(Hy_oG+(%H=o%tyX6k^D>M585&I^nc78 zv9E;?X1N}1UQ-(bpuYg;(8Be{k9U;7{V4zyx;yGQm zlOy>zeK>`s%IsL{l&q9dRz#+@0UO5B%8sDipLo~zx#b(R*{!|I<;!N45u!QBIJPwc zJF=V{p&}VI2GXTiiVmU=VY%OQ(v_{vDK74)?c>|Kerq@s!}wM-6D)gqV&#!*m`B&=Z)>5!Q9Jcj=9 z1KFQ#xu4yxVcact`=>V1x|_Sn!;=z`Tvray!Xc>CQK+gZ)Tz&Y>}=aNY@5;XzGzNve4?MB7z&nmYn?5}k-oQ_^bnnLXI5CL@tiy5E> zh!j)PCi%{`Jl%gR5Z>GASb{AT5EI!UHE9v5Rkag>X-rXNuy@2%UU(`4 ze+{damGTfqiBVIC$y4h%{N^=eDkkwPj-?3+SxF?2KkD?M-1gbF`TRMmSBkLU!~BGK zjv)S3&OS}&Evub&l-+jYqGY1a4MAvRBmOjvlN<1L{*sZ<&rZ0hMI{P7B_=%AnDMpP z_4}Bi``22!yc~qONmUtvp0f`mgWG%mOdot0u zEpFcqcp70x$oYABQyFu{W;ZuoZt6_l*v?Of+`DHYwOC!ngQ{d@c$hskZ4FF%MD!KV z5Lz|`C5?(mzo>gKDIAO5fTY}|V_J$l)zDEa$By^6B zttD46IZ)0#k`fl;+C4Y=0Jr}DVeCXLOl3nQXfQvYK@)NqHj_-}rs}$_QYb)Jpe0Kw zA$ilOOCDIC^||(CZEO_|tXKK`xo$RyX?2T9Nwk5bK5=Y>N*bLYa%5MLDeWgK^zDtqp|R7;*6WqS&1Z#jx+%uu93n5l6?BLV;li&I+sR06$9JgN6g_vU^2#kbFEcPMskLRu+gjv}fo5ww*9=sojD zsZw=Tzdv8|`t>*NJ6`9r-8GKuw@qtyyi!zTYJ7tMQS%iaKA)mi*J8}0f>>}Zf7PUL zK)Cni6(AlR7m_Gx)D7YBkEA|9?9Ic4?jEn&JJ{stYH-xqjJ6(`w+5wi zvDTzLb+)pdOHeLG!j)!BE^bOG$(9;yt~4vf>T%;L zZ^*t*Zg*>TmK%&_w)4QOzJnQB`h&-ZT^0MJ?psa&0Jj&rb)JRXZFeaea0t}?FjkII zJv6C~zNmOsog2=X8z&!-*;}x0?501oXgfm{L66xfx2rK&$abXI>EvDcLE48V_?ivP zip>b(ro+`^=BKQ7K|G&s^CKa$lFcQxnBB7O0_8wj6aY0d0tDSFp^_*Bv36H!$5bpk}XXo!c4M60WmL#5QCB4xIBLBd?xIo z+uM6TUk^)nhh6sO&3XXX?Do~!+ZR2$wl;PQMQTkd<70|yWW+{TO^t?3eF8}H(bO$D zzU^r?;kj)WR;-ZTN32Y0R0!eyK_?37G1MqNOp)hFrY>GxTkXEwdy}y5cGKK#Z#}Kv z-B2Zeth#l!mfoWVW|$V8m-|;+o2n{J5s-oWO_{2?XJzLSY3k|r&cKHTD_Wu6Ca5*F zxopi7Q^<)gpBEG{K;?zQUfg@etvv@TK0)Ka@s@n+w8^yRhelNOXADGiqr){ICp2F6m^swES5JBhuQBNHI0IltF$5?H#_z(Dc z4Ou_?vfoL_`l$Z^>e=i6(9<@tuae7HeR5M?12N@^o`V6d>}{{ZXxn&bVj9?(dFhoh@! zIurd~eI*T>a>u9!)3s-@;`bFPVh`Yh?F6bsBq^tN`43G*LEKQ0{{Rt>_uQ-OCV42Tf~t$Ev}FE0<5x5N()NjB`p!n?8SQQm z)nK{(Sd9i0N}x!Y^I-Jz>o>Uv`@=c5((c~R+}>EWzpy$(T-nwM*Ew?w7K!LT3Y4ue zPPdN!Pd(AK`}5%5#>(u>)LW%CUT1LZyojcbc=B`^OnqWiwH{)H%S#1trpQLh!&1tv zaKzu(6*+5|xnkZepP2UMhjNG<0vs~b>2zhNWnsYJ`haoN6YtMAa&I{MoxAgQChme= zlW|C;t0|15_+UJ2i~&|w85JO4s}&&iWYg_k)l)q{rQ2Ehh++h+qKaiQYXO?f;y+lE z>Gd`jzqD^*e2imLY|^@-ga1$KO1+oNe_{A$K_v6imz$>XWmggZt~gq{NB~c z%r~%M;w#VqnooWiV{y8k71q9miHKvOSr8iiMY3Er>Qs?=y%K9 z@v>aJJ5|QvZE^_;gIW@5Kv6~@ALaAvr@PC)J8x}&5ZlqzW~*wU(-hKf8qBU1f=F~O zxgn&QiiWnWT-!jGLa-OLxiAj(?rPg!OSi{wbEq99-5plGR6-Sq`I=ODb)Ej$ecU#F zW3;v2x1H+VJ9b)#ZG1VT>d9(`YMB3)}O_&-s4NvQop??`y2%XeHSi z>*qYul4@!&jT(?CL5>xzdP`IMsrg^G+B(@c#$t7(RxcKF4~DLQhluDBm7|SjmqKb9 zq)~oF&#_&%Fx$y0guhoOfCPV(R+am6)3<)f`$K&jLfo4SI_cdT%!dZJJ|P0Wc;SwL zZqn^7*V)^Fx5n+;^f_yUz)+uR8r$JGeHS~vRMjA9%vT6Xcje)BPzFyUflbT zd4HX4t(9ypm`aMr;UmOc@Cr^xpAqNOKh2+Y{k+9A{ENRdQvgVU&`O{%^Bv0G zS?C?ht#r|@xFd~aVy+-EwJk(QSd!6z&5eJqmA;$Xn|qY3Z!9-Rey4A`Sz{iQ1QIwA z$M%4F#I9oH?qTIS_S-p&YL?RKxYR1H0r-)HRe|+VM@&&>q=8Zzh@)^Kwz(2UPaFC~ z5~O0m5HBSC2)Op7T8288kNUHoh??}M3n0P&00&6?x7kuv`Do@pXHZ;JEh^nwM!@5Bk5=<=2hTl+jqJ;Y!#2 zo{kp5!@~36sAYyBNTQ0CNs5=&<)V^VZ5U|*YKasewT-{P`@{Zg++=s%uNFh&v&i6j z4A5s7P-~vM1+Z5_&7_=RaHf zgR{$LcI*9Qu>eX386!AZ#{;O0NC2R0jx_5Hecj|)c@uXR+i5M!H*y~g)c%X{@Lv?+ zn9t%B99JM7H!TdYRLK;xs|O}u^K-x@Cc%~BQq~%Ufw>>j-sPF>SZNHSAGV!Ea9;u* zjA`e>oi|iusUCUh=AIWwp3|5bEg-S5M-m9k(rW~epnxy=_d#PN0|X$EkNB~}t2OFZ zL0~}R!k_H*hB@fWPxg_jG-2fXgBe)o(%{Ifj!bP44{i_R-kuYciiY#c;%xI)WB9B#lS?x3=2I$AGx`jurm^ReEu6i;9<_ z`5rX?09PKFG8J-9P4_}Mnq4X#9bL$$1V-?Q=~%Ne6RzZQ?bu-nAc)gOXht){8Xwu! zW|*>gfSTf<=Nu_f`+91Ys<0wM_HR&ZS(8-m?`wqQXwf2%s+$jQBrr2Gc;S6GW7pRo zF`k<1Y&Vi_ZX;tO5&9w7=5BtZzM{5z+NeSaj z{#YGaOQ{qkVjfjLZg~FysC5&$dhSEm? zPvuYY^x3}GA}L)!oY$~xq4N3DCon8)+91aQ3C7SHmfVCl^TPAADuqmnB!i9oYl?NJgH(Q znS!Kj{#dWp@4>JiQSCzojg%k&kTJx6v!BbP zi>heZq^l?=G@;L@<^B$xp@RCF-?+n>3V`Ye04l2Ag|&y~-`Cp6<1JE0f3Mrb4=*E6Qh(yU&YaSig^xknQJnY5kyuTM`huu8j2n1fuBfUEQN9uoHR37G;E#i;dazfLweJX z+x~u}eoyx&dgXRYS>=13nv^j!We2QmYE=IKN8vtz=dYZ%%a4d3AU+KCzDuOOK=s95 z)ZBRg04-)0HymwMwR;P0{mj(xZjGs%P}G@>O<0Jq(IB3cziwnl1$~swYQjS!+!{9l z{63Wb0E*ActgzYl{kM9sj_+t?mfIC0;;)*>IEG(O%v5w)TD=}G7+9SfNkjp!2_nE; zzP&4NsK5Kiw4&LS^^!vlC)fO)9Q{%i(g0;V2dAg}UraSp$@eK3dWl<7C6P3$Apvz* zfC>}E{-WN@Vnpznw5S>L^Zx)pNMvc6P^wvuK3sZP{bB$3~(6#09TmlTx|$ZrZv^}oc{ouBL}WEh1nLWI(cPjO8vv6VHB&~ zWBtf=>k+WIx#su!U)`Vz7{t$m33yU45}--n)hx zDwvu&3PoCsl!8eaL?cLek;o`#lUN09$J6udiw27<6 z!_{r$^BLcM*JZcZj zFzXPxYTWW)KJ$OKvv%$CNZ0li;A4>ftZU`kazOJ}^}<^NTlP69U5%le{GM;<7D58C z{{VtXW9&l%=#Y9GbuVqVA5V6S$FaLl=fM6)rKWO&B$H#e7T>F=#_oN$S5KD02JvSbr^f& z?d9J4X=%@#uCBc0v@WVg@!VUZYbYs`GzPLm=EGEfiFz%)@7g_w+g*c_-(8EClOvO^ zikg<12t2T3s3_>8iY1`MViX#~R3ikxsI~Tzhp$m})xw~nf-Cc>A8K zKb9$}B?m;t8BVkytg*2?a&HUnJ3Z#u?j?+v0r;s(e3)@l{Jjrd9pqnf`E#DFt=7in zW8GN+Yj!z5(uIa4O5_no9&6@T_+7_6JxfQDnn|FYuJXAo^zxsqmim-)%a6$=zPI*Y z9mbQSp3bHXw)L%?!#O??Kkp~jo}RzAp@(nevbapPFL3SbwRRgbiK>esh|OXu-jcq8 zsxzu8syet>GBuAsRb{wfRFUo1aYD4HBcUv|_V=($ZFL$woQgvRp;D)fYl>4f^5fBz z%FWiFI3?Use3r|}wYxT5v$nQ}SN7I31x}k)DmL_)XRoU59CZzXc*|36^Fcs3S~ER9Qm!_1eo+qt=GXt8nPaupd2i>gpj(^AP%QB@&r zAt6d}A&{${K)t^<_AndX&X$*ZlkSiui~yM(oGPFhs}>@a96yzMj+d1=o^8`_*zL9( zsdsy(0vKbBq>@5SD2jlV&mT`djNZ)nfxR;@E?a$Mq1f0p2;!BHSMCb3q60V{v{m$D)@u7<_XOwuWmq>) zb2n)De`Yj30s%eqgXB~n3Ik6jXL{hGk$ z5h|?71i@)=l(I6j>tS@)Vm^c3CiBm|+|AA2D(`&5{wS5z6}y-%)K;`QPN|qwEh=kF z9zAr6+K;<0wLaHGvT~;?B%6y7{xx>1b8Hfz_bBUp(M2*78V)O}Ql2vAKLt4UC3@$9Bg2a7(zRiX0 z#LQR{0nGp$KWFXo=@_&{016U5WSo7U%b`=NyKAvJM{-i`UcTH_m@I@vTBjVwX>i$^ zVs$+pTMPA)o`({O1f$uIQblm5Jg8@Cwy7&Y#+%UxW{iANK+Y|qMP_e_1o0$W|Iq^h82=SN#wMW zV{#CYQA+RiLRGy;eV6zi9KIRh#2-=X*E4cVy|Dx<@Xr;^U~&m4Sd($PrajErqy@yC0cbM*El+hJx9smWqLXRlBm z?{J!?bre*u?dqn#o0syv-#vkpljh&WOhaY+j{$|3K!&51F;`|Xbp_NV!9IN)jRAG|xqwj9@O zx>!y6H47p!J{-}LSB6?}Q%a-pjp)M!gRj=d-T0mFh8bK(o+AwMQRMN}k-a`o3zVi{ zwOH(pI|P!Rs+K`(kTq~cj{%+X+T(4w`g?)#Wk}$|$f^GTQ5|+alDY4feZ|;e<}O*e z*KBblZBG{6>6qqUBm6D!y3v%7dK|I)(|6LfZB$!}ENU_s*zt9;$yW2tQ;vqJ8uXzp zIgkiis+~(O(Z$uStiXpS-S5!OR_*H~W;Qj+LTXmOI%m)J^!?Vsv0RH-r`n(}!#J52 zK+>{+R6RXFCZ3!?s2z8)ApZbH9hctyHBA*YKHuGO?Y{2nxzJsi1uN_ix^ zNlS#zR7p-1n^8~=&nMhB_lekJ+$H2MaAHR9jjgU&Q1`&5NQoXy%d0=p9(_T7cRj{U zi<$ZN+dJ7b$7g!?R?AHIY~^K9Oi(yRrOJHD6d#vH=*FM3q^?(r>=nql+z3stZYYosZ7`sJ zv#&Y*OK)En{GBPNix^_kKmy=!-%%sn@%iW3Y`=@6t9Ck2d32Z-8{C)-=8n?xZbJw`PX@k{km)NRVKD-MKpVJ zYfzY@Et}pOlB6y#Zen3Te{y*PNZy#y-_!0i=6%k`X?ME5xCt0hPc~!dtHhu69)@<; z5nII4&m|WhpU8c^Zdvf}{u3GTZ?2=k?{Aqoy1$Ygi3z8#sMwgAtcKU=j6F@flH%&A z>12a(@AzVt!KJL0l9o+2`%tkGt)`X8&~5bu zdqaP?Bx?2l0D1@fJsj-Z#mpSJaSh)u@7K0BF`BDe&m=`p9B5!T z{JJ4MmHe*$D({A>uG?E;x2y9t5lE>~v#QHsM9m{h9J6h#pWRRtjojH_YIAR+3lDIQ zHT~SZzvejQZM|+byTT5Zfy*F2IHahjkyT`<#Yb6L$$x%7eK}-7ZN2XB@0)UwRl7hZ z(f|Ytn6$l3IJl5kh&Ae;K0|*jp4RB04`iv08JXSv*%l3v*=?wev(lG}r*3UQVaHK)v}Wf?lU=s&c7 ze7|lz(Rem{tFPR=+R6gk-n?lHt;0+=IE~nog<~6$!AZweFS~lmhaDzMGqLLb0El98 zDotM5jzd>K9f4(=8Kl4PjJ&q>2T+nkRzn;=7#5>$WSSm(|?WKdf z0Bc-UwF8Lx^^Zc~i6tA#gna&8GRZWuXcSY&Q1Vnu49O8Ez{G+-$y-c7vj#eW1OQ1M z?AGg2&ZG(hpY!##x_u!P!8If7{{S~g*=h1A6;$$=<6|V1A9D>t2jRp~saVqSO)CrB z4LWQ+tkDaY(LpK&DNozS)1>}9vFnhK4Qo;Szrod|^z9Pl_SWCeQ~2kRXfSiDxeU(H znrLT?6&$IT>PZCHpU=K{^Yn(pd)_vwYN{rkXgspSAKCVfyGP2qoLk2va@OL~YFmx6 z2Gz!-!la+H8iVs4ST|SAB%PJLYM(@jO^DgJxua_t18B-rmNo(fjReBVE_9En`uoOi zZAD&H*kM|N^W4Y}m--t0wKU1~^y)q5C{Z>Iu@KRoS)37Hkf*IpIO8U`;n1J4vDC@4 z=g0XU&56usvHopdNg*G`DkTb}JG@amQmE5@2jbqsT)}lKZ*kn|8YY4lrvQIVN1z0P z4t;tF^Bv5qzd<^!Vw&0sD0nyN0iRL`Ip{at*vF#E#gp;O*v5@<+lVAg)H11K}nDTW5sQxkY=wGs4_|~6H9e%4; zs6ju8M{){zFsTBWZi4RH>1saN*%iAtI}+1FUk8OrNa|jOss&_=Cr%intxY9Famb7u z2Ly(=KE@o8&(}PY%r@Kp*&%6SYVj%^PE2jbwUn}vOk$KHqV8tf_D*ovw|-pRX!chs zX!Oi)@kZd)zdn|W(%=BVfPH-b0OGv5YeEe|PT3cxjdTV3sGG{@ z*Fr>qwZ)E*O@;X24{jL0Ovm7AZWj6!_;`r(k3r7a{ChA$k7;3Uk=DO=sc z9YFs8wBPIfJ=QyQ2fixf)2m5x%qp{RKk7X;irJy6W{^cB!kvQ|ATbpZk>rtzS|^p1 zlp~u1YkhtB?9rn-3jwRh*M|xYAbI@y^mi<>ex(Tte+?;KB>7j%tZ`LUNg^21qwU0& z4zetBfK;*~TF64&`mK9?eYYjDBCssJEjUu6^Yi?=yjL#Fq$%*dYeW98pHS*&s74aU zLvJq$<(^3l%o|PIE2FCe{v6)^^pK$i9&Q|H0H@i4I=f9Ep-6IgRMxch;nQ@hTOSfa zplh2_M?0)>g$GjE{EM!~f%W6t>L720&1g8Nss8{5K7BTPaHCQRRQ@b*{PXhYe)ysB zr?EaH zZl|G&k8E|u7M7zSk^6LyH@kOjay!><{l!@eC*NgrwP?~ekT-%o5k^FDs*OkC%YWf& z1H%E0KZx+)K+oCMD{~g{xbCoA@0Wm?Zlp1&Bo#=Knvp>SidTptrly(b-b9Siu_B(* zIt7uv4;-8VfGvU(ZV&i-I#G|qlY`WMBPewMzi2q(2=)2=$4-z#S10XKy9nd7K#ew+ zNpd`MT$>BskM#clZS6`$D}J10`hCA){{Rn2W|rMQQgs^6e$E_6_&$HPshJt@n^O~8 zozK_?lrjP{$u7lpWWP_WYI&AUVyfr;x0uaAI~_?Q+1EG+@Hy| zLv`ov!a446M0IT;v)HH(sZY#`0yB=M()@1iyuz(c?Cv_K>Lk$9QBzdsvT&9PH6*eo zOBV|Z@#tF-&*$2x{l4aVx=XrqSrQr&p{0<1XHt*Z(nwVus${LhR7X@LsHO5N!xH0bCa;GgA`I94#F!$09Fy(q z&6l0IZUnp9ce8VE5G9klBDfwKY79MdT6y%w-^`xd^L^9UZ+yD8cT<%MCujkwpVUC5 z3BVN;B=G59*1saLJEC|nyQT^C6O^uHL&>Yh<@J z(9Gkgs+Kg|cnr2BCw!(OClv9`3kdwGvRRQzun0}HNvqVKFXRUbd3xl0`pezFnt6Ku z3ww(l(%(ypsAr>B%n*G2LEwKbtCKNJk=t4Nyk>rqw+WZV)c7)3jLjuxD=|S*i>6p> zXmT)9RZ~i)z{eshTk+4e-%RfTkHR(Kz*G5jwQf;lSyELfb5MBv!QgsfuE@bGftpzF zsIsCPJ+zH1x)qDL99WwX^!BFS(nL};8dJ~xpD&+G++8EJb&A)^{f|H8*Q3foNYf7$ z(7=l;G6i!JN#wEy1UHcIO5fG~w>vgc&LcYL!HqMD(wX}{eqDH7#R-y$RVph{npU{` zf5X>b#cCu}k>q5BLzONH)JSz*E}x(cAc9BN`d^QC77-z33Jc?h!aZ}xrcM0KM`j^F zKWX&G5A|^BzWnGsBdUTbh_BAb#l=y7R&-%PieJ{~0X01u3M(~0?4)1Z5_dh__4 z6}3=Oy){G)D9Fjn|0370(3wkPJAxV4N@_6K0{^d&thUO6Q5<&dPK5BhGXI%N+tuD69mbbY; z9B?DyV0bd0Fnw#%Vrg`Ve364IehXcUfPwVjk@Wg~ZS49OYokkcf0Ll((`ADSw@$ci z%bUanT4{gD1L}HOlqQ(4xx8UY$qO~_tqQgO06yEj*tXrsFu05vNT#93^R650H60mj z{MWtm{ISco-Ll4ws4YkU`l$pmADR_EK89>3ZN>y~R+%9-3KFpzvY9}&*(zW#)~){l z1;SN>{i z9<}Ir+5M9yMPkKKtTSWk9oDL7Ya^aYSR+v-LQpb=aXYEzHvm}Netm#0_8IwMjn?L@ z!9D~kR;+NPtBoLv;F^)vP3+$8N$*zL+= z?G_te*S1-0J2kq)wp&E8#)I&piVFIYdzhbzi9UTBDqhFyz0b8VT?^hgT3zMWyRR^{ zIC>PELA!ePyZq)`d2Bq9@>FA^qo-YUbc6P)g}@r`bR4@b@wC0}<7ilIa47K@f>dfW zR5apP@CV@loOKTSv&$T@%oiI*(=?I)09^=KZU0 z1+9UC^4zG@_QZi8N{Xb3q%a_g=@qEx73(dnhTM28e`e+8qs>8AO%7KPNsMNEeFZK? zKldMvqh^gn`Br11p@0k~)R!7hyf5bc&vDuJOU_WWjqT=*%u=+U8?qkx8#s^6Jc?1X zQP)R#TJLY>jk{~+3k#K>Z@Y38p)dO z@Zxc0(KrCe!ZlD@QSMmUttGiKTw5UarPf?_OZM3 z9m@ugm5wwTq?$?=Awi%N9}^M+)K`e=<@zt-KTmYTFxOS$se1={NTI5CPVC3hR!2)C zDw*NJVq{5aG4%dx+1N`tA6NW)5WJ3iHBo&$vDZJn!T0B#IpRmRwYq(?WCYS1cV%Z4 z!J1JUl_0LR5%=o-%yIawr4V zpwm5Gc4xPGSEBKeX1klSI`gb?G;}QzR_~3?j=;5DN<_}hkEE=fE9>P*;&Kw6IT^^( zptYCWov`g!ca9d;&7~-y9V$+K-Wcni8>3uYYFl-Yo!YcfTzVfN{!Xj!xWC~+zX$sM znyVAkG(ElFnRwEAHOY0}(3=mo=%$vQvN4mU+*^ItU@7A}s8+3M7 z+gvw6qagmGf{j2GlQqH5&w=YJ{g{hl<<0H6pO|^?bmhD2X<-p6Slmek)GJ>e81NenUS^KnmpY6{wv0h#0UApRG!jUAvN;Mh*;kZZDkx@$gx*hwc7Afhz z26sg=m@8j#?oW@qs!-Dm^Ab10NrjMlz#D>2I(4*mv@5Q#XczSAp?a*1eIV-dx31w zbf5VJG^?1Vq6ifrfDrm51bKsrOSYW_qyTgEAJg6^dup*{Z z#sM^H=g4_~ld3iOQ&Ak9<3$QPvr_fBNrP(Avb}9v`ZW?Xn9BV)KKh&YZnt>-x1Lu} z7ER5{(wPBJXY;QfxO4aYyM|x9RfV)J#o*9=oz;Q=0Ni_zW)7plw?EK7;pjPN z$M=T!L!YQm_~GmS(k1l2@RZNyEtQ79C;k5b_{&9CQz5FR#!tU@OtQ#jcGU~j((I|J zVtBv@RoM;rKE(&#K3PW4Ew0G(Iv4(f=tR~s#AxJnNB&Cx0K$0x0Gj^*KvGd|dcTeG z_RiVGWd8pEBbDf#&xh=~nkqP{ogSurxkDu$>k%r)sF6a!Lkrm41AV*Po>AQyqD{-e zl#UXqO8)@1%Krd9l1K=W07e9v{hd@EQwg8inQG0ox^OwYuemU@$w!&n+m91ngU({A z(nb$Wki_Jmrmmxy55uC9_~Y25pB6QmF8Eu6DFh#|ijIygnMgxUj-T?;{#-rL{LDU6 z;`)26VW`{tD+{+Nvc1LIRap6|@Eu>X>M{Z|SyI6bJ!a?42xNy5j%HV@s0EIgW0pk) zbB{Axa;DPvmx8wp#6=xwWNLoUql-6?`H(u?ZKnNLsVns4eq`W(hxT>#I{0Jov!K2O z^nTvxZ;yLfaC>hR9CbT`aaXN9M)B-D%+VrbH-7ib#}ra!GdTxeN)0shk!gkmNYpR9 zLEiVh!cWD*S^2+zr)|U_g?yczW)FZ_@}+~uDkyLWAEL2 zuI@$bNVp^GYlHaz09gC>M-IJ8`E^zQ05ZRp2V3{-Sx&&|iSeB$-pw6E&6&l~nthYL z>Lzb2l)K{xLZT?DsvUhf8d$ul=Tx!HZ*b?h9?WvjIzc4x+DC7?YSmD*jzj9oJ{CFe zN)z~lb((&_{qniX+X-yBbDoU*@3+8(3hk=$%|M_w(z)+N{{VbS)S#qqA6lUHUeew@ zKiWC|p!pNEGCKn^S5y2CdQxR0`;1jZO=C10cXr|`qF)V86D|eg$WosJwufM>miLIf z!^wN+D@!%KtS9%*-h4=S1)sv_LAG~7G(uLJ)p})}-e-f|=T8xww!ZSxY(niT7l1cXQ#PF=CW@@@%3}#eD z(n$n>En#nC)weH)T}RTS@bo^OePi2Q>B2Bo&!GLI%>MwBrpnxebnqFW@YKBVEROLT zfp#YC7}l~%e!9O;KaXxLp>_ixgHQDysMnfQ;2QqV+106hTbfF)q1l!2tipPuB^(Jn zeg$C$W#NZ~DR@Az7dQU^Veg#2`a>1Jxct*B349VWEZ5N7=AQhd7W=dnA4+mEsw ziFbGop<>Hc0;OYl6-fDM01uGr#X7GE9Y)~nOrk+2mXkY*#giMesh)!YMp^ULE@WTwtyDXV{WHGM=H$XYey>G<{>+$4@&vzK>9rfu2~ zD_XQtGT_trNGG87=Oj~X{H?q&QCnAl3f8R*te7N!3kE+vrJP)FO<9V`g{q~kSt6BP ztnx!&8=0Y7*}^LeU+M`S*!s4SAiT6XCX9k9z!W$>pXceHu4!YpzOp(dh=M7=6e5Sx zq<-F#SZV4Zp~zyZrkCzE&0Aq6o5K{cR?{p?CMLc~B_zugMFg=13(1l*^&{EU^l`n# zwdJ}G4(&WpDnM4PBtQoO95pNWSa7dLm&p{jR@b)C4-V}-P%1!HC-qPPz=sV=@C{C= zi}|5!*zonAQ;7I>DC(k<+gY>-fG(Sdt>53bqgUpYS6Iz z4y8s>^QTpnPnx2qQF>4$;w@C>YI!74b#|zd&0<^C>K6oCk9mbA-#eT=SB_|ZVE+I& zSm7Sy3IW+e@~Hi%`Sjxs=b)6Iv8kwvbg9zuy$o|hEOM0->ZuFo5;eb7uFAhbZ)xP( zWSP9)Rccx`ysleXPvlS`T~j2w-<=F> zKA-VE(#sPwcw(6TjX3b7J$h3Vs;VBjK8CzF*RC&^rjB`GXx&7T#T-b*Co))vn4!L? zOKSe6{^~a3$gU3nNjxd(_Vn-XB8*qakO!T9%5eUDW|PGyg~OvH^0|k^#>EkShzQ|< zBUSnT0AuYbw`J5QXa;N2v2++NMouZ$QwYXBwqY*0VUAabX|sk4X;4TNLdPOp9ylae z`%WN#sEIfsBERIvt$I{$7wP7bx|{<~@{0KaI>7~1H1K#R~bJ zUHH{ZIJ&5?R5a5Vds?f#?tVv(QfRaV)Q=;jbTGpZUIB5Z>9#XFJQd z>3WlIRZB;=_T^0U`A71*QcYJwrcAzKrW65R_-eO;6k~HQ(%P@?9_Cw%&T{6sxo2;X zt&9v+jZTuwnIt3nBA^f1$E=RzyDh)l-bI_7cQ}LYH!-U&2B5F~luAzxcxEGj$@qFY zn_Ft_e!AO`VX$=6*qlZ_6g4$dG9Sk}NF|fE*umF3Pw(YlV<^8>F zEY)JOKs7TE3mzKeZ!&&-I1ZpK-+A7-vvzCC=^lIOScF9cg&aagqk@6xDtMZnp6D|e zjIG8qD~`w!uHufe3Wl^q2}oGon25=<8+uRI+PizpJGzToxTHD4uqPaF50{@s_j_*R zVMBXiG$S7xGK}!a6wjBhPF~alOpcLsQ~T?uXmTb^{{V(bDJv*xrhMfs6PiV00B;t$jG6dG$DEQ z4JQ7?oS%1dHrSBeU8L-TwU)mJkR*Zrd~^)=62{8ce3EM&zDs0~ooMvS*SM$z&>lXS z=vX7zt%Y;v&Gbmd09V=2gJ|bH^JZ$=UN?nbfr(}L zfDZtETsqN1`JjKoZN5x=F^6&X_r_|h&&jWjxQYogdCHnuI+yrqSY-bJ6n>Edn6YqJVMXn)Ea` zdYpnyYy7GFy?RjKX`3;f!Q%w-RK0dWmYoW#m9(?Ozo9_^RaE^2{{X9#s7P-mZ56gGl7V;;CbK07@z~ zfe?m}r;eRsLRZvea5Uc6zq|yp@18X03Qurl;&2dhY(&XAOqkWn~T`h7?c9 zR0`+pchfVJV!i9d1~5-uaZzNKn`%Y5kkN?@br?{si_z=sNgG4pGPZa;qjR*%h@>U%6PIg zQbCE@Rm)JC;Hsvn#Y<6>qn0+h%MD88G-)EmP5%Hs;O*-E?$2xGTf2E$D}`w;P^qC- zSpbcJ@++dX_4_)9IksajE%MBBDDdT3sFtd9~*0aCU@p%VaAnG zb?)s(-MwX%s75OIOodCNn2D$T4_Se&299oZ5F(KNvVHbz*uQlx{qy#}Z|2^?&6WgO z?lCX>`4m!Myh6;Ms=iru9}iH+AoBp^?qQpf_X*GL8_6}o$s<}aWs9ojD=xAoxnTOV6YvrMNb;3c^+q{$8InI z30WmQVf58Y;}FctcN1SLX}pXtia2T&3bQZF8Z5qtOZlFewJ~gah~=x*53yhPpG&9` zp@?Rh$?H&5sb{wb;*Z3O{S9>xe$MOKX%x**9+)RA^zxYX{f%Aq7+Y8BiO(TV>H^~qW8%(nrhQ~o;`9wJtrBJk8b8`tOd^?;uL0DC=c$y=NWY_0uJzh*Xak*L~D#jPZ7 z#Dn69lU9t=EQIt=bGX{vHAmZ5LF1Ldb&#g2c|c?Pl+z#8tDCR(PafsXs(XFLFB;lf zpurWR50fvIJ$(AYz3*+l*=~)s{2E;4PZeS6jph%hmr2$0PUVR|)V!qF5%mhDz;J)3 zu?nP7C{PF3Kg-Z{ot&1g53gL~XtnyJF3hCy=?i5yV0cv`{{Z9k_V$L;grKkO={q>i zYtY5hHRe3SQpAjJQ$tXIUc<=kMX?6LUQHDOy zK>K>hPrAP`9i!ZRuruj^+{IH`043E6)bImKsU(~Q$48$HOPh-<)O%ef%kIi58r-16 z;aF8vK|_y?X2?`m%#HTzPft&FmNhayg(QFhE04CEwJp>F`*x68Z5Z!-G5I2#=A2LS z>!bYR?{3ks?oGQ znVsQ~k4x1p+J^~7;^P&EQ|U;MAKZ{zS^9Cw40A611=X~BF3WCU*kUyc_~vi-!;P=WNs7MW*JX?!*`@gPN7lCp*lgk#K_8uT4f{K@K`&)jliC5tt)F?b4m z=2snAxR#AE)lWcVCTXRHW~!pDNCc>*v?k#j+wM1)FAP#7 z8vH~rL8L1vR!wva;eb`{B9-c7MM}n0 z*Wm=VIys*XK4<(9>b!2?&hBp3S`N(Il?_8#S()0qogu^RIvHL}Mh6*^IHN}KRLK~s ztdckV>E19)2!@$D4{G`L%V)B&U7Tq@sVG;DreY{-MyUuepzy0u3iXJ7^81}_?jJc^ z-&);QWVK%k*mqE-3rbXhrKD~+_(F~ySq>-Xx5E6|>!A51)oO}{MwcPD7Z$3Zus1mf zsq6-m{AD-tAWrPcZ=% zkk!fZTx9U% zS%Jyk!24;+2^5R6jl*$KnXaiIC(leY@KkZ2(!_a_(uOFKnl*wLlA0tQh+&Okjej1P z(N#y&`g>^i62#Q?G(jA8kfpt>OBK5CQ~?xyil71InpcNh%P}`3ll@rV{qFwtKsXMa zXJ<8bEPi?a01r$VZLhbph*v3yqN!pC6&@iKTzC4Is-n>}ZGX-EthT?sv^BQ5bsm+d zKWI2T0C}_8?{9hL7mu1bO3vb9C?*Nv+$YT@k4vfhYCc^fcNW|1b=$a&yR~~Sbhh5x zJCdJyZOx~c%E>-I2f3)>nw|{C4yIL+=&QUH5+i<;aOYL;?Q>mhyPOwxd)CbfisB}Y zMnnKQJ{es&5Pbal#(r=6vhz;SBs<5o{OfgdEwqayR(H}8=wtXi3%vI(LM(`@<){PG z6$i>5z-)#?4c?gS!{lZ$$3ex zQdvz!Ln|5;AP`3mkX4GyOHz)k2!Z~ff_*jzk^K$*%#hKFvJgkhJ!3u5F~urK3b0== zLE-c1gKc>Z@XKi*UDbj7eGh`d-=C+mCt5>qU*SLD=rwA8-H!F7@wiX;;p_j?-Ombq zafm@rNV4hGU=#(?pz~p;{jm20G1P1G>O{VTsRZ=9qLRuAn=t%>RDx~!AD{8}O3|u4 zdJJ4882WTT{&N2SD}ROG%qMMDV}3#P9vY{5{hL!@dy{C>(`~NW+Y+iuDJG%alrV~n ztraY@7it`W)ltoBG=D+`yB9TYI}5AWUN?bW=*g^Y_NnvviXWd%Lp+c*P~+3fpo8Ea z!JfMQRlO5~`17>hn=Oy6%vbIm+ugMontXn1vbTmpNewHE@^?#et z^d7mjlGa8^0r?UsU$l7<<~)y5i(35u0Ehe6yB6t+e7eHZfNg)R{BWeVT6NcvKrMey^}o=M_BJ5<*03{Pt)P+xJG$f~R=83)WK za`Id1Z~i0df8r0lhw?pZMR;|T5Jw;HzvF(~2D$08PmZ2QBAhHCmDyy!`5A)4Iq~%wKA1atdUV6JktZfE6P zznNiyr-?@40o4qd6hFYkWX9YWW|gSO>ma`Ge|S!5_7j=K<%2!fCf&%Q{>N8rs4!)Q zxQ^;IB*!48zwG3y9BDP!TXV9yA9_)BKX72`_J3#fzFBrA>!hf2Ee1}Gsgg=OzAqxN zEH$`HlvNN`(oChJmI{l47%=yRoXN>k?EB9%ZS!0Hlh$-!HDD?!oQ6*zz< zetG5Yd*$7un|V)hj_YH;h&*xuLQQnCy75^NhKUg691wVQpRl$~CUX$Kd5emrar)`E z9SV9HuMIoiyX~q2H1SVPq|4%2nyMHqkLb+Ps{u0Dg2P(fPriYBY3>Hk&s#FzK_qbQ5ei(u zSO$tpP_QSAENW4|+L|z@Tv7L%+Ad@EpPD7v?%9WAyR+&CHibMa}H2R9CcWH6!K~D4(BQl#gJu<(`Ch=5x3IB}1!IkR6b5oUwXiKp z;^psQf2x~qk^;whFanqb(GQ;t4j-REy~gnW08)06tQBIv zoj|4mkt1QmVt^A*Q&ZA|D}{;bqNpK*!puV`RtuuRTIS3b>IgR@*=?QktS=BFOAqk$ zQ(?I}+q@u+EI4rE{-Np7e9p@Bd+xdj2b5-ZbwrZF+K@d)6C)c&Y1hM~)U_Q$3zr-% z?e#w7t+@pJy>BFjh708Y`YfnxT>Lted3p6J?P@33Y}!+#L3${7&`O!rpM)^4=ha64 z05*Ky0-tB}q_vMxQ&&s5v%y*QF;%I+(a%{c$Pr)mDhvu4Zh)Wlz2`^VcW&Hf<}Ywk z6bo+lFw_rKoP-qNmDXrzdc|+OfrD@5{!y0ZFeh!oeF14ef+`clk&u-BdFqr5^s~iJ z4JBHixTl5HjH(G)9Hg}$xQ*gnZ>r?l!}_0n67VIB{YA;W ztVh$^?F6ERNKg$tYH{dKOpA!A`f@SNcz>Iz30sw=kj{xvfeWl^06@(pqE}}MQG$IK zxV?wAn%34;C`#v#odD0;K2+({y0}6aYmfM^E;RG6O}Pw~OiuE}1uW9A`)N!ng+%e2 zpCoRIR6I-t$mfr4!)Itv2a$sD74$xYdLQ!j=exMp7%GcIn-)T&Vr=VsV9~B3*0Vb ziWb>t4m086-?J(1MOa)YejmI<6U8P|~ipOVU4zT3|QK|J+W!B6mdUPV-Qb}qHI7W&n^soccBqT5j zyp31=T>X8BtP!4iwF&`G&*lDJfm_2QZ~&x<8NWJw{$8CeBXuk+ZWVww{B!I?k}jc6 z1E9OB1vTPFMK|NF9-0l?+IdQ*GG{-G)zVIqK`d`e6uI22l4z2ky+a9_6b9zND*k=O zJc9zqx^o@GrnkN!QYlIUBa_EDp!)?nojuvRknB92Yi=pGG(o`x5X40oTIub;Vnsbq zMvo(mq02)ZJ$ycRVwoxyGVX)R9m0}hWoBD3xV?xx`;u-g?e9@zxI)o}ttv)G*~EOh zg{-gcw&`ALIdn?ORGI^W$A~mPJ|oMZFR}W9Nn`%?b-ay(-B_7p$fh!$cY_<36o?t= z;fyznA73zz=0z5q-DLXQ12_It)TeXh)8KAV9YGY3kEh9hf$>`KZU?C^l)b=Ajak~)lH4gV|9o7YUt5iOC7?x z!BmFeFbuA&r}W&O^3M9a!MA-&N22mJ(JJ~kksl@=ya*$pzdG`<mUMGI)@` zsuMz|%Tk;YFhNu2(1TY?PhUw@Lso)XTH1N3Dq=hdAgGO^l`r_zjCuTfK9V@+j#wrY ziPWnPP(=^f&|2PkZEhgCfwa#Phg0avYCo9hh-}=1oo`*(xSI8!Uckr<<~|x3CYGF0 zRMw_0s&BV>DV})g#MJV%k^}p4NW)3DxHoN*dxrZu@kbPUm~KNnKGn0G=dq zQ;cL#;~hKuSJ8J~_wK#c8DdFPqpGs7Dpi$O5W>V2V93JXf(Sm^W$DP|WIB}Ob*Vq| zy8i%#>1?l)bX(`;XTp3QJ7av7f|j#!?_Q(ELrsg=-Qd);^_96g%rz`Zuw<8VawL ztdaPt2U;z3cUx{aJFg$Jw>}3axA!j6%vaIwUB8>h)KO({S$sV~q^-r}@zs&TRYO}z zQVO(kAYmXJTi93Kz1}^ilXrQw&`JU?ku}XlIQ;X&tm^x(^6}8f#iE z1%5`oztX23uB&A2#rxO67M;?!5kC}0F8m1Gdew+-WEF@_$i17q)<`}XL5o=bS@ zW|-&$*HtP$d}+h3&`hQ{Sx{6e`F_e%t99r-r7qms+j=~lA9W()VVR_p)@pJUDIP2Y2CNi->#iVwnx+NwVwIC}MteEYf!si(KKpGzyzspPBV zKGVXUy%_$y+i~M+H~nvxN1G?UvNd3RyONP6D;Y}?L?m4zB}jcYvVeHM*W6vq+oN4a z%aCXSIJWd(h-8^0Vof~ibLWrCsH>ZIX1b4+t-=8uTV!f`hDnk_Yfn7pnZ|lAUp@XU zW4=)QdCOp;hLV$e?T7yLY#hBpM8CuGbitvl#?Mz~c=1`9CNWfi!9y%^TJeMKS^Kj4 z(|7F0x>h@zyUELUgXyngQck#=D!ijY}2IUPqkmca)#YS|iH7o?K}o?>vd zL0%zUfKyD0gT!^Hb!Im?w)1(7ox8F1IDOZ)YpStXd}VSNs^h4lki{sGSPf4b0dhEX zD&pb2_WDQLcN;4XVAyVw<6ymsWrjpGQm!f}e22*78mY+Wf9;<-$;>t~>|5*T=DP}{ zs@Q22dwfcHusyN?=SSe!7P_mmGdlxwV)GOeMrWg1sy_{4iLv=yK30}oZgXtrsoWH+ z!e_BnGSbY92+<|Qh*BM~y=!@+VgaQ^4nrvvWMSs42?T$X4yG1MUEan`n{%&%^eE#E z9Ew9m>U^Fz0g=5$4i8VcifmO)MRZh@&e&?1rg}O$v*eZvIV3VcNi3Hv^HHM+{GV1U ztMl!2b2YT$YbRvVdrz1ihu0W25F2os)Ww?fh#?kEh*`0K%e;QO8dPQ=gb4>^*ZM-G6I$E=1k84VQD<-v0oUHS2Ibah?s()B69Tmv81b}Vqe-Aa? z!iu*WPl-7ENZ={?(BywS^^X(s2HSBfNoC9eJ5S+}3pgH?7(cLdq1*jAMI@0UMO&Jw zTOS&U3?q|o*{84o6ZK~!{g1R;hc<4^uJ1e+R^GTR{`A=WgQMPG_UCB4x{k|i+V6Lb z(3~V_#e9ds7$%;jjWe2Y=+X7hM^V;hF!Z~dAqL6Yl~we#`7E6!3gj{vx=G~mOOZJ0 za~iyKI{cC@zbB1bPpARzGTphx!Uin^OM84cGn1enwDJ6h=hj*BXWfIJcY9Z#dbhUN zwtXc1I)U|a(x*m+?TMR!GQJ5FQJ$>tX!PbQtMbqdmx!UkZmf-6JuU*KNxz9th3);H z3RTu@s@$DR$hi%h+dF2k*J0iDMO6)4337=hxVL%Uw=Lnr-rSZ^@UH}4v453LddeTSXzO)36`tnKQ$aCvR!6jzbW0KySlJxuu9`*NcwAVg#qX`FN+@=| z>8h)us=+gsso2}biA1@rom#JHW2LhitXz*{H4ErIxMcPbxIsYF?LW(@Z)v)p#Gh!~ zA70^Zp_Wf8h#Ltqo&~=IpnNh4{4TvWP*pTcg&pH~-Z^8ICwQiUSY2g?cxH)`NGF11 zS4UDA8AB-qU)e0tR)kaQKK@|iMLI^k@ih>RZBpe>D z8)jwt{{ZKITjMHwDvpaI-F*?dcAsPJ$_M*MayyzWxm`^TFS|C>A|Z9DZ5YkzNf0Pz zmMZpDN!-OD*zS{V7MFXiw3>HijHS|lzY&I!bf8ntf?z%wJMbL!g#7u)vGNxAw(W-4 zza-wzt8SKr{UyTH+ij8aKvz@PvwU#}wyAiNRY&~$=sv#cZrG`=+uaL=-1R>tvh^9g zrMqjlu3vBAHYZ}^rb@lhwJ7$zJvaAydR@^Qee_;=Jf=#SQX?OUb)8#t57TTHcl(Cv zEH<_g)>9l}M=@Xr{x04PL4Yc2&{t^NtnB&gW)bpbp7AaGtg+kON@9VhBM43vSeh~t za>TEvK!(Tock>f}?b>|K&G@^wGB^skYht6C4av0WX(yi_Jn+@Rg08X?1x!;@lpPJlJ-4F!H=d z&Et6y{1<Et%xW zGN!bMeko;eh!!LjcWR{+9Fx;l&+G5wQa0w6qxc@x&0?XUsl;I#s}#Gt9|cdGNtUIG zMPK0A3Yd~u>D<1hNZ5eF{?%Mw{W1%7{Y$iR!J3WXk|{+$#05bk%%3i#E?)LyXy^Uk zZRd@~&f3qC`~_H`w~e4T#x`&9myG`aV+7|hpe9CyAz}$6juBSAHRzKQMMDK9J))8d zH>8GYEif{&LoE}jrk)1VW{ra@i-rUfau;JRrjf~G=Uku9k6A+;R@T;$?YniVTW#o? zQ6d@wttmy*O+RQgu4`V7{x`e6I31T&S(od*p;x)-Qi_^AohMJGIg zymm2Ze43f{x=X_phm;B&dmZQM6=S@VLTYt*l>m7PG-TJ){5?ds9J}s0-BKHFWxP$j zwG%MD)DU?nic4pGRHZ3V!mq}qyLfg+-`sT-Pl4%9y4f_f6kaI5yV-8Tq_3i{W-R#{ zRsQ%%fq1lp5z|jYFhB@qW;(r_TiZbE;V{ol0URTMPIM<_PfL&;NzjnO(rXm z`+8BU1_6}aNVq@Y{{R*C@HOGm&bfU!Ab+s{{{X%F-(KU>eoGaN%+nf7tqnFpoPq>( zF$pwk7A7a+NL&0=gYD=pC$*4EZ!;tMgHPM*`Sd}|+^fr6D>?=0FsFla2RJdmVv#4u&Ik=aecQzyb#Wgi-^9-pZGGUUyD zB~%p{3VPXVG4-_yvQG=mSrnlb8ERpMMUmr;tgck8u0N-}LC@DVtfC9KNuVZGG+U&DeDD)~vpdeL#+}F>k z;^gg28g1Kh_@CLis4hodwuas2PktH$RN5!)57WtjE_v(9}UHhf)vebqDDzP3lwlBi(MT zE$^+Svbu~kEHhv5kC^iR05?i(FYflc$S>?=DRUX9Bl&~!BLs9<(tQgW!W?2_fFb9Fh4x;2RCft5U zv-Xtf3qgbY)03uTm~B(RlRqFoDH{vEiAOn^l##I zDIAMTRZZCdXHojJ-`IC?<|r(r7Pj!4oAdY+H2(lhbNe{@)1j8h$v2y%KVN%tEVhCE ziy)?<>VT0^=*EN6y$AK3)7u!Z)wy1c%14AxRHlxus#@rkZRB|jaL%U7dj^aSKEBGN z=1uM*WSf^9TYQPsJ!{ALj)W0%Pb%Ef8(wrnedS#mepDU5$*a(ru)9}gb~J2u_C@LP zQ6Q4H1Ck3#m!&Ff?cpv`vIKq%kuxa#>GpB8@0)h(i)pma=8c9F`FW3+{Q3;Fds1k!r*a=aaaAYLhuBX-ib_SUKBxVtgK|$c1TFoZD;(pXqec${)Y#-V=F9#D z-|q(ek7`lK#d=QYKHj8`M+f?SKR=(xw}GyDVB^cK{rjzT*Zc4H-(SbQ^}eb1`M>-F zq4{yrHC>Id@ooN{`gaGG$?f5erq^4(_M}m@ZeL~8EGj0d$y20nQ;Kg>r9fy@T5coW ze&v(ASgz+|6?a=vPyiK{F_uH>Mp->gSMgM4=iI074=1#|@SK&**V=u&-)BU2cB0u` zp2)70oGfli$8az->6GR?>M7NI%jDaXSnb=3$;pw&#ZiUG%TW|^PGz8|YAVR8M98lU zPJ%O>ae(K3aVOqIy_YdB09W;(ZK{-jM7N&9B?d0MPt^~$`2N0 zEpJXkiW` zZsGB=BsZdI*WEXme6Wf{70@Y!0B|UHQ$By-=}AdhjfyLbwnmt^ zj3iOWf;gG(7?C0uR3qqaFYK;sTc>(`9BoSHH9xS@y)2I6C0d!-AGe3?9YUQT(JMt- zvc&JLfeqwT{{U7>kf_e>W*me5KHrIC)Pe2Da53mlr_P*5O}mN`C93}btNcAT(obCk zjiAiwq&!NlSVyV6VpT`zq(NaOZ- zSEZiX!*3n!luS-GI*Qo!eZ2Kc9FbGUPb2>Tot|Ukge+(EHO=XdvTB`X{ zm03d_R)himKVM;X_bTQ&7C2t9v86(Y$Kky_crooEX3vuqR?jG|th>XKkP6IVp*DX+f z&t8^3*=Zbe2#|Q%SY!%RDW?xZ$F2H$g`occMq33bV5owYn`vO_>1pcSWUGRnEPN2t zM=Yw^8%!ZUBI4gbJ?6H;{wCA6$`tOx8j8u8sZn;4ww5WATdV4p1rajC9rc1yb)GDAn|(Psfi&LBOtYvXBZ$QS z7g`U%oIYP~P7uvz0R0F&0m(KWsQpFH1KOCMH0c!3_SAWQs{^2$ac!N+ zwln!n>#!(kGBw$#H0AK}CV@POq1tHV^D7sgMAkU;F>Vg8VVnKCaNDnLcYTs2l3ADa z6NOFcLwnpgus!6q@)KcYWf?2-`HA5uB@eY2f*o3{E}xjvThYgK$MIMDfh zhd*yk@4nY_7TUjAw#D_^Yf!62mZ8Y1`QwW%N7>M$QM@*#4K$VYJC_9&Ej$9UNrqO6 zO*Gm=tjip8JdUmi(_nQH0QMt&+iQgk@@_B)lxnWEIO9+Osrh>J3X7L_>xq)qEt=@e z?W6+}j_wpBfCW72anL96{qFF$?wkhB-(n7`9tBm7ky=Zd;D(MjC-dWwQF&m)3P@F5Qps?JtaH~jo(yM2^&pS zzV_WTY?UT2-L9gENewJOv~BL@-Mer6nI7F_o+4Y^EUZ5ei~?LJ;@|0gD?oU4pWkrb zc)4Sdz0*yvp0`nJX}H@PYiZvRB<#b(j#fC09+X!!0m_0vIG~Ncvp&ab*P}z?mZF4F zI;>+^lB#-oKNN`P%dJ$&sGdN#zH)Ax*_(KRtZ0&!&z6wQ_Hm{aPT}uSf+{WLkt{5LWf(ZWr2SErgXSbd! zxS#cr!vp74Adm2ML0`;|;Inpa%$vP>w-E97FImMt6MtYal{oA`{F&#c$8hF8y zr*vX4iyMFeYT7VUnH4Y7Ke|ueK{-!*Pi#5f_&2xv!wGDsk*Ky;7Y3#>#|v*Px`8zU z8EDv6Y8dm*&2~4W=Z;l#9_Upr)UWy?xT~!=F;)(xe;UrGyx5n*n5Q^DuoO?M5pO9=oy&^A%MN6+W}5s}or$ei=G^Tyg|fC#r(fD^)a zp*YmF$&HV~c!S#6856edbI21NT_^4fEiCSTSRY6vWBsxHl76F)>Fu~Bs0hbBOS@h9 zYFgYkf8i(35e*xr(i@D_qnR2W>MU{e2qNm^Yi)e^XaYr0~~3(CAgSGrDlkL!fSTSi==`X zllw#jWT{b>=^fbH3lR=f?gra*n6}GgvXr^(3(^W&ouR(*bLic>TDFiC@OW#S)zaKq z>1P03#^>3LJLc+uEKTN{cyu0qut-@CmVL2RJXa|R0Jc=ELB)U7{Qm&M z&;xkeCfYZ9d#e;v1>EJ3H8icuttEl0fezsqpa%9ooZEZ3u^Xdw;QInN>Tp}V zzl86TjZrGCbW$0yeSv{R{kFe&9{{WYx>%Ft; zw*9{EWMa40z4rR?RXBTTKcMUSZC{0zTZ(komBvjC5ydaTV>fH&B8V*D7$zK`P3_$&rCp`GZc3 z7ss02%Z}Z6&C}FbsW4sru&QdePQ}F5X{p0@t}d32U++I&Qd7vjDfcyg0Msw=iNn+G zJaf-Vg=&@<<~i8naXL-5v0d^VPKt7u2~PNb)0EZNdu3Xv?f?)cxG`;)8%@sF&Gtfm zLBCak>P796#o32}cFZy%Npv5mQXbA>9Hy}sWU?OZ>&~P3)A89W_L-Ay?Va;G*6pTvr))OoSxpRRtLzF2*f@;y_C>z8+0M|YoN-}Hgx0l zt)vIdL8@2cLaqE%#7)Z0a^#+9xIflA4H8FmgGjlAlk~fUBycQOMCzyXu2s9N#%}?N;=9K zm27mTG9{{%GAp>#?3%~gUP`vyBa$20-reLg$80H}#^$LCo-|hDpN9s6JqG!ocIH2E zH_JWSd=~ciQNtCT&C{_9s?`X4seJ0mLq(}~pix$!tevw-nayte#9OWm>eN?bDR)jr zqjtkqH#YQ>a5QyP`;#+1L;SJm@|5$5p^oJm7fxE_nL7Bz1)aNEvQb>3h{(|pTxd`+ zQNW%x2ZvKXux+z%d(Sa!n^mY@SG2Q6VJa`wU&`;K&v4Z`V#j5&_97JwS+x>7#S?`^ zEW}2O8ZG@1#)8QjAhIeT761+hvJ>+d>oBOy6ca@PfO!Bo06c&g0B{%`OG-*P>K|$5P98XHD47dtM@a1-$7U7zrXc7vH zmUlahq@oPq7Lu0>BxzL}hO>zlMgV#=pQ@`_V5nJbgSkFzzZ3DP(unx7L4 zyUTQCWXV#`Q4|tW&5y?}zbdN`g}sY^bnP(2X1r)oh`1= zw!Y^3do97Jbs@G_9&D78Tus1@QRaYBsWT+Wa_rBrFsTCx8j#_b%h)-cOO=7J)Ml2bejdd;G&l$ zwdAZ-4+VDF>>L5fZA#`)LH(M>Sr>*J`>3_t_DOtMtyxut4MwQk9w3obBhc3#T_nD~ z_PgHwob1*-%?$UjKaC4RCxN+GTra^qQAy$4!y=w4P%MI~;DgW;w6hbP#U9bmv>)CY z14CU+RRz|UabezdShAF&z(rD}O4LLy6~Q3ef$8kx@T0x62k9B8N1Siwr__H5^Bj6f z$~@=1#k=kv*>n7edE(O0%?;8GFz%Ls5H6z>9vtcL-9h+VGcRrj|JB^f4_9UY^KwVx z-(RTaz}wzFD;l?@dY?BNd>)wgzH`Oio38;(NvEsY7@VD2qcKSG6zv_I$3Nu;36y<6 z32R^2Ue@48&HI&_e`faT$Ney;^P&BnIlfr6le}q(BSO29qNbY-jkHgyiy>T+HGN@%R$%W= zAd*<^=w@}|-ohJ(`z@Z!EyQ&CvcXoLgrAA1eJDusspw(0@|C{h%`jR@tai|bN2$ZA zkP#|8jY68{igVM~Ol&3Ddu}|1e~PnrZe(1ZdnG!TtWjL6QkcZ3koiPW1`Q>M@=C;? zp!WAK?cYIWCYp_XH*>M$M$Vd?{l2GG2GpSuX_(_#{U4d8_(U#at+xu z1IoX{s{+1*&)1|6%3Q*`Vculh>9>W{O;om@;?c%~%<%&>r$J|Ub>fO8?5&ee{2zO5 zSyLlXJ|#svWvC)$^T|;JVOCnYG3zV=GefN!{8*Qm_Mzd8-)>J1{u8K_^8<+^)N!wv zs67e!BbXVcZd=}D@wSVlD56a0W5Gc`g}4BI7NJ^Kp_gE9I&JHrPqmq6ZO*2|Z~bt>AH;^C}c>CML+3w=esodZ%dwkyzl#YG^BALZ1qyg&d`YmxQ1 z3NQKQ;{O2cy}TZRmCs53nT}X>Bvm2c@PEURVa>t%5pU>yx+DjW9+@yO&zD&PhZh79 z{vYG@I_Gj;kwORJ3$B=p?MFs*?IC>EK;&Ap+&B2LJ*|HXmPf zl2nE{CY7|tfRcRx>Buc*y_zdac#F>?X;mI%{{VyLe1>|YU7!4_J}vgAc=m^W!LYKF zyI-+)&O>-bh1~VC9j!~3tzHgG==7cLAZ5A3Wj;4 z*QBZiU(;1~)2mP>y;&C7_+9a9YGXfy*l}%f-HtelgBqf?T>SK=^95Os) z`bz_+@O_MJc`KG}qF9E{3xFwBMd9`U2Uy>_{osA)-R{lp&$#=#OPXoBpA{6KCPH|0 zTf5i!PJBApnkJ_Msn)zu^{xlV{{WA@sqn+Mwl`GvHc%*KQ61W z13lDZEk>#Qv-#K4^5}wg)^3At?7qtFiscYt@pyc#dYR{81lUclK~V5b1g@-<{{Y3S z7E3V$P<7zkd&wS3+V3~6VdY*-w5#9GaU6JDiEbT13;L-uv12Kwy$_hoO*-M%*~v*veZa;GI%CZjxXMKcey zpo_>u8hR>aSdd(BFYoA2mN_GA0oj=k3Y+)KXFbNPYlUX48>gskjNLCkti2%P!se5-r4$h zAjc$SWLz9m_IO=GY01sK#X9#D8MT#i`>u~pEWMEZaP!Wb=cwSAt)W9kt zbS&e5ryBZs{(W!9sMe-{{{X8#T?k!M*L%aXcZEJ18yt~ipwm;B$f7gHMM7rMfeNp# zu50OyZOusWc3T!O z?6A@9?kR|(t`$u)Bk)n_R`Q{?zPssf4Lvs7+VQm(E*FlIA(};5o}!@o%_Th31xKkD zEi8oThvlCKD;7&R?I9{#AVd^5=xa?GQnMfgur!6((lA3}!V;&hYQ!K+NRW#Ewknlw_ERJF*^3;Oz zPaG##su+AlN#|3K@b_;T;wfVWy2!w-KnDPyLTg{MqeFRh4Do<_^ojy%0-Py7Gg{|> z=#>1?@4UA`>^vnV-D*$o$6!>~J|=3Fj#+S6Y;0(1GBMLQBh0c$kwdI9i5Rm3qyvzj zci(KSJhv@$^r6xK9BbA({p7v&y!NA(tZlh*kn=_R zv@p9-mJ~$>dyNMUz_O%u8bdWrX+yea^3m_u`|ILwPj4!Wie&QH9=F-~YO1p`)qU+v zMk1buu(ec9&`VcKk)n9&QB^!r-s&|Ed4IP50EpjjTP%td?I$5thu}C$SI|&=y!ztL zxLbQkcV)dTT06xh+aDcEF*F0>B#?akxKpF=m3pcO24Uz1+tv%YPT4z^hUn8*@R8;RoktL9Uo6w1 zE}ttEbtN54N@I>{SSLl40U$EQ9K|36*_D`%KDPEFNyO2^A}tW8Bl8?O15LNdX>oH5 zjj7f~Q%)E(sQkKcil^`xsq$&Dunsuj8{GYG#~$57zvnaAUG@aubGr8JHD!2GvE^x=Ony&6 zJVy1DtdBA%`UwMtKTl*^moDsk+nF~j6?yaC30M5e@%dC9g?m3Yb5|_K;OyI*Ev`RF zfOx_63fw+=NUxabCqwbCtD=%A9PVn!U@8`hUBfa`unC~WF{FkHsbXaU>*P>v$o5+g zx7@g_tis{YeiJDR`RM?W>MASI&DXoU=IY45NgI*z2x{MG)Wt#cG(8TOj7B4G^+t!*u=pi65zbc)@0DvA&GN%JP8^%~#b z-|n|kUhY?NO?LcQ%}?3#1IP*i<(}?{{JQlz^~cxo{eAmauU@BEWYSc%l<~+so((s_dF<_WMhERpzNA$zdRKV)pF|${$M=Tz?ru-!yFLE^W`@(jO(b=^O?r`|gI z-QHA>lewztTb=eRV;Oy2*LGjJqL#}WBM|aihri+J?1Bs z_O4f%o`b@jF-(=1oKuIz()7XUb8bqhCie`(NwDPG>Fhcr%8KKlpqDBuiu3|*ii&Nq zxvMgj%EuYGBQ(?KSXb?{R1lV;msw=e`5HwrGaeMi3ost!U7|U6ZKexLaz3uq>J_ha zPJ4wjgl^zG>p(h|HW;Vg_FHQ!MgscDwJmGi3!d>z;y3RD%rOcNR6p|f`C|5eb#4CF z`K$38VJ_j>I|YSTXl-Oo2I7)j900EIV~T))P2%9 zmz}qcLYI{}`qpVIEJ~%V)Xn<3NCZID%XnYtZ(5@Mlhmz5UGC2B%f8F=rzqZ7?~7~B zyMShz&4AJ2kO+B-nnbq-so}7$sy}HNquLtS>*>;>AW^TTScyJJCSTPXa2QyNgKkH> zh`Y3w%Hg1pWMm&E9z=ha(BrI_W? zW2)t8r^C_81d(CB;hBu_;x!t0p7v;?QaG^oT_i_O4!3C?%y!Wwt&WQs$dp~uow*3-7#j;KfyOcd`~<`BA{6v`P0 z{3MXK(n)FIsZ#2}zY^&LX&)n8j*x!mw;RCTW0pji!tu0V{+sJ%J|hp~T{H*K@UD6l zx~C^eRhvzrkjk7Cd!n+5cFygFrD&@*4`flwvg}RaN0TmxA4MK*Vx-BEbbW;FHN3RY zk*%#mTrHHdcu6ZRi8vT$2lVBykPV4FP}ho%i8;C%t+v^ByIUi4_Hj9y+M0#sp;PrX zr4AX|I=mn7)d}!O{U08)@0II4{x|OK$5QRyvF}a7olo-bW@G$SbiG&dCua)NOWV6n znuAp|Gp~UJ%{KT3kjyh5rDw1ITjeBj&H^lJ`HnM8UNR}4{h1!D0%Wsd= zeYemZ)7KapTqOqT+=`pa8J3Qw3LIU2{@ZUslEQ9Gj#@jw^p$j&xYes$S{gze>P`uE z*?TVAx>~itB_k#_13iYIh4lut6yww(1%Z1-@$np$Pnx`vV*P>o>ZFe6LUR1iTJ zr&{s%zW%Jr_x3+@?~dZ@-q+q4eXF*%Ugz9hKes2v^_JF`9Zb0VR^F32UmPj9>+rPn z&_ru#(V%1_Q|Uutg^ty4XS6ooVP_;zqr9q;zNwm~tigDwH71A8=5lZBw(+p?Up3lK zdA&~8dw~{C$r6hwb&%0Cw+!9ytOZpIMbuf&o(d@Gbb4Ow%5CTRVs=A^IIvRPZ>gpX~rlqGtB=r+HvO^LMUPn9u`99co3JWs;y*DJW z!yJ=J;bKrpB+vjoN$J8}jogm2zCWk;RZLXmtkNV)k&+?;78BE9O>DHs)(8$k^#Dcv zv~FxvsC%`~5B4k22J75Cy52^O(kO*!4ASWY`BICdgXBY>^7VqFY<313AvW#V8Qr-X zsC8_H3pGa?#OBxKaMKy{HDX)zGm?7&z(LgDH`rsfwa1s+W=<(34fx zGI##=xo@#woJxVDYA`+psXsQ zmm+d~hlZ-1k&yUKV{h*G)_|xQ!x}jh5qlC9eWJRy3YASoeJF?d70>PHC%x?nX=>72 z37#6|G+Iap&%>4juhO0%P2$!Nh0o^wa-P0p0)`g zXx5&q9!w!Yk#EPdyH#?!mS>CufD08r?Il{!`i9Su=zX$U+}y_V+TG1<8k!9fOz}6J zJPXK-fk+^hNk*#nnrEo}VcxyR(Umo$rMoM5?5quQy4Gy!>gac7#>~@6%hGOrgSert z**VCYkmaajW*6iiVm-fjzpz~}Tu>e>N}>6bI6t3Ad8^xAP3Lrl`KMxnZNVv~c*8|J zWNZ)M*&zAXrFQ7-AB#Q7xjO# z7vsL<+!XNBW1PTcmG-t$mRQ>El#gu$OJjMrZZO|Nb7(E(Xu&TZ!B9mQ#!UgQnvsG> zSoiK9Cv(>$Zr_(;Nq>H0v#6O~=0>k`cDC)M z`z*%$mOtTiCsH*I--xe)v`D^4mTw$!#toUGh&la3*;gvsT}w9OzitVp;_UVh;g8Gg z27nKcub)I-uKFayZQmS=ldg{WL(-c^6ubUB?7Sgm~<}W2^v0b+7(SaMsz=8BY&86TU~{l zn={w6HO7f)UWYx6nyv*C5j)eRPBvNkiktjl0#F|qxp`>Ltlx+Unf(G7~_U+?!-r zm=hUa_szkMNS2OKP|OD^BwL<17xp)lX^L|*5P~zP`EbeVE4Gc=?$BC}^D=4jBe+n0 zU$>wK;`f<4^B~~2*~z-{XC4dOhy)a(O-gJ>uEYIt>^sS8All}7{+XQV{ery?ea-OS zezi?Bm2F0>e@UrN=h2l{0fAmDZ}qbBewH>P{c~&rAiN`E`|QNEW?;AEv;M&(!@#`ww>pf`p3oLk6QzDtgY70v8>ZrcQMQsQu|R1?|-b3u-V ze31k;Q|~*>h^*F@rK1L!b5T$a91rL7=^wwpnBVgK=AQCcI{(THBo0j(L z*!Jl5zo~?_hqz)hs(_SIXb>Md3JTJ_4t;z4)qVo+90ne%Bl8>MMl(NK9IH`^leTun zAreC@sT_!vwed3j%u$C3P44Ok>Pwn!)_cv(lvCYpQ%5#cKewRf_q9Q{ z?sqn}GkCUQg;)@9MQKs!arSZPN!ze|Nd9778M`{44ct9T**LuAJe3=BaO{2ewYM%q zXKxA%!-L#d^Nh&U)l*ADkf@G1(!f+w%+ZimRk>F)a>{R;UB=hA+p-oFMk;ELL#4;r zz>hIddK~*h?r$-BH_ux~J8UfH!EF~1)P%XVVmw$Ja5V!|ZN()D;)HdpmsE8h$@koQ z!>abzUhnPKx_Zw&nA!O(h8JblVo?Yr-na9DE0)3BMARgX~uKu9cHVl$75nHkCJyBpuQ-qyje?EK5Vb7tLVvhG&V z+`?zMNZry@4y>uGSzx3BQAq?)=N%vZp7_=Lz&559qa(U{9;uF3a93n%>05AZ8l1cs zhK?#6bWcMLT|aUvc#*_WyBLz{Zbz`UJpIu5$96=x+BO-q!Dx!A9xz%;>v{trHLDOw z15p(nW2ZHH*Y{@TJDBZb_bLddhA$2>v0R9O4$fG=fu!Q!x$-4l=4>7tvyTBDzd`V^31LonN61d;90$!=1xhtnr+u? zxQ_Y~DHPEZ4Bv#SU^0#*j9?1qsUMK`9$Vb)hcNPYG+FNn7zI)pBajk)9ab1X`7VwW3@Vl}qw)IGhACXK(1f?W_k}Q2yZ8ba7Hk%00q=GgNq>=O<@+#9ZdU-Xmo924!g425d64eQ6{*24!=Ls}8`dY-dDl%b?Y^P`)r7albXLVnko(PQ!O zqe(Swbn`4Q!wf*Ro!-|ZdPT|N{?XsuS?%_ho37;|!(nd;c_d>%h@z}X#}7*6&~c|r z_MN+O-#0zGV%hDUeb(-DiYU|)UPmER4@~hsLZskze4ib93Vn^Yu{#Eh6y>X_q0eu< z&q{AKG;Zq?QY55YYiSymmB9fKByspY`A_cWxc$czJJMF=hKJKnjbTk)Rau4aBp|^|ZH-Sz5NHycqPNxA+ zSCGYR%ycOYJaH>drTmwrqD9p_g^HbW&cRC(Tk1crv#7T@p|rf*u4OFcvE|&{0Q(lS z95{4$7Vj;!jqdGrDQOEDVx8`I4mb)b2M!0*s;vHEUlcoIwYOdae)Y1`?mAtqw;yig zHi)i*hc^)W+3VuS;mu2}C3oHOGu!gV`4v-Uq*MbN#mwYNUVn`>_jr8eGu+l%{1^IKPR#Wq_Tj>Oe8qs2Be zbH!5#01={O41G!OA-CRXsuQoC78r-n-C0FNqthoqh#GeflUac#_WZ99^-Xx8 z6EGqPCUa=dk+cvjoF}&OIyXtE2tTZ@AyAj`3w| zf#8TNs=QdJ_<$U7ka+0?XGtY;a%z(Eb@4L(p->FnIgM?OGw7Zyy( zjOrQrdDHFcde_=ALy}#90^|}+?Z-TE{XM)G>8Qy+&b=fyo#Ly&b)GzcSue@DbHOak zqyh*BN}he)Nz^g^q0>)isVIGam-u>nf}{4sa6|gP*c)&!{ZsW-G$AUPHg00QJkBKu9vNG0)zH~ebo&(5vEVc=?OJ5ElosHW$IlL zNoRFvoW??HE?9sq^daVnAm#2@i(|KA^;aW61C0p<$rUGuZYx~*bR^`Q0MdKvX-Wcf(A(D7$J;w60g9S5im7P@Wn@u#d~sD*IjVS(XFgO| zQbjtm}dpfs%JQ;8T9Hs=PSkDd6RU#jjIN|2yvA`pd4V- zf@(O{y)MOP1pQC^8po6UE%dPG+08viL33~A<-7WcVQ@dE^te9#PcEupZXIxzscx#K<&L5(ZKPX^AITj1X{)JJb$IQ~8JJKH z@b!RIE0GyfVm)8${{UM7`2PT5?Yf3-K7Z=|eL8K~M!NI}e23}Xx$*<4_g`4<7(A5u zcqyxJ^*Yiyaodv*I@jRxRPs6z3#LLPSN{N26R^_$+_W z=L&o$uaMP1-l|AA>QnY}++E|^PJY;V-)WMPK+KaZ2@+dOz8vwe2S27sUq@9Vt#>Fe z75GfvLl>5Z!;!`1YN#?0X?w$2LsImTCZ+%`iDDwdfuwuj4>H@_ZFhIuRnio@wvpm> zK2IAJb^MqSp1S>ey4vnLb*<%unylu5UN*;aI)(f( zQEU=LxI(r!rjifrS`?LFd~qg30M6F zQ|H>%2dzq|D`BgOD#|IfE!CCPfOw=9V5dp+y5E90Baz3l3z#RfnW32}BL2hk2h4TV z{$Ag9zGT}icdeG^U90|1j5wpO;dS6gpAk@cFg;_~Ii0_r#O^E|a^rVK27kGwm7__i zYh!rc3c5`g4u*~Y0D-|((^Gav!Jrg-D{xhcT!!28w9|Fw@Muj%cG0YvgGksa z@{du2t80nquM?j<5(8D$lz;69^B?Nt^Z9hIX1lqLN7=V&HEuAiR!UG@Ls~4LaMrk4 z&~Sd?+UwNK{nR;~r?a+CZf&_+baiK8wN^I|xnYT6d~Wr^Q^79k>iy+U8%rJoe(mL% zDrwc5!<5BO4O|7Ib`c%5k&504S<7v*{{UwtGZX$O+Hq+D4%92n8aXiY&17=MT$^X&|lz>)~ZP31^sZk3~T&@2Z!|RUiKtrq6@)1kwb_~@9*3_VZ#(%es z%X_zB{xF>X&O(3P)Bl#3Dz{_Kxuvm=8f@;&b@`;Td5%sUP4t)fLHNWlU~r4-c* z4k~j~@}XLSIzi9A_H)0pT&ucrZ!+!TZ*i@pjvG6+1+DHaU0+S(aMbaH380W&*ard8 z!Cw4b-P^CW_Fh*Zy4r$TyjE^pba{GeXekClk)V!UH54?74La3Q&cz8uRVY^ck7_xu zZ?xJs2%)kpBWS}FB%LOtVU0-yXQ>D7-R@U3`<2M|ySF#IGH!PF?-ETKtbR0MRMq1^ zsE->Ghe!d2pD=o~Zlc`%1GF|JL>-;im|fAlDXQw$hPIooDEA#%#xe3zOD;z*mVysF zayu9B_+=|(y@kwueGcb6%9~53NGXxx70=iQ_-Z`*7IT*`bN=nS1It_U!L&LJO4m&q zYsf#Qh)EnNt5Weasi#HvaCV;M$me9P+DP4Tj-{xWV<`5GMpFi}QZ!~IIXrjwlW^l2 zcUCM!Y$8@Zgp7K9nni00r6xWr9wn$xJty0oOVbu6zu$qY39X##-Kyl_VxMpx5!V4$-SPbB+a8Bi4y zfc{-b*095C3PAv*N-!!-2c=C-2axg@;nL%+I{Od5^T!RA-q_uer$LUlBSdP}c=TGQ-9z$2GZa7Olg7&=9>`}O&vNs(ZrM0(oyF#R1-$ka;$3{ zvO@0a#1IzV)owh#>jaYhNNaTBR}J}4uphVb=o7c|w%N{?)||h8w_WY`vVvBU5Y0eI z3e6O54v<)t3;-k6y#(2f^O4;&D@Ps|8GwcED}RHwLKv$My33?d%UdlZB5AJje%ZOx zr$|xkH{r!*OBqYQm1t@C(zqNt7}@L=+g!~vUQ2Mp;qf$*rz7GD7|>v6*0rxpbeNr2 zSmFS=F2zN)Gg|KLYqK%>lgaj7ak#1i%=|hrl6K--hei+M_dr$mS7Oirw?Ih0?b?dS zup1+8(NDg+gL>40nC`ynJ+N0Hy|-0l?5`TtMTmk*e0(GqtI16SC>fsK-Pt8=-*6Bt znr$N60f_O;cI>xlDwyq;SiSpvN?H zZ6s)_()mh&IQBhA*4o`6RVyUKNL2hw88wL;`dVnrJdFi91oEcgb&?{PxDxugb(g z%7CrHpAg9WsnM{+R{#-p4^S2Y!oYn3fGuHe2eZXKM~_g><7#ThPXp5af~ih}aKV7) z_8(qP(0zT|g&1@XynxZMN_48Es=a^(hMR&3V{$He`UL~}d%ZOiq#E=dxra?jG(WST z)4VdY^!-1-WRcWsz_cS!ay8V{)5R6ai`=^p_?vqm=Ei9GcXcc~%(PQ+xDpITXnueedFa>gQOB|Es)=u}{v2BfyU5KP}F5})S{0j+>gH)ALtz#?| zl~JTe$`xZ{5+ChK;0xIMzcSwoEw*cD^L0OBFB3v&Px%MT^-f3GWZd_tFC|)7T7ILk zz^KZuabLuJ6laL(o^HeG{{V}fS&07tO&zJ%T~$Ga#imCyk>8ug2ev7auDYa2SkW$4 zwwk7R(z2*RG)DY^?Aw?2dy9R(*2)`pX@IK*1ot*b$EW!^Cgx4ZZ#&)X{A9Jewv;sd z3)&B+el9+JRM&d{0K%3(m5)z8M;EobQ+WJ}-Be8RM}z3CgP7bDRkJMSp7h(#KmFU; z@=^kf#pA4$lp2*=QU)Bu%Dcw_b+}7SqRwlZhTxE+ zNZxoVfwS}Bud2gx!7fyXtoqK?_t)8c24=+e{WR zC2CO#A?m6Mv2n->#Zv9Oxn!gFhWsRN;fYE9X1z;$7v0m{?qhImxi01i4xa0VOLd|A zUB_9aYG^C|TGQ-5=X?C*`<6$Jf0NsPr?IsQG&1A*hpzA#hlVM|$Q9L;87kt*%BzZi z$`97zNJ%dH$`&DozR@i2>h1tPl~4FOo_TZbFV6duLnisn78X(YgpON>Tvv(k(EdmK z{Sp1|-G4B9I-t$jzcqeSZ+B|BYrId{o1YO$9aM!(lE+U&l!~4sdudcfRX;#3eWX0~ zpi;|VvV?HWT>k)*sh?~6hVnJB{{VK}<-Fe4$~a-S1O2re*M&HKTsi^rT~9~2W;HvP zCB1h+ma9P=|TSh9r^SiPrLsBu^hgPvvPLG2;<`!r+ib$$;PYc#=fVl@7A4l zQr2CmL0VZwn!c_d9_TI&tKFRJjGUVzO3j_tOOp~GHeg`)nuL2BOEEm*UQVO4}7}zGBuI5zicfM#1HKyssaI}bu*8b16q;i(lUb^ zv8XbuOV_y#*-yIUV-+noQPysm^RrCv0!I`vV4GW)mE!=5jZD9izTA^xyMm@&$V(VJ z3Jo;*vs3+FpHTNP?mu^<6p@{%!*~Jz0C1&|+f@Yx2B_&=RGenMU0?U|rR&eI0OFW8E z*I9BD-{a*=dpn@*17Bz~5z|qBFNfz!l6rynX4$T8m-i*T_tFe0xhPJN!kR@#*}!%5 zB$B;LF;)t?n@GRlo&h5N0732~=_1;i4&IWRzi(|V`+}|7`{Qomw{G6Z#?e;cv)K4D zG*hWoOvwHL(G z)p-rQTP03IDc6}QY1X=)jp`#B>-Obruq<>l%o(YrymAw%9KzhC?e5p@FT0$r&YNK= z%MwrE$ZJz>(^fI8k(ijZHP=xzRwU53L$>dGZhrCJ$#bu^T*Geyd#7t;Zeh~8Q*n;k zk~xJz?7L99q>6lgMFyFZuV=FAYi-(^aJ_{$9Dg zQWy%*k1zB5`s4^w?t@!91~C9s>OZL1dTig3?!q8+tMCJlRn?X?&!_o%$@kJzYEvee zPzDSZ_f{aH85FgNPpSNWPkt7OEg56%Kk6oj=hlqv86dVrKiJRusnx*$054ySvByI< z$d1B>Se@3Ui(y~|3#EMTJ1sx)c$PqmC0AH$8OP@!0rRa2x~l6jBJeBLf@ zkAbPr-47tf}Br6e_3t6?;}gS z-koW&HSJeNwj-%g1m_C`{v%!y2@3hiATkne;vE3rkOExUx_;{kun9}vMir+kk>ZhE z6+Te|r_)xW&|jLj{{W&y*+Uk)j4Mm0xN9P`C;Al_;a{^OY#6qhH;R@+5iIn`lPFkX z^%h}ZL2X)iAlM&ZDK5lp8fC8rByl|eWxrHqY2(yz)ds9bmmg2?bce@j%4M^gi5Vh> z2cH3rnhY%R9WZt#GALM-NbQ z(sH*K9bIY4%M5xXsar;}>T8CyA>wXCVjV1a9R59uHrtu3;Egns8Y!+goReJn8va!1 zUt@bMt(xuYA=I()r{>x9)ltyn)4NZ&Qz1*)doyh2sy6Nxt)C;fkzSJ-LrE1vhpeTp zl~D~vG^nnoFu@r?Hov)(+kK~-TXMJN9g}I9tRetQA?-j8TT7Y>sWt5egmLN|_lJG< z%3X(W~h%``-)R@QxR5WW-r0_b3s**T$v0p}Z{WoUqN@~e!sUzHUaI|@v zNTnB+ajG$2O$)!3A&`NrThQe4K~wLc+^xKg;>8@u1>%nJ>VJq1H1+xXi0h2J`N|E; zyPS&@EOyx&^vymI$3q%WpF`#;<_|(nUWS7=NmGo;$n6~QI1|MyMO{rhC@WJ(QOSx$ z1JpTIUKkPV*5cADrIOy|iAD!MiCfiAudk6DdLXg5y4&T7^2RV7NWlQ3FPgaX9-d(2 zQ=q>yy|-6d&!)ctS-JL%Y9xy-i;?H8#Zw^*BsCQ79pgk+45;i=NNq9`WdyU{?i(v< zn$@l>0K=|Ik3u}XKsfY1T?%dXJ)fGB#J9X#P2k~?zzXf;K^$wql^VTQiRoR4?;f_w zRhkHQjv^Z55Hr!%)EY@6dC^`t_0$B1SO=Rmfi@@c?AF_uc6r~!`uN12jgRo+zn?+- z-a+O|So~wO$nj^nDAfarpv^xj{JIig-aCF+gwbcPa>ac{X!6u00+DAo^L{l8{x9tL zZ)}-Et>i^($6E07^XM%nFYajiA8xo0=wolo%clJAb#?C4f-mBmrxeq&ofK3RBO_Yu z6tG06qgkZ#GK+;aBn~~dcg&k6+Zy=y@s}gvQ>njTuk-5mT!GAcypnhuREmK7QVk3H zSdZmigD87Pc6QuSV>V?TQvrmkXNse6wFA@3;qgrcL=ewY2Z9ND-mEtY6_5|gpdKINF*P# zp)+b?Hiu2@>8k4L(h7WSEcJQJJ?>|N}Uk`3j#p)3fd6!r!ao`xPY$T zZ9t%!&^b)>0#6ca);^m82Waau*C)^$@_7c=`hG5d-hKQ1w@n*1>2gYlfdHOnG0H*YmnQuCb=)W{sL8ofp zZN$|8Q|c0t&OTM5ImZ_#H9d4I?)S{o?*8BY<-2lkcBk+&#KhHjs!ebPqzA|-9$ghw zV@ug|k78FNuxnv<{{VHC$LC;{B_`Y(RhxglKJdkWo0Vo?IJXod*S;bT{CBCvfS;1C z7P*IZLI)o}M&gHUj(*2DEOo*$ZqGg}N76*=*SQ+Ir$cm}` zra$ZZbCo$?apqmt&u_D|XYnLZc!5ght>h>PC&+bPQRQ3yWZf++;I(Fjq+LYSMw-=z zuOXxy`gOQ8aD+ zP5XE32P9hTJAH|c1Onaw30$dT=uS;ol1cOf$aNn5{khI78(vrTzigFO-UtMwtm(CxBn?g9YOlw`bK11|=5HMZ1vQPIpUd!vOL~)f} zxQ#588GLLfRRJwgPKKP!k)6Qs?vW*h>jj*DXD66GhtwZWKenA^kFZ|+Zv2NW%y|*&4_#j6zGT|@k7~5vHaoEPk_-{?BM*rjaaUdiPuq}sF+FeC?M3`c z8&-)^L%1=&!M8>ZSMk$lajPoS)74TwmitWB9yx`N_9D)o-?M8wTh$zi>9f&tZ55wMJk(OIxJJk708_w-B6; z*`q5oXu(nPXX0i@q^S0%Z*_+8qV7M9ovkH9bw_$(=~|l;n3j~Q)%C|};-m66UUwGR zjzx;U9a2=t;LS?YK*GisyJGF}Ld`eS>~jAAWiTDeeGihb{7HaF#SS`-IbWOZ`O|pb zA84~qUH9v1L>s2la>wcK;sS{-q5kCBOHc7l${=Nc5ghmhIxP6g^s11=L()~i58Y$u z3+IgR1c>0;YJc@EmkoYwc=ktgx3o$eQQ&Wd#{=>s$ohkxrjA(WdoE&O~0CL zSNv;lo`QJ2Bt{2C#k+BicuOOKHEC+7RK~?^WA*<4ivDkZ>+HDO6Xnpq#y_7*yagpT zVzLZvMq+~nQBcAfTKu~-IB6;$h@r?=EzT)rbEH%k77IST4l`@Dq_qgrT} z5td0LpvrCOkwnO8nn>DDUaOOT1PyF$l@OWfzyAL{w^P0zanb2lzsT0o=sgeS&_)Vc#yAM;Ua zzimA_IiJj{4HXYs^&fXp!B16@=`QEmSvIKwCa0Te?`c;9n}$cy;ppc-Zz8bb*JJbp z*$kUP^9IGue6KE`xBGO+Da1&sS~56fH9W_sSZn*@eqP==W14NMw;Oij6P%Sk8!$;w zo+7GBpG@(mMLYR{{9MKMk4@EfZ43!EbFL^O&b=KWnLoU{QKzJ;%F{E$>c`1T3jNd# z9oP>dvkhEgSKWWytIka4gyjq8)3t8W_*H6F8#eHP+TVO*Jdx+iF*mElb`A0JxB8Dm4M|R25F0$?YWAm=Uvauwr(@!0Qe!kOJ7e zjASlCnx)v8XQ&hM@<>Zc3cu#VHg}kB*KxTw@|U`=6ZnUb9zavbaN*RM?WNBtUh+P{ zbIAL2Hk`fTX-H60!gW8Z8=r}!SE*)VOVmG~Lm*&4Wj6!@2>yqVK_1FF9Mp8&`*uvN zTo7WZq@O2QIzdfEPP*i-shNUB1Q8BerfC=iRpr=#1<$vl4Duo>)rp`Ur^~A~)OPX7 zHN>H9(Me`J6b>YxAO=bD8R1H9jU0bVdvR*4z|=Uw1Q18s4oBzG$YqLnqPVx2B({-5Bcm&$Dd5QJO0Yhl zk=9ysQAIpev@_2~S5E6B6?D?HQ^6t|tHmPOm4WtQZ!0So}t)|<^+RV322GDy;-Q#HY<0$B?KCbOvj0Ils+&FrE- z5@}hQlodbW{%1WVhT6+-jgrdFD3G;issO1JBzj;|6zNTl#SJK`mH~JKel2cK9FJi8 z>-@78&3a2L$B8-U!E|>eLqu41vog50qHklMkya}MWkwQX^kF62M$QAfn?cq%B#C!jYx^T#fGf6IH1HS<>B zE%u9b^30OR*p3Jz9n#G!QDcokW+%u4()Z?#Q2ztA8S5HLSW}~uq^e;(W2Vdg1Jv!CFJeY#I@;MqB8j5;};6dq* zQlX51DR*zP<}PE}n{wKW7Lhq&5R?{q3gZI`py$cBSBFH``!6f<_UfB<_dM5^Kn-Ft z5;UkLoOQVXWCAJY)#dekS+4uoTSv6E_sH0{ZouDIN)5}j^ZN~axID%mB?8n_R8z|w zl&Hz2w7L`yjtaO05$rbnvCLDuF6qo}jt*4;$IFV3<W!+fz+`PK2b~U{C)c2Qe~kO%Y|8Z*s`@>}Nl#KH@Z;(l zhao*GX?4*}R76r#ERn6^4eA_&em#aIPLP?ce5we~sjvh{%jx31Lbz{$mMFgM07n4RLdPU)#<7>i*Zw9 zCyrR7$G+f`?(-C{MGV9#r;?bf`m}-#(%riKjG-5yQhy0evViJnC!K zTJm?@Q{4V&wvTV-8;CY7mq;es*a_}RpNqz7=|`ufB(N!U34oNRyFMo8s_ZM_{-0iRk zEmRtqqoDbc#D9aS_msZqp2za;;bXP)ChZRA%oED0klkFare-HXt-LKmPz`l)AlIc% zN8+XfWp$rj_608S>zQTj3f%M%>^-$wYB!$P$6y*5W6EyoD56-g5#^_ug)9*nVsf9eq;49_UR`SQSys@`$8^14XyrcWJ-pV*@I@_#JN@NUl zK;VXy#6B``3sR)lq~$)*+c?w>JI6GF_Sa@6#9Ub}e;?NT-`RTHZr9C7;~{#I*Oz%? zX+UO?UQy<0{z{+c^Xr_`;3&aJ6H!$*(1^Aq61F;l1A)h}7TwC5)%jE5ob(;txyzJx zV9L`VWv{2@#Qy*;lGXJ=gUb~ALG|RSIb-w@-U!==MU?)6T&C%^u&ZbLXG@7~{X!idmEb9OLIJVRfwc8}ZECvz{q9^mst&-M!_AZ*u0vEl0?onplmk6HK3fwz^AY$yk2ONb4*xZVdFeM6Xq=S|Ix#rFE)kCb39^PoID@^PN5o2h@{ zHy_J)ud9EF_6;{|_x*U7$sB!|zUry5Dz}0_l43Tzcyy>_njJvAhUn~!7%}z_z4s@W z?`z>aQ4_?f)sOpTuSHFANO}mY*jU|`OE%I?t9E`F{FbvG{u`B^6f$Sf3xb9b^wcYfx6Z}j_{gtQk>3lmx zaR4K?RUaWvhdDCkfDFxL00k^;0*e5nfE7TnAA#)_pI(-(+%9+Dg9Z|&~L+1sOFZt5Crrr6#%Ope~o z&{ZN!4MsmFPW1AEk_KIIY7!$_=^`r*N3?r|g|6#kcedT7ZKsT*eTU3?6*M6E5Dy-Y z`ELIJapgVxXy#p(R*!YDohFQr;zM00)m&8_crvk5gV)UW=Rfkv-yLc4E3&r7Ok-(x zEd>thuf|nvpT4EWny$5`=@W*+XmV0-?DpLcYL$ITE}-L z-W^tJIi?z>5o;=vLE>tl4X!#zsd$lDKjJ*?cU*8b1j9ii=j&-l!0)j!0H!NL1i><6q+y!J=k>r265 zKepS@x?_r3%F00VS5+uS%r!HbbbkINe=P0gx_34=cK5bAEGFK^JuQ4&A?Au)rdC&U zcw)^6nd#~2SxS={yA~%)adGbx{r&so?0YWFxN`Tk_eOo$!A88HSmOr-!K#ey$Gb=X zWqglWkL(}Zn|L?dcRBmfY?j+JbdoKO{{VQun#SXGy}NUFe9~)X zW2uo%Sd;xWITgvMJ#?bx{@%-EPYxx7FewsJnq!WG3Mr*d00MvmP9vd@b?u6%u+Z%~ zN#$(D{H$CetU+U1JY%4fJzuYe(+(y#3Vx8ql5?!09i&GST2LSxUN6Bal-xR8b;_mTZN4{hmE^k^+NKIC~RwZ)STHn{GRe zq%&o8Rms2zgH!(iAy1b^+_$&B?YdaOKXR9=o&X{Zav%4RPnCLQ#bO384@HW2WM`wH ziW-WhT>@#!6{(gr4CM^6u{`=%x3%||zgK-d;!fxgkP6?vtv9>PeLpCCu5T<<7lSgzH-S=z0PhBc1zMuG_CvZ%JO|-K$gb9TUo&{{UqCpxlW~O$_^Etnu|iNZNAWX#${M@|w8< zDra)?DJ3CWtXHwpE=+4H@0|5{r4+-mqhh}bk5l|^eK-%79;OI(?pyZHZZbI+9Kj;c z)8ljeEB^b89w*P{anbGCn9L^2!clGf6e~@RqC#~RPd#N!mNhvF#$6&>x|SDX^a9EN zPzSkBZnC!8?V_@@i%cp%HYbZWsXxnr$52-9HTL;^HsOB7t{m{q5l6y{=%dTmiOK0& zGQ1B{a6#t45-ra^*V&G+Y4-F;Y%*{_4APKHr=#QzOd% z0JSe1*pNS`99Vz7`?w&ElRby@Ph2W8x|c?)Y8PS%xJ&Q=zLTrl6ELAbf8x5lHWWIk z!-w0{Ly~tYo<<98KiLC<4Xy^GZ)n((K-b5o#geEkpjWOE_ru=RpPhdek$WJe?r_0FSgcWU8Q1 zR;TjmU6r1&Wwwv=39XGL-e`0ShUnsz_`k$8v89kMygtsn$=nf~#%sYI4zrVIxz23aJ7h07K2rsT-5@ zUwpRO_DKH#srtpk?3aSVYOG!srjbYN*nw!m-`-Ar-Z@&`cO>1U zw`M|=Q%{A-qcYbF7J*G`@m8Hqp4RL(_IAsDh)Iz^6%?a>Ek3F!1y2)G*2^Et#|cZd zJ|1wOBkQR#HWYA!%zXu~22EX1DG;8l0qz+P;j&-(P)B_U_gzZG%i}L#$W! zSNx~;^~b-xW&FG6y!_jA&P+>nGA3)=8~97|_+tQ5%c~q(@9S^%{{Y*6k0f8%@9gUv zTG!L8;FMiet00<|vW~7O>M3gJDx!EQscPxv z4IK2<5IZBI0A?I9?E;)y>hkm5t##Ank>+>Qai+7G31vDzYFoM4OEfU3u7{H zSHTT^1kGUL$MjE2I#{$*C_18^Bl!INMZxw{KGSt&J3%_>kZ>b`9z{=>KkBwhq?BPvRedKvb<=#IVPqpo#|y4H?TRU)gmOuxb|<=vDxuG7HRLki1X4?=dXT3l}5?VY}}mK4-=@>68i z5EfG-^2br_7Pq0K*e(@hWvg0BK_}#dkQjP-kK!FboA*9*4oA?>+zWgpxks7`*M61 z_{GpH!7C+wxtXO@dE<`l9YjerBawbVzp`mIctyfTEKdZ$_eA}qk3S903G@f{o~1p% z-0k+)m)~{z`#xgjDPnJ?-*(*>2!@@9aI&|nEkDsEwgqWY(V^=;8agc9Trp!R4OTv~ zsKZZIvAtBEYR+^t@KD23FWeX`T@oi?*RqkvvTKdKqLI~+l!9>BH1e`cl;T5X}YJX@a^Q8Bod zEN>THOdn;`?K6eixlP9M$&Je6aTz)cwgV!S5f-SZ zt=lGrBdMn!y)8UQ%2+g{6iaS)z0wWTMq1Q8SPmkfh96^BkFVv{Jp0ATS5Qg0?zR!H z?wj1PP=7*mLUpM84&zd=z+zO>9R{7N@lStkiY}dtvi@iGPVJ-Ly{EJ~-lB(W{{RNq zJ98PfE3mnWoaSDdNNT1t8Z2fcGRsjPh}`*umQq7|4<&ndWiIVL)$PvT6~aREYmp4j zUs{kWCZao=6e64!fOQUTyU#k_KFeou&KLIr;_5gAadrZwTA@}k+;pk(HO)aiB=Ub0 zz7zDn@u;w0Bs+&AmB>@cBI7oVR@dE;L6VJ++t$`BSVY232v$O-NLonPA0q`m#lO6F zO~6Jjwo77z&GjkM=m<3*&pusAT#@bPxjRpe+@-qiJ6saDW-`2K6EOTu6sX$qf;*hf+^UTLwJDHaeKSfO-nSJ83q(`|c2 z#EOwzHLc4G2@bf4^wmJi=m`XR^)_Aa9_w;cLic&JwC0V8KeaXxwXWkD(=siyJ3(+4 zizIB0K&T#F2zz^SVRu$IWiVCgSxmC{rcth*wt}iNb5C7KAdaqrt|lL))lJ3JpRckj z?Yir3o4~q+qtc-91bG!nTrPdwTcC`J~hCa#-1+7=Mr7CTo1O(rzxl-isK< z;x|LeGMjp;XyTqpXrELEc6Xn?Uf#=c@Xp|*2xfi^M+h!IiZ}RHPl*W?Byfy5hhe$) zt_|awc_3Y{B+Mjz*KD?_dvtJoP1|K!5e?n7d~1skz6IQB%!-q(Bn*B}^#051jGiki zvv%h7+8E9AnB4Qhvp0=hEnZKnvs+TG9k>N_rZ%ZU zzmT;zOIvFxA(jYbjb&y!9D-viLdy$z>V`^y)uW>!9(@Wut>-=GnQd;ZH=WAL^6JJI z0lBwQseKgcX0qJj$xo-;Eef+n058R+br>v~2mI`WWI!K;+s=BI)77A)wXd?yXo_Sa*s265nJ%Mko zWOmaU7Lkn<43bX(2bm`TbXjwA6fw&@(yBs=S(%6ms-mpK@Bjf)e1Pah?*7N^Z-cpx z*Xb%uv*P=Ib<&=n-8&;{XDRCA+&b#<8LIuim(F8V=1skZ$i)fC3V90=f~fWNW5tgWdX#w=lgB4*v%cYc zZ+Wu$gtzyMJExrIO8)>15m!Vpj4F!Kr=bfG4LarVEm<70(XLM(Ya*w0j-pyctAy0Y zPa}p%>K*{W8G%sNCy#GNgHq}ksOVFBB!<%HLcwJ*K9WU1I!y@!Bm+V~IT-8z(Y{UF z-1U2YvK^nZsg7%Z<_U_DkpP-3I!sTFwzV(gGnBieZDmy&^G5pX5ii)*%+xj3scB^y-yz@o`oK*>g+ZypzdAyRyVHn zttnAcRgz|`prWYZ%F@Fz(^)Je03>msTF8n$m)LUT5I@##P4yd#8j{&nKQB@}PCW-f z9%S8bW{gXwc?MpXx3)I|+7}{AHPJ0>6NKua$Y$ib|AMU{@1${OZOH# z#b{Pc2P4p&AD08_IzeZ71=VAjbleOOMw9ZOGzW*;Jge5+{{SAp;YNST>%4I|*|Qz+ zIzx0;69sn7?tBhUY*ymyW2b55r+nQlK0|NSz@Z3^XzDb(`YafQG?QlBV#>kdM@%y0 z5z@xAfyfH0y?7kDWgrks_zAs*tAh63Ao5Tkec;#Y*opjbFBi z3(aHW4R37?y8P4pRsR5IOf`V50%P)~e?GLn`Q!6TwSS(E$=cnAurqLV_rpHB-g513 zrK71u+F8!morOI;R_5#s-Bi&?w3Dn-RY6Tr`#8#JkqVjhFb?y7Fj#U#mLEyCK|eRo z9Rs$SK!o6yKBtC80X3#N%s;yq-O}gXO{4BCw1GJa3DAe&nt5OvZ zj}ep-S(QMkJqw#}`F#8+`0I?LkG%V{1z+}X#viYGkS<>*X) zFF>}8jDDjiq_VpaR@TRWByb%)W&Un_clh;7CO_i0#%+PMs-hDuKK}shm}&PG<&c<7 zF{+ChBUH-`T#QQ)(iP+qgMh3>e$zkrhTKW=c`EJp=d^#T9SujcySCvMiS9?Z()~3m zZ0u=m4Ru#ZWuv&@4gvm=$s_~1{%`z~?}(}~`}edn`7OO8hkd(`DS+C)vVmia;c>#6 zmT1*%SIDGlB>h;DW|kM%wEC%8tN3d{`vyP5(dN~*`+vz5la+aT+6$Eivz6C2c>c76 zzH5>Qzyp9C6$vv_10}K%y;P?|_?@Sd^)1x5HVSX~9Qzq;{GlzwB`nULQYbnNa~HZ% zTdc_*;-+(oDJ*}HJvP+makLDFFObtCloa&WnrhmoFQznu9RTu3XZmSBQ(^V@IP$-? zGhLNo1sBZHfMd;%r&y!zZ{9;-CH(xCF_`Fw2tU0*bQ zQ_D$R*BvU|ak1*^%oFy9b$!O(#l;+H6!O*MFf+orT$BPi*T>^B%ZazkB}x?l(J6FZBzP#hsI}A6d9npO3{HI8Z$> z^sgG^U9U?20K#>8VkgIDzEgLW_3g}@DwEai4TvJxn=NKp4XGNbqpQtiXnZElswqn` z`jxn7{{VRR(sHkB%R3Au$f67mbP`$1S>A3+%KVC=s*R^XcaCrLlL$ndyryoAN+3hL~ z^ z*`80U>Ce;~elPuPe|xC)>f>${9Yt)=A6EnG{jP2PBkTD0y4Qf|_1nSVzssoYoCE7J z{{UMX{{T<$Jp1;4g!Jg!hwvV?ivD8sG_ZWm>`a7eu+ikOyAHc1)bk`OSyxkmqE;?E zdcNsGhH?$h)SLUlUwo8B&fAo0q|ECZfCWm{B&~d^Y3E-qyA$_Fd7s$+Qx41{id(4i zc!jxrAaU&##VOEZhnk+EoBhi?6s;OUvqfIIB%Vrg%&}2H8F!teK(aKJvg$um?g=b3 z65}KNRO))ZNurT{i5;~TAfW^(Y-)Bm0AvNNPC8lRt7##jsjr?oT6iOdqN=#GmYzsp ziRY9dai%2k#%!b3Uxqwe*dKQjZZk&&FIfqqkLeSG{;whP=rg#%BTpP2Be4W3a(>ExGUZ}HB8f2#S>EA;p}0dNTL9q2h-UG_Lp}K zyKuS&7?;BI6hd%40eZ1MeFk}pYr5R7qgXD}z>YB*ickQ*5o%JUn^P0()8^FQ7!A?9 zw+7>CxhYct8tqJcb#aLWHGGW~c6y>IV`oimswfxy5ZmfUvaQ!=yxO*VUA?2!_h8OS zla--JfgYG<{K4p>bJ?#fHXBW%1QIlow6f_ms8OaRAmq}ekIeKeSMH2tQB6}%T(v+l zMg&qLTB1UI1YYrlMI`+Jxc45zwB1Q6#`fhnoQigjKb~pSdlt=kG|LROr2(m_6zv>H z^{J=Nk45`@?x`y`PSV0g3(^|u?bDNr+TEhU(v_q#S>q{0mDN${1fEv*Jo}OPe`i=W zjq7l1P2r`yXMn7&-Ao?hifi&TuTpm}?83`!+-}Y;o*@Dn(t<)YQlR${=047sH2b=u zMT(saZzRqVLR2s?C>(;)M=M*O^p(z`1JRjodM zu!@>f^XNnP@wK4rZSlM|(F-b{TMMm`4(I=&hnF(Xleou@yJbRmc zr}oLY>zcW4Yu#VDEo`+;e~2WEs~u~DAvF5~bPe}onH!RMXJ_7Rz1Bi372 z>MksGupiR)RhmuBuABjbN~%YV4U-P zBn@BE-%s%NYZB{LR$?*!uiMcD#@tb(WQ-6Gr=LN-?$|qbaKO^z-}|$c6G>MNQxu9B zWsy|KWrti#6SNWf|+bPyd)hlC#=ysbsMJ5m!};{g+@H&? zHQRF#Uy;yp<;O|>RqGW003&;I?%JCN(^(WO?Gm+h7Jju$SbB;_O^%3wew^F$>tL!aeE9as8|%WW8YzGG4_drWKm>c^~-ZV#3_@+PB5W7!zV!p3y}01n&l z5*OwE;peQ&=?E@#kk;et?#$f#x-WzjTU(#>vCw_BXZ@M!wc5S6+1$><>aIp|8d~Fp zC=>jhD|UCryiGkyW&0Cx)$Y8Rbe3uwIqG7^yx&rlIT_sKtD`r$3*l4ru^!fK{D*9g zE;oC&xSqLCNLu{Z_c!wBw{+*5xg$2)9fI4y1{r`X2gwI&{&hVYItt1P3Rp4N=qd5^ zG-=|cqNIf>>8ayeaTHO2pc`^+a(=h=JdI+75*TAtiEtDE1wLIy7Zy{^BivjwNjv44 zi6ozy{{SZsPMnTht;diO2;_2q78W1t`*EAlXQZFIRMW82sY#qw1>R7r7p>De|9Y~yI+OS_2~stMNPNu~}Kgjdk{ zSE!KuiQe0B<$lrY`rK?9)uYK^BbD^UBNT}xp{kvdS3*VnGLlKYk6!tF7GPsN)?cTE9cw=NBd#&=yuwDo40pS?udRi}oWeyvkrcrMap)Dga-H_wcGlO{ z-WvikGOg%A7|*91boiOoKrJh2avM&qP0j28-9RG00up(#_qK6C>C+9h7CDS+9(+Ha zO?7*V{G&?D0>=WzE_FE6UF6`KazC%**=+M47=>ULO$X=4rPkXw=;|>N#mV#-pdAJM znjp&c?)ajZ$5$NK43vo)>jFusDVne@m1SlNBqGC$k?t$^Z({HZ|@)?|RM4J#^z0ED1BL66F{~Bd8F^I7xiEb<~%L zbEF^^Al~ENUwbvMLA6J38N3WsR7aYvNT{a;q4lkNx|+FXZ;Nk+(%BxdAp)L)wIhxI z^6PT1g851j@z-a?L=hm0n;4NaK#1NS?&cK0P?vJ(tH31OeLd&TC8+(%C@K1f{yM#I zpWdr0i9N&L-fYNjCarvrk0pIFdN|3FR^U0~{C=eUey7;Bgi}34k7CP`ol0DV$N9iV z_}l6~*0KD1u6;UA)^z+C>oCaL#h4rY1^NE~8w-$q_@0|KMAn0cO_};k2J6A*wzlcS zV>cey+<2<&4&&R|npkoetlkeTO(hmj6_lW;M}nq;x{_9oL|{Qy{=EBd>P#-Ku0yG) zrx8y&_2sdZN=X?jDw?Yd5W^sY>JR%peCWTL@AA^md>QSm?_hNnA0buHxt!F{HXzAW zUfT{z%AY1X4U?>KBa8)XRS}FnLSu5r?POx=rHA~N%=Wz8mprq-6pNUkB%@Fd5qzBo znWy%MJiCD7OswQ?dEL1(=EIscNg7)TkyhdoNJ*4@O58%orn)4hRN&P~2Cwm1N<6hH zRnbUUZ>B_VMD)`y>xN|d$1H9B-|9V|-E3DjQy6X%gm5E)9z-8c_^z|BmAU6*=MAbI z-($Pi37~Z}5=8!S$fMz5`xtjFIvBRL_B8%FJk*TQaFExxsp9%7tyQjB0OMcOet)mF ze|Py2(B9vC(gbpvk6%B}{QVCYDthd;Ll;km5>#ZWYU$1x(bYvyQuzYGsGA*J)fCH3 zT4cA1K`d+@)?jV#YqmQw1X{`EOd9!6`5#V{-0!y5*0(cVNTShD_=Se0(N6730o0WE zhL!|z1a)n_Yw|bbmgU-%{YTw z34B`38c}63@Ud+|n1k%?M&j_BTgYR+jX(w&2APm?!x}N+f(vzuT*b-$+3j1y^N%BM z+n*xuH!^BX*Jy7OXuNVMN$q13*iy9d43Jy4C}kAs6Pf6rzBM9oU_7KsO#E83dMC+dGV!tnhVzLib&gQr717OGgL$8k=9RqLZ%bHSx#Gem2y!dde2>I` zoI7HPa~nPSU*%5Er-m=F-Q79cU2~t@Q&9vHtxM45HzwZR^zt}m1t$^DtAiT*NiQpz zV=ZbClh!#FR6mz%53sFzy_entmu=@Z9Lcxc+FsU;9o3E2(>|)uhKC8x*dkK3z#f^cDUt`<)ZfZJ^?Pl&>9*P>k||l0N~}8dIaX!<#Jbd? zv)~TUNa!}*R6C<*=HF@N@LQv1?{uW6ul^6X@cFH)ox@PqQ^iqFn5m`7Q_xq_!!;dB zyah+^c^1U2{pwAkSX})~B|xP?rA=}LGslj6x)a0he=hTVl5O0HyT!O(-$y8pL{>0I z9Bw1Ho!!(Uh#2Syg_))*xB-Yn%^}Ng99BQgJyizE#hTiso_VK5%w-^IJZvOL?w)wD z`sQK!mss~!vuJE*k(c!+Y7g|PYRBv?LHTr?Piwk+oy&VJ-UsfkSFkh6KmwPyC}6fi zK={_&$vGZH!Sv|HY(A6iF3Q?_%X@4slb79lZ?Eey6kEol1sqkCm^m}hRn%iDs**E?2 z8%@h_NgCWrbgaG+Q0lTC&0|`SnzayW1vAnx!!;a_PdqYHPfq0}ibQDTiPVrot67zm zzutX>?(Lkrc#3uT*P(0|sUpWLQi7xc7#w||kMQ&zZtbaCjjWTgc0d%{riLLlXBe(x z$8RiLL_JLwN)`RFUagEm+b`pmF|qFb+iRL5@n{_IWk17SE5oQy+zw0J zcFo#fbv?JF9O-Pj?(Koo2I~UmNTxxLA4n!SK-H)W>Y?aK+xgsP?7?I6n8#@``AT6b zqmq-sASEg(CMrY6Q%6v&j6no4+D zww`F%<|e}KJxUwmMg**pNDt$Q!y^NNN1^D~cSmo_-J3(Ib9wB=bysF!>GE4+v=XV? z!M!qADhyUPV)pdNphGt8&g?2!Fgf~*EVXqwDr%?KEmW+kH(U0;w6L0KSluO7QT#*z z5^8WP$TT~7lu~j@=rzdvqMVVub7hT%q-)C)vQJ`Hjj~G8J=Wel#k^N+*H(#@jV`2# zbgW1SIYk1mjY8Vw9)I2mz3qE@1Yby7StqFl<{uF`^yo~-)79;rk-qz`wzf^RvHEfh zK4Ww5F;OKK@T}%it47P)xH(}fQ(L|FK2kMIWgS275)ABPhBuK*_Fh=t`KNFY?FYhG znM=+|3l4BEVF<&n6vG4Xo(_@fJa!xBLD)i_i=O3^pSw8Ve}V2?0?vkZ*K%XL#%+2>Ui}(9S}9t zoPWwqJ%{?zr|0}VyBtKY=?&cBZRXB&pYR^P|I)Y4m&F~m6;|WT$@kmGb5AXPUcRAq z)X_&+=48jmCps958Le+sm-MI}@tiYGQl5l)^+es{{{RWE_?NviZ@E4-cMoX%T%NXB-y^p1)1CRWWsYS( zw?j>uucXV+By8T5HFBe}m?gOdngpsLYperFf zYSO0O`)G)d2GVPKf4-$)zwadJ{#_AG$rtgih%P~2m>~W^PM_uT>bX1b`5^rB_^*Yj z-y6^4rorzXzQoAYx%|gTZVJu8m&D@fTg_KjRkqA{{NhszU{188nl-hF2kNR>e!V1* zZst3Sd%Ywsu%&87DoFMD^c|m)@9ihImT4zzAtD(xwzHrxFGZjr>8%ZVC4U(^hx?sD zxpsgsZTi{`$C1cl@!4vVh^&r_D=x81qNl|msG(@Wx}7H0Cg6Jodxgk1yS3)uxvVcR zdvr-kF0S+(Psyu}x_S2^_ve;5dy+TrZuhOy(%SmZaguvcaU#Lv!*fDHmmn97*STw5 zEGlW9j3!fiXEMzz)aI$7ic)ooOoc3IF}t7LsTCUJ)A=OW4`F)_L6tO!_UF_;iAf{! zr&*D^`?&;>lH2{9cI1#WTtXMj{C+17opI1-m)$r_eZKo};i;q`Y4Fx2POy%6MS#q8 zx8QwA{{UQjkoJ#kw`;ZmIqw?;-8~04}Qy*W3-R2cnN5KK2(J%4W9q_mMY^>T1wUJz%!^lT6dkB!12| z)A9595`2g4I%<6X0DN~g)#+WmSxnUw`)jW$qTXAnys*k7Y+c zxGCOn$AU_qo(e~*l&b~s?B;0mg5!qu^(1;3zj4gt!NC%`S;19qa<4H>mOskXBfezCj zXfyRM$7;8{XsV`1Z+XrD|!@-@0Q4l*#n#Gwz6>hFXe>h^gR$ zGbHlQD#Z*ipe-cQ%OMDns*9VE?a?R-%)|gV`46|IPR`HV;(@l9vw|JS>7;4N)`%{{XuWjSt|F&$5Yks=0!~)u)gju}ArTJPwVc z6zDi)SHRA`n@wHnUIvrsPk}h%bOvgcu zr;;e=qPv>|D(L6+4`voz!3(&G@-q#fMs-GY{te-gP%+m>HbsGZj(&vk^dEwMueA}$kQq<;dTF-tQd5sy8!SjCSh4)u z`u_mP{{TMK4JL-2C;Dm{Y0pi$J<*NB!S{KLwGJkillK`4sA;1heM)&)G?u^iLHAiC zh85Q|iizsRojVnjvo?qzXMaE|*0i4^CG8&K`77Bw?{4fp)0Ep)+m;$FyIb}mk~)k& z-;OLz9c3uVH7}Z)t_n7lH6@C;KhxeC^Zx)X?_A-`o7U-NV&*v|WsH$PQ9wjFrVfxn z^gVS`+Kz7IFKxZH z)uhd?In1{7X!gsw9vLAve-AkO#0u$FzLcExPI3PM|!glS)>#I6223UWX&! zk83LNj&QX)j|TBT3tkn_1xK&v(igQL?tFF*lNGpnzkgzrE0d;&C6QgflA4}_2J<~# zL(0%d%8xWL_{b!BpMh)pN4NV?yX^PZ82Cn48IhlXdki7WX)p}@E;#Z@qwL=zV z(c?v6!K^>0u;ko`b=%v$qwA5>F=Y%pjSfZ!tw|K8LU&YnT2yfG`ie6CL{xPD0M`5V zXfV|DIVUMv(My!b36eCKvUyf~jYyWR4HXc{OC+IJTHTab@;#LEPc9^v(%f3DU<5{# zB##a{BGFA$h61LBfSUBnDJrbvhy(qKaOgmO#g!wI!BYp3q-3Osw2HM}QyO_Aof#n|=G z?l~zcX>fa5iWaM&2p&3|&1{vQZqmfMrqfSMy0u#8kPo$&y9^J?_V2Z;tk)NebiHU+ zB@3#DhFH>{v~=vytA~y{08M>Gf636j2J5BO9YTp-8iZp_Qt+P~fFWTFY>en9j`~S! zHy=;0uvD8o)M(8EsqRp6K4!EuJaLbo4w#zNO6a9920z33`gLZ14)HkrS6$?HjUZ>P z-+8$z>t~nKFsH!4m~4C`02HiA3lVNE=lc83FJbmkwsIxB@*o!z+)7Cw!mULWIi+TH}{L&=G=MG+hk))J-*Qbfx}easUvaXa6ZKY%cG@3n0VE$S4kHn>T3^B7q_T# zf7_39#knc~83vqs#`)~Vp{I}R=}V5vl!|9i>dfE=EWkW}mKQc5{+Is%4`!DAs_a)a z=(^(GuBu3<`mz4UPgJ=xWI#Z-kxr+%VjECkO9G&BIrg?S1wi{pNhE+|o;d1B%zvs| zg;r9)n;sg(kFK6M_hJ^jJ$i5HvITtl@A#V)a9c%&q|wW^% z5uUq?HzJU_*+q{!o9G#I5=RI6`>NoI6V{s17!yI$fX>K$O*;t0fNE!u59!8|*1zNN z?fqOQ|}1e73pbd|RC3dAid)1*1K z7GEbIv$48>G=p*h;`Sq-YLU(ludhfX+fdYn`E?>Z!3|*KU3s%y9akiqAHnyqat1Iu zZMNW6x@(_KrAM2S(nN#o0N_o($K9*x(+{>LdpZL?LiQzg8){>A&MKlv^4rS2 zai&^nS!*N5#__#GaU!siL0derz~mkgh(BLpZf(7LdkAdp*op36O-B&EbpHTNg+D6v zB;^f)3AY)q=ZqLFlTZY9mLPy@<)i|`=T3yqvD>sAeSo8&ju<4&OA=3)$s!`nQ&%D> zk_4AXkW*6Y>@>9;EKC?pD|xSz;s2-6HUF{Jgmf8gG5gtJxJkG z#=kyc>boJ1+ z4nhig$~luv)RnQU&`Q66VvsT(N7wLeZ)oljWgZlY8Z+d=p#I*JTJ7%%@t}4|fx|8c z{Q4?8(`e-S+ao_>b)27X9TZ+nmJTsfDAO#*%oZrv3fftcKp08tghma>JOH;HqD`h| z-F9<8zY+?bC;6$bp9*m!sS|Iyhk3V6pL|;DG*>hnDeJ(3F-|q;c-S4Ojo;gDmvCd- z#XH)QCq`QGW3o{qnc#0xV-sAoY;CCs{M>sGZQG1Hm8xAvXvYk`YQu>C05`8e9n+QO z+buy@w$tK@Xe`TAzLVc5XfT#ABvo8wqjfeB; ze$`;7eA!;LRl9`$0M$jOtyhkkl@AoH}RU@Jc`N#WN8^w=~a;=K>WlNhJb76n= zzr*M~j%)Mk18uPSXRM95RXAT+wZ)GdU;XFXZzx)TbJYgUUoC;xn{h3!vR>!r_wd$y6JH~ROuAK+|#rDDdo#XoObZKjlXW(Kp*njrw(18!)i|`(VbY zacy|3OUPI>ZYmuJH3TrB6hAt2rqy=~Au3tiNgPe_3>80Wnu`4CUbGzkY~RZFdVeq8 z(5>xWq@u`f4~v`YHKS_fWs&j|Y}|!uX@Aki_L%F76MTtkK*1n?q9>^SHT);bNgW8eW1TsRkvBN^ot{u8BTTV1d@0lTTzdZi z3l8Kt2iCGM8QLuU7^|c#j*JqfmP7lrvLEa}(^4Pox6uCpug9~S{#>5Ie+E>lo(u*U ze7z5->oz$n+`XrsHlN;mYnbj*f@m0xaJlk7#D_X07-50~0sx)2H&#mpDkM+$6h(o0 zDM`>d{cu0(hEesn;QoD}J5y8OJq;6jWUqf|==62}0C&}HEIlS0KTn73d`2{+kl{DY zBGhhdEYR4%*j@hsMfSaki>0G*3{XRpe0u)?#{umP+!Cq;o*^t=LF!2R98uPX(W&z2 zC4FIG^-|yMHxuo5?g(eLZ81m>9~RNIS;$+1NYDvS`}3jW8S)Rb*Bmf8yzCu^wj(tL zi*0t@HBV<_v4VKsD8Gf)?ke`&7`CB_?GM{l!iYdRe;&hgz4D_*%p`|BvX2sYY+P0^Q443z9|sgr=|v#ez}3&L8FIew@bs7>TB4j+7vtIO0dcpF9Dc z1E)D8uaa167N(-2vYu*Mm1E^EHb;q!fR=DU z&TB(ZGv)H>L>t|>MuQ0hhEt>kAUc(1S^-81#*8!7iT?mNO_8;CeE$F)f0!>>)J>Aw zeJC$ik_oSRL` z-#^ioAR3=4sAVF&LF)*;faksIlr4FK+Wr0oUT602eIgP+;zrN9JD}hy>as}`fvMbv zFvK{irB1x3R@zwXyUNuS`-!K_W@;Nwx64g5kX6HR$BK!m{3t)Nt8Z-XmWS(SfGs16 zilh1FcJ$)=v^WRxcq-Sxl4CRzex!ln~1C zyP;;qt~Se$sDK6pQIyt&1eK69*v`Xh-M_SV7C;?S z5AR;i%nhfTqYQmN#bCzHSBoBfnt{q&r0Dn75yy95#wZWw4wL@chvn7<^G_yy`TdsK zZ?^77=j*;;0*zcKnNaP%L@F2%vsZK&|wf4R55 z>D*l{xG;hW?SZ`d*CUmvuG=;H8*t;LtHNbyV8u-wa={GGEhLK3$g8KAhncoHY&R>g zZS>m6>|-O~WIQyHj1M7^>DNO&j`u%p_Y2#uS==DqjNHjtQq^wluTn6xrPMAK zNZ7~;R%HtyA(Wc+U43`BF!*l7?9Q!%)H2Xy;N7?!d)X3PZfcepGO3PTT*FIW>d*kv zk8m`PZtixIU+p_S?m=b>V67N}^c zywOufeRUNKL~v52y+!4yWlk=6_71zYm&JR3$6X_$`-|0qW|iBqYERfd*!1aV^S3cY z{ru~{g4<%bDmr)J<{E=~{D-Tg^uKF-!`}4AHNIy_LO^K(dNQBjAOw}bNG~oWt6d@5Q=;2?|JTR(;KiYDA zl%x!5O62v?m~Mpot3~ zKN3Pn1ImE_Byp)7N5W=vc(=kzmU`uk{K~79)ZW=HriTGV16v zcee(pWavf4?z$ef~m&~jDCnNS6j)*rtMc6lGrS91qKk-n8{{VUvKhL6XP5g`h0G3@I zWMvnrw{1l_%<_yKM`rHXFqU@IU^L>nDm(x&0Ysw9VfY@zi_d(>iJ@kQA72e?{txnW z7(UPPtFUK=;KiQ9G@5hruMaQyuA2Kt`Fs2_`23qwJJo+4_7*aXqT_4oGSm;bD@IQp z8c9i!p099Ek(uhNX~X#+fMf*!0BYXj4{&+Mom=T{6PT`2&B0bk+d_lHVQIvFgQ;KJ zk88OG-|CI*K3UoMi zM)s+OvV2`c%~1_XOHo5A5Ec+@Dq@!KrKji-a zW6P;gZV4G}z*Wms1__Z zAl#F{(g79(AJ6so=7|sC%{pXQI_ESWK8wEM-F3aaykyvTO6saTn}XFY=dY(WTKcGE z)8Y^VA}%JA62#cb2!KBv?6@E*M$#bP$gHNKuO*N=q<$a>I! zGCaC5n|>@d+Qq?&!qY`XM+jBZ5C)>5)j;#sPC$B^htqauC!eK-hp`M6(Obl@#-J$l z!TkPzK7zLqT-;95%1)!}!}9rh4xh$dfYcxI2m|U#1lW(Q!*R#w+mw-NN3ThZpeIW& zmrNVGZtcDIK=fJKM3zk~X|ge@CQgP?{itd{)>gyRjdfwc9`$u?YksXZP1jqVS#o$rf?B<$p1iLcLXrab;VhRhsECu{ zV|ZCjy(}!BYHO<*&4t0&ZbebQ!aiSN;pL8%?v~bf*6X-iE{lL^BIEKj^ZR_q&!PC& zm$3|gA3}H^P!B%D;D$8^9S4LUVx4f4DHS|2&r>vTK~EdaH1kNQ3{gfkJd#MnENG|+ zB>TR#MPkGX4n0uYmLLT+K3;$9^j`CQ;g{SQH`_f;iI+288Kav&Q4+lb1Rqqe$06{g zHjqe~b7RJoJbNRTeYl!aZM4I!{Md|tnx8ZK4@YUs*6~IzH(4|x$Wep;02lHfx2%}X zmYX+NGkux4D>pVqKv}W0^URb~?&Ld0YT1@nL_7tFV@nTe;Ml&UzN2%wX=MHoO$W-n ze`PvNKI`g~`)kn8hueE&Z=g&z-^EZHC~0D&iRu_Au-8#Hl4d{a zx3kzRt!;%Mw?+K3`%ZcznroYbS*K?F@%sikQVPdV0-Yd#WmE;^8;c7M&$T}7bcif7G~<8&C)O`>P^89RVLP)q)Ue4L@%{pJM!T=&shF zs>ko1u-dtZt06GWGUF+z>nvGZN|jW|k|goEg0K3Njt{b%zFyg{b3WZ3za~+niu}hy zt&5$x!~<@!Hn$dIKdOmPp(;icuXxUzo?ZUzj->{{Ufg7UOHC1~jcIjDOP%AF`m+h#h7hCVPX) z-2G&3xnFom+$b*#c26CAq=~zRe-PA%$-KG(cJ}zo(`PruQ?#?kCPspX!zpC(3M^GO zjf%6G7D(Q1e1Ww!?d*?p*es>n`F<4vSVZqpn(L9P@}Z~Ur3XT|MyW1+1A+X9`Fb7p z*7Vay37TUJvS^K>Vq=M+Vr6yE&nyjj1=jwd_#@nTy6iQb!X~5@HR5Z)X9tHGW9{nA z5v~PCSN-v8D@|R{y>(SfV-%RWycVTl^h?p z#CrX`bJO1RboWD=#EX+8M16)B>He-A8G0JF(%^EsPM}JU(!syv8z1S<*W8H!rmE#> z!>ER6(CIXxuS$vxfsCkf)@27t)4(V|QVF>P{W<)5G`Ap7lbUe+y*ewnx7F~0)08<) zO(vkRk3mc6AON~rz<+3)pQ%37tDfuu{!WuUu>onGq^)Z>Dmb*dSP`VQqCgk=fnq)0 zrkZdw(|!#yX~U_XbZo}{K+1lfMz!1N1ifeSP0ma@;YGF00^>bknC8E7?{+ zuEs!*R<`=wSdLTt4X#J~$Guk|=luOt!U(33)aA*YL?{J-AT{~BaBRA`UvCB` zv|gBNWdkQ27e3&ql1|v^nWtqGa8|ytENdkxkme{a8#x4|tYku^xZqmH*iV=cw)e}- z-`R)GG4ZZGUR?@y7=rA)!m)#`lvCH?IUO1W%4rXFDge8dx#V2gf5nNnv4F@V`E(3x zLEAx^Aq%M>FY55C3n_0={Qm$?W^hA17U;JZEiBZ@C;T5S zi!LL#o_A||Wr`ml2l#$|y*r%AH18ClXGw&KBu)z?k;tYuib2ny#>5f+Kc99WXf+iF z{Z#z=XX!y;ML`~a&cC;!q1V+_U3cC)k7rW6>9_Ngbr}qOE3kN(9-sJ@K13nC4^JY` z2LN!kBiJKuiMGyRxv)z8EQ&}6?9{)o)O0o6;!W3=ZEvK~ZlhqVeE8`#`$Z2!{F(N4 zX<5mTNO@962JA|XIAg)~bmg@cC%U}{*2hQ+2W>h+cHaL0hiLUbVs2S##XLAojk)WD z=hyr6*s8w=rQKAKJ1T*3tg!Z9yG|h5HyKVT1eve&PeLwD*q?Ui4qDq%EloB23RgS~ zicb%aKWAESCgjQFve`Vbt*FS>)Ko=_p@&;Y@vIOLQ%@KGJKC;t0xPd$Pe{;^l5e%^8ER6+cYp`@V!@)#o}ut z^3vrurb3r!!8~D6qm~Lx!=_o`nFukz+XQjQHs{#?0BGdCV!e$egKBu;BA~blTKt%U z{HgQmE9NhJ{i)@7-qUjC=pOA&87;$HGN0)f!9Yit*HOTLan;>?GVA{1_>-{u`vu&z z7`=|j;8Lvpr%-NlN+?xk;^_OVvtUmPEo5veID?PU}F$w7^>1PJgBV12M zTS*}jQ`ADqH9V>wHdX-pSzv|ZcoJAKPVc^hh02O#|YN2oOfV2+Z@vx$_($Vl_+ zLeJ)N{IvJ?^8M`9-n$yAvv&M`-uYUT*!!vDFIkI`$KAfe-*LnYFy|;@xTLEEQz-;q zR0%4}8s_J=oawXsk+rtldm6{S!l1~WzFsU<;-~R1;3kHmhoE7;<}Ysdn|1jQ=(gXDPED@Fu#M7Gv?i#<*%DO@bE*=ngA{`EARTr!b%jGxlhvHt*H*o$!G zsjOr%ymeFXuoxr!{{Swsvy?r{+PTYZ`r9cqT_rqNO9Jt?`B0yQ_#Os_9SwV5bV-gh z(7pq0W!@GaZ8dc%$7N$b*;sS9*QBpDzojH;6rZR*$tKyss4%O2y&7KM_=Tm9bGm_# z9Sx~JINMVFqydhOzhCzUP0&$6N!*|$#(eEC)-?60|MP$~Mc+K6lDlyXivUB98 zocf#ArreQTa@CtDEn_aP=(r#8;73vR>3z>r&R>;1!r2*g<{Qg4EnMV1wZgd6e3>{7 z)1HPrrc2|#W`?4>tt$JPHfZ(ZS9PynW^wXOq%o(huE9%%s;2ceol69cpj@dY-oU%A z$zu?c!%LNtoE#w^W;FiV9<{Xd2e~%WK_4=mh2tl@+Z))Lo<$O2Dz~i*s3g!32S{ap z57Pet;q>+qlWSr}ZaN&r%%Z>Ab!U5)j!ojfQD5KS#M zI!98_LbX}>Dkf;iX=fn`ve-!*Cfv=+)>_vQZUg=0m@5qV5az$1SYypRz%73G*OpLR zs*T%_Ce)ysnP3epOu&3h4XP|)@CpdYuT(v;=2&TWRsc;MEVv!XQ(KKJpws^V3f%P3 z=V{<*^{A4XDJPXc1x#QKBv|`fxovclZ@nv3n%paT>xh`i`$z!%^Io#|+3sU|csZY! zQcWhyaWcdPSHQhRxJ97+A(_-tl)zpGr+S^kkD>9VQg|`#EsRxe@BA*LAE$!8#ub0| zhbqJIf3LO%$t1OC6I#=N9mDef054NT$GDp|$2?a2!MLrIkMO*q))x5*iuhr_pzN*a z2+vQHRn+wnut^}Pf=~k#c&CCuf3m<5t{5BGk73QnWNg(aeF*;mCqp|9Ww*OX?yT=4 zmM$TY!w<=npY}Q*w%^E3&f2|SxVmm#;FX;@oruj*u=j;7A8>75yOI(tv2Jacn}(LA zeTBHG-mm5?|#_8+*mz82DL(dv@b@FOZ11L}f=t9;g>)IRMV=!%jb@NwKwl!?K#Cn_!_)DCf&(X zl2*Q}2}wF+DMOtidTQ!-F-V8f%-_^s+v{cfrq5~Hw+KjrZxqUhh)D9eI)S3+?dk>NtfQ14T1!V%j~gpkg1*7~j>j#9)y1rtbZUL0h$HzuCw;Wr)``jzG)#4_=pf48QkpX=FDG%3?Sw8ME*^Dz=K8T!SM> zwqRFF)Ke%tA4xXn*gS2GdA{4)qK#5aiTiP1%D-htTIT)!({1I>Vcl*U^et^9kd77b z*H9j#QSBsT1B~v4+!fUsE#JR#nI6vF`D*D5)tNoVxo4XxN|o|AGFgFT z)K4fa?qS^{GhRzvgzX3YEz&gKm$OJ+kGGp054N=ZURVPI*BAM zN%i&py&7!p%g0mo&f(nI*PUkBlp7naHeD<;h~cW;6`5R?=HB@U+d&m{Sm?4c#Tp$f z&o%!5-FEgvV?58h+1Xm4({R&IDI%ms6=R7P`u3mQXggZNp>D-)4Lr{d@h$IPOxjDe}X<^lmWx$>oj?ZEaqipE029SbivIK)#5 z<4OMj2VeixIn@f(Sef6jVX z59m$rV0r$Y+bjI~4_#P{g1s-OH!A|Rkn!{b`rg9BpLEXxIwYTNp(dRN8Sc&8+wVV7 zu)6lVP*Ko=o2PWE6C4)Sl2Ou1gvbyuD12vJ(p&-&N%kJRxx3shTW;H5N-y@3dVGQZ z05(baRP?4TrrORCdwiOl{0aV3^ZrBaJuI-@X|bs&{@T8tzb{y0y!mR1>WC_&oQt%P zq!Rd`8jaK)Tw75--;0-a*yGb8Gr8i#kZba$2S}#6yJysdBKar)kFz7CH78(Avn%l% zb8uD5HY*@S7T?ZHY^b#1BZC{1n6PK9QEgHYX4Dv10s@%lHWEc^a@B>fj(?J|_4Pd^ zZK*Efns^Wi7cRfyWgbK2(53z4btQa<>!*|S2K@7IKgXY^vwC@H=(z2ObEoIjh1_mH z9$s(sB!5r$pKqvBOmxHThzT_48Snb>U)8&cq34DN!+ow|IqDiDh9OBhq~cj5IwFcn zd6+Rg56`gw05#h9`yJ6rYmBRp$mjVUkNH~NZMUmx9@zsSr=3Md>?5K9hTNE{sM(~d zrFFW6nj2R}@vKZ$8fY2USC{mVR?0u8xQaDK)vBN2>RS3T2r4nsyKL^Po<6RdAoUP^ zwmQByjXcrD5-P_rOzi_%`5{}A^*mqNhy$xDnrKt&>+lqEDq644>fg{(ikmr`(JPQsij_t1A!~ z*jrFjz`y3+_Nw61`Hq`=ByQrlJVEs7uX}bG+j~PXm=d9?ikIzZ!F?gCD+#8BwOaRt zxqd+XKkR+6d2-NO$t!$dW9Ci zOf|H-fY%@sanIE17qLI$J(;Oe)dvUj9T7`pK%r1b{{UAGonx-`4o4qTs{a5`PuHKP z`u^_4LHM#bbY9k^FTuyD@l~-l48uvi@AVcJVfDYiC~ve6PLoLj&>Cd<9;Gz?byRb3 zuCg!Sq>Ey*Df+4Z01^FtzZ-@L_Wr}t7qEy8RU1~G?%vV{(_)9YhvNSLSCIVr5JLnTEvnqiHD5UG9-r}EXY%OD?Ytfn zYGUcI_$nxb z9+AlbLy?ao)?X`I{kPNpMSpHrrgZ%JUH<^D_>cJ?_#b|+ zThcn^V8Z-j{*%r7$AbH=A(c zDUuRJEB^qNK)<1-UKS4LpKmWC199c@(pg57XgHKnQc7a1Gm(}b((=x4Xnyh*Tf;%i z{Qm$fcH6_1RJ+2%JA5EaI71=FclK_0=saqkpYACPo=GGTuDg}BmULpQm9(#=)uVMG zmchZ}+z&dej1a~IpwNSZPw1cZ4zluq8hMZPf2+v(b$9;&%e%6ZaCK%!V%F8te-_%A zYO4AeQf4#N;IlIc+N;7?nB%6&GsH!PpGYH-?p*fYbAnqNt(S!M&8P#!qw)J_+(@s) zJ$l0b0KA_p$!E-ae>BAt8%x+kay2_vXoUc;t4Bs3V^fD#H%&7JxV4E;2t4UOkLV5k z%5edjoPVfwjI3!vPM_)Kmf=gA=?vEd*jU(>A5r=Kocl0JoY$nTqLrq4dWuVswjh?W zwd_c7{hmE+59j)OT%1Km+4=O1l;_j@-{9&o%}_^J_@Q4ExhGYUN=RfAOG_D6K3cIG zGg2&oSO(;i{yz2NLb5bL$BpPSPq)+a>fQv5t2c&3L(K3$A?x{c=M7wiYzbqe#9!v6s5J^Re{y*^Z@`nYwS zW>vnXHe~_L&G;Ht$^bgSA6x!?+*8l07|EuQpDv_|rCCFxaD8_qkfeoC!m%epsRR5^ zw?!*a!=}6vRE8Ph{$KNS!C>inksk_qMou?M2@lF?B;Q279v1Ylk7XaM%KH%rs}F% zFaU3m6$Jjmc=RCIqx!9;>uP@2B$4S;LI>>w_8y0NeZxhSiW>SVu~kD?O%&8}MRTq> zBi4oNJr*BP{ZAgx)=2IG$cV(H5DmM1VpfE+?b}NQg|WUeE}dN%~DAvoxaflt7@<1fQKv2hOMRpMLNA z1+()#{{T4dRF7xb?Vd)J%@JjFDk@L#r-+qg~J*wnbq<=vCg zEnQVrWO3whyAr0f3Yx5D-G*dnDl*jbNLFl%FOaYz9SAN(9Jk3RS0GVX<>u_`fqg7!|Hv9_RHC12XDE> zMQvs7z`~Q|@~=Ze=hENj7z4-ku>5@w{BPO06`(wSmqjOUZ{Zc|GH0VDwMZ@n&D7rd zxv(O{`=9`E9cip26r$s-!*DEWqs&w=B}fFDe~;(!?@dGm0o4ZH&RUC7I^;J(Dw|Xr z-&MFI^KMDM*ZO-*Wl*GWKj!}cKUNz|jA`Lxs5wphjlcrrk0|m#ApJG zgp3=!vdR6FKv>&>?Hu=!#~aAZ6$hF0{{UyD5NvZvDn^hNay+yCs(;1wQ}>My6Xn!3 z+e@(U6nQ>{j899Fz~*97H%&{%W7G&@@Z=*>S{dOYN)hTu5}pgTee-&cda>Sio9S%+ zmO$~k60TTgpV9||DFsU5fv-lJhc0dQ+ilH-)v8=v+{RUvhNV^Y`4DmlAnM4aI@MqK zgnud?&G@CB%=YI*rf+_9J5y^u>!1#HZHW`XI|*xar8 z_MUx~-b1Z>Sb3?Z=l=i|(SNf({{8Q{ZpPn~w-0X{oi>mHtT(F5bf_>F>d5aw<>M=m zI3BgK?w+*x`LlZuaN+u&e#hCn4vneT71&F+vYl4h){-T9-5XwP_DZ4(dPE6@wMHy>SXY6D5P@zh!U-CqqvTY8$P)@9>{wc{!LPNnPQnwlC+ zX+A>wc`6ih>^R#_<#_VF&C5q%nUJUnQTza?1eW1S`jgP3a@#pKm7=h<*!gN3u4}t? z7O8OZT=YkvdYkz}>A7EMvf6DXGI(QDk{^m$o4Q$A zo^JIZ4~1x>0Cbw`e3f<|a&`{cq^O>rnwv2eR)@n?JU?VIQZ%(o8pO(k)ae?515J&& zKI_bTPl>i{Tai=Zv_%{GMFkhrJRlA0NI{zNP@)HJA#6+255gIHz;CyX$${C|(IF4MHf7WcKw z;dcv!ug|;uy-B?Lbho^N&X&ukQ|*@@^=*w$*-HLhEp|rugLQ3vzYCS7%hclWt|@@= znu;uKBox##QllF<5Yv+)4^p#mEW_Br>_1xSDL=GHSQGQ9IOwBg-WFa}<(VLAMJ?JB;jisPHsNKRM)HDH5Y9GQpi&v~&=8k#Y`5sKT8L80-Jl9x1YHwNtgt zyz<)ju>HnA*5{9KOJtGPd!)7oBoxk({tlPeys0{D*7_C~`hSP`9zC>0KF)~lZE|tf zd-HhI?cJA|$KR!Ngy_8X2?I=`GEv!c%o)1Z~CqMJ(up28(SIWOgR)EX~#v- z?ddJTD=%*o`DUFy^({0zb7tY7j1RlXQzly@G5-KPHC1wXP)Q;6FoFg|7yg9)eYdq* zt*wkJr@h9eKBW5ngQOdbel^U7he$LYnEwE0p>jOK-A|B);15>@*B??zurH15;TeHAPMv9W6sRDq3fzjhWuY;IQZFe!k7@*`C_kNh_$J zuiH+LPh^WU;a36A54WWhd3U)1uC407BFsM@Q~f=wR>@lQnXJ};(<7v}WHcGhzTUX1 z*o5@8`)4f#@G&K3i|t*^Y!CI*$Mp7_c8z7)_ZZw&OfCF{dVgxS@OL{097L=9%{r)R zt)$o(dATE7=w1XE3jo>!WNxmAtnz?W1^QuYDv8;(Ke+!SF516#2K`E@aP1pHpS zdJuM2{X4Rnrkv5iOOU3uK6Z`nlhV}DjY&9TXGkZJZ_V^DEAf1j^- z34`bUtn_OivvE6jZDKNc%JrmKXrqoQe_XY5R7RQ}IA8=w;dES{6n;qdc5f0GBYBN6 z!_W3~T6Xg!k}PN|{!WvT{D!~~wNHiIk>kn#0D<3U2ZPX{G>oC_HGXc#`uk1$(hNC` z!k<38c9|$tFf2U3$<%%Qzp)$JXyKyU*$C?vzjR~i>gma7s;QjAA&xqlb|I8q$sbj1 zHw61jeKc2A(fBS2X$435$5n>O;F-&z3J~YlqhF57eX7Gq!EH|rFhwBXDx^yig2L9} zeVcqVS_46k+0cGVa7L`q@%_GIrQSNR7$DWp_^{^p=UuICf7kbD!io+bFZOyVx`fq@ zE7G2xp+UJM7t*?TvvX})haj)Fh)SGs{{UAWilvE-C`LckN_72CA~@1o#2W_&BfU5Z2#sm-+s5>1nbyohHcJ*!%@0q?QEpWNLr` zt1>cx)l;z-1r_}fkL;p>?QM;c*xSbf46hUFe9!s5T_n7?H*-Ai!0;Y}$bX;b(19C< zPf1@$01v>p1hv8Xf%*2ohyZj@;D;K4&shi1AZv~az3eW(L4JAm;(_p$Q=TU2a(j3=h?o{{ZZ6N4qJ~OA6}$04G#<)%#kS4-b*)#T!t#{QeKrAISWBTCGqI zmqn5$l1G^9k>m0H`~Ek7cCSr^1dR2@{_E4A4!Z{b0Gs~+yz~C^U@z{&rrBx3hh6^w zzCY}J@2w6w>!8f62s&6BsRq`u{1Ibu?zKEeP6Y%IMMqT^^V{J4KHa5X#wNgx*#4VQNzg`` zdFnpm+TF2?`64>wO z+P8}tz+s|ARy=C0f)ANrGwDEly38JO}5AQ_V?Q ziuJM2QFhMJ?oE}6-rF{{XP~d8fY#&WksBj{$w>rr&4|jtjj9T|b0vnL7DcluAp6K& zt97&8t-hwlO0KOWd8-3TH>b$(BOvw8UT@_M=aTn{wteaiGLGbM4vAy(k}`OM=jNuN zfFq&59_2-tt6t1Lq!3BCxg1*m0Ph~ekW?>l&mZ`{fs(EPUK!{w?rzPSW#XuD7&5K8 z^WU>c;?UA#sU&d_u2f|$_Y+MZNN>gN-+}DAeBD~cC}Fp!*GYj-A^cxy;5sqccA3yx9^rD=bDb;&vXT%|lwU8GOUMwhVz;uLUr+(`n_G@b zx%Ouo*HPj+LgWAe>#|)NRnMiAf;j%q)SiC_-sz;*txz0w(?~QQLo=I>4TYI_@q$a_24r=Kpi$Ttd@{H&Y@)tY(m{FVZzyoKh*nZR2@KOy(kH)t4ws_Wgl*X z)a~g9{Ykh4`o4j6e^d4P`&UZFyn0WfvN1HL`oGow4zLREsbTcE`U}{816taMUv*Y* z#nXlWJ|3r0*Dzm2hXjx859&DrB#qO>EHW;% zm`tS%WeS~fvYvkyKaY2EDB72{l&7tHy7F5BRIUwp`cuxm6ugaQW1+Wnn~NT0tm_Qh z$sS^uEROg_o73%bTT3E=eq06(9h0Q5Ik<**yu4vkd}E>|CtN?NGOsMi%SQ7tGc-?>LK zC;-^0`iuJz&er>c9qO+WP>-|A?C6#|N$e*f8I{(f^Wc8okvTn}BrgslbLO!0a>iDo zl9H;fKP-|?vxbVII+d1`BuWy=VnF_!doG)92CEI*#)pUmk3S<^Q-(b{T@BCxG`5KD zI1&ai=}I5Zq+9g%-l&{On%p~+I}n*D%>;A_{-QB-%dpB=pcV_3wL5sj(sb;LN zuBwzEjtHYVV}*4qPg6C5#}ZxLxE|8o+(m5+w>J_6f;Fip$bFt?<JB0lhJ0V{nNHsJ+h%Rb8+vGZ$J>iZ& zZFvV`_RD9v2J>-dxW18aWK=2w;)g>?fDK7V$EyQt=Phe`&-e>~IUN2y%H3je+c%e3 zB+V*Zhb3=o-}C+?57GcP_S3inBRxAElewV=y+V^bPXa&yH@Iu+{2f11Ik)%^W%A_q z^kW^J23Ius^ce5WtxdaSrp#k&jt6(*!ZtHE0ceAW&C;5?!UTmbJu(Zjay?7OvU~lt zZi-D2(RRETWA@YhJV!>hQZ=w>q)m3M#edCSl2qN!6Om40HP#!&@8;!-U>F#!{DfrY>AM$?B+0wJJ!Eslxom#(y@gFbvzuVH& zAKm){Bmt$}Si~p$83`nym|S1uFLyekNq1kvGw&TgkXz7fQ$xlqu6ZCi?6V*5)>1{vj`yi8eMr{_h?IRu- zp#7YBI!;{Bp{`_9Pd{JV{;#v9Dr|1<-?=!meVbnJ&{JRRwygxFC=jp*OyU_NN^pLT zbu{g35~JG!!shNlE$emzgd9KB{Q6MKZ)q8d$uh$&=TGJNd2~GEv+&T<(ooa*DJkh9 z5L44rD2ff-(prAlJ-r zZ9sx32qVmTAG4}b`HlRddY`*$@*C%(>hV28zUs{NIUTPwQ~v;?y}?-_ zE-GoErdo=Pp;t4X-1|u6qizb*p}wr6_Pg&vzVf7S?L6xX?t3~=ETE67iARwpf_0}2 zWH|G4ib0(9_kOV7o%bG9nQXTv$&G>fc@M1xS|jVE75<3xp&r`!ukyFzwM(x0*tw`S zF240>&?+(tdNL=2ck28%jr8F`k>Q6V?%cu25IUe&{mAUiU{{VC22V>r$ZNR7| zGx}ExUnY&{N%hmLSA!n0=W*Np(Du4Oo1Wh??TW+#e_Gjq^A5RM`Bb4EYtUVX?pUcM zNvfzTv2_Ta@FJ1ptA(yC!^YuD#KZ7)1ME$4$a2t&d6CDV1RwKsve(_cw(UGU*KLsj z^FkeK>r62DQoSrscw_1j2l1MUHX4SyTzu3rJ;&*n?G*!y{{ThyT-=F#D@$O1+Yj>e zX9u`kpYeT6ls-=zwLfSie?FMNL?t>!NIhWV6Pse%>>6 zy~%5PqH=57H`Q)X=(LX{Vy;I86!koQT`r&8D{I(SY2|y57jv0PsS3)Fsl!Uu0)aum zr^H7}j5Ru7akSXneA7o15O|(Nk&;S@8`V7X6e90Dq_O^&_CtNQz1_suG9c9Ffbt$d zeS-s`j?H&(wC(m=Y%QuNSBp}t$1LaO%~F2ex}I6WkhL`*sE|DKaK`+Buj}m)+E%%b zp?#+@`VrDIE1LUR7Lpj>BbJu_3MG&dqQv>C{WuiTpVO7U(Boe+az+PTV5nY-Y4SDmioDfuRjR800Cm9v z9Z}=xQ2zj!rG%UR09QPpWLv(~;-W(gI&BiP9%T8mda?doIy>cEdvv#3zU_JST+Ma> zns36WJ{TY$f)w-_b{d;B>0oj(Q^h4sM5`1KM)OT05UPSyW>=SXz%_9io zin1}Fr>VzM5az3UC?>nRoF%kKS(xwu3X}Uk&C*k?DkQ6^&u8XA8|Uk!tkS~LEiy?g zG%$jB@%X`$kLo?7=IwzYips$SRs;)QDv%2wwz%jS?Kb;0@#a2ix>A#Fw{0i~h>c6E zOJCuoTlRD;PExL#rj@@3eB+ zX3g6)E{FZPmEq^dp!;Gs-0i)&Fp=V^!N*mIl&h7MDsh#D1#s(UR`Ein;>4bQgnK>R zwpN34zM}TZ%OLw5b$^7OfnM5g%X`VZypq4`*(8?F{+bC2f5%l#PZOR8q3a#mJFgt8 z6qQh9p-=^~5s4*X&(@|gld-oPlW%R??d*Ycj1QMX`S)0!q`3#>{;G5{?Ed516C+KL z{x7$8g*A36d=5sAwIab%M@c0`MP&6g0UE#flT`h&qa(*1If_Ee#ndQ**KLY;WQusI ztSLe&q#A~=twt&5&^LL#zk7>#(czP4F-#{{1iO|Bv8t_fgagDf6H-A{0+l@-825(F z?^>)SR_@NyY@XN#l8kRJvY?M(_Cm!WG*fQY$HfHOV{}MJj!dHc#1&+NFhVu^MQ6*` z+^^ydw$$D7@j8TBn9pxsA{|7DV)GI9vVI!y>I=Nw_r5|~*!Eji+&MUwZ>J9C?#{H- zE%lNvARiEevE#^$u*YBj))7*zg;eAl54f7^enIj-{7<+khj9mwUqLSjF-MH)AK>X> zj;>(J0}=-o=j-*jzq-@cqKV-IaO;-&#a3>upIwQ^vKrwfEnPHHIE`u^l0xkXcJ!;r zgz3G8tAAf*yQQPu*~tuF9YG(Lm*>%1D#1Ft{6FC7bFy-E4Y#n=xhN&at^Dz>`%&!*(J z^u6uHy{e!iqUMEoX%*-o?aKKw^;<__(M@`+_F5{c=;I{3Soqk*6Uk<_olPWwAFq!7 z$Ty;Adp)@ie2-I4P9Nt#mqr_OJ`kShj4IH5zv`gqf29%A!38xv#5AzOO%mUQiU^V@ z{{R43#)I+fK!_9~FT$V!_6&4V$XK&6$u<4GPL5_4wx9vMgAgozytOUErrs|q^w+y; zyn9P@F=n#hGN$00+|f!F-2F*59@^YUUB3SS)4_lE>FaheYQM3d{{Ti`@by_SRkTwq zXquFjjpJn1bttUEU#CMe3vq97XksX!dHQuQ6j~PY{{UB)L9XI8J8N~)?;J%u?6nSP z^Yjp1R%&AjVIexSpCU#D>~89(>QAR zYMD})sS+{zudC<)nV{yng<4@AW4sU2_w; zYUpBXS#lL?tUZmx7~ZKE5&Z%7UeYAn^hr+0VyzFU^!=l!{3#;YrEFGdK(2TX_^yY* z123fW_$K$_+z;w6>_i<|Y7S3CE~Q$8W2rR6s}co(1h>#!6ZAL!zU-$s^650n3e(J< zoEbHZVEt4Oe!uGr{{XH2x3@-f<wEC)OaTN`b+4!MGx(aFca+U{p25dQL$LRZbxFJNln{uicBbvA zhFKpa1Q95Tj~Td~buGOKSY1uLiF|waAC*6LZq{4vg}D9SJn9?)@Jdgh9|Q6EHAk2o zbQA97?z!fTjrk{jx-HCBFrNk3_fKrTq~)c90ldt5TRK>RH`AT#y?Q4ccW%zim7Y8m zB$*mYfh^dp)F}*YPZm=gp%S3QtA@CBCc%K?+)HD7x$V5nlI?RCU9Jk0;*7eDRe>}r zPY*H0NF?=;9M8(z2RLk>ySMuxJ-A&++$4#JrnuiFThwqo2t8bXTYoTaw#wsUld^F& z`zm-A0g$esj$Gy@KQhF8?HUMj6!5o}-~^Jy*b)u>$-KYs2G@0S4UY9?CAGtv2T#tUY?QX!ZRAPKB;X99&u^c@QwY_ayQapt$B zVv4**6GlTAj+)_Aj$gCe(I{h}#*wR3>9zF%$Fa`TM)SSRxIc6eQ^YsO8s{1z6 z9^LTVu`2$x<0td&`#L&GrO9H2j-OPQJccIzn~`wbdmjZP*Gc<&1QS6@{#|z(O04P& zXdb3TQDz89)vJOC#;YGNqZ`W78bwhCs(L(a(%c6 zeOiSFRnS3E$NgC8x}u>GSZX1Hv)B(x=^P*cfLZ?l+k2x@pU1Lf+raJUhq(;{zWQ^R6YyrKG{1*5AzSKuuImJ5Bj2;5D z>N8|WGXr7D*m7^_7q}+hQ~tlbtxa*BoDp!YG1oDeR8~Z!p{XqW!iT1G$ z2pwf3NRMMxjdR>E(k+I2GxpyCF?oPc#*< zLsd&qN>ozM8cj_!TquTEBn2c^BKAK^U)wH=BCvG@TD1ovo|Nh6qLBzOk{EC!2l72s z=g3~^-#-_7PK-rKEq24*RI^p>di+fCrCkLrEaeGG3j~THv2? zHvN6Ma>nhbQ0>y@G6|>^p+XHo(s*#e9c0fW@+QUZPb_%0_a@(dwIVsuz-ZZsC1qVS zbq*;}-QF9@oe8@a`Hb{F;YkMK%j9--N`w)%R~cII&2l1Q{{UqjN+gB7X2hsd`Sy8d z&bvgyv$I7105C}W>0h_gpyui9A3NE}rpnSAw55MeMHK%4dn@)+k3-cL$$py6F02<~ zVRI_dihJUdBVMu0>avi}4GTt^P=ePZN#OJB**C4Sf9!9StB%^ApOEzE9d+&RG;PCH z<+8oHg{@?0(xZkoI43@puSiYv@-AF;JcDEGP0zn_j|D-dSPcdb3rj34(M9}6C6lO0 z1TI%!?8NR;dK)Y@1}JcJ)bQBD;k{{VmaM%Wi{+WQV%{aXKn1QIKX4fA)D^L)@tDy^*#IjbM zrG#`;2ZAUI>r+$Jh5rCAZ@1W8BUiUK1c`**HJk5nWGk@QNus03_>DF?o|0vTVxCAO zjut3Xux@O9$sXM&(Cl)-bx7`w!yPSyK&l1}IMCCmAK&YXeqiTIJH4*qE-Yi);!yFO zOQ^hz!lTcHM-k`I^?cE{>-|IPtMGXiJlr4f_C9AhuTYBZ;=d0Lq0O7KDDqz7$@1_y zBkF#iUI-xb$F^B$YH$ZnC6gLaIP~3BxnYJGM9i-n3rPb6c*?baG9-bJf)C^$X=Rpy zwF;-F`A5*vRj-6a6xl$qsSUvv$*W=s5 zIMjZOK~}l);nhu?zv!f~{{RQi?dvM%01`7w0s5?Jf7U$Q+*lv*zqbPE3~NKve?zU5 z5rfxlxJbN>DG6ZO!vSIR3ZSz;1beklA1_|1`@9a&ne^+bebU-XX#z8K5->6l2i3rB zK@au!bY`YO)9c5ozSg0X3V57p{;oYoZRWAF1(-6ZzYK@fb7Rf_06#!U$q#Ab<{;&3Wkv8yxzK*JrufbJCSxofx)HP78T_t54s>wAqWi+6}Q3T3t$m+if5`m&aVr>Br5T}Ln{DPf#L`tf)4@@mmaGp zgn*a#T6AhPf;wpa~<~>Nm*iquvURdVPR{Z zbFU%&;yvNnZ?>La+IRl|-ZI=z95F$3qGHc0ghdh`)mpOw@z4*msB4`*@1E7}Han*M zy6qpk;)oEiY))&p5^l{9Hy=oh@WlRV3mt3+ z3e(E89dg&0nky;g+%|2uaFdnY+rgEQT0)9w9z~4ymdT)~9=&&u`1A4)W7SmAuE4`& zo@oG&?d8vs2`2;=jwPx8+^ z9i}NIvyKxShOE*ntB^PiUQ6dnanDPd4xI1m*GS~*`Ka1L6g>H=W{F8Q1d4d)k(S)u zZ*O7ym*sQ>jpJQCBQ^eH4u%Qu4Vo!3t-7%P0EbY1%_RQ-G1NW(0MfnZv~gc~l-jaK zj;ThC>+p*`T}>P5yRMlPC00T7bwhD`4{dFe^0no_RJtZrI9Vtazh{@opSPqf?)B#E zliF<8cB>&=nAwb~51N*yerhT@1#rg>k(g<;(&S6%u1blFm6a35EbQ~n-f2#&`VER6 z2=>2n+piVNOuFsq+CZX!cwk_CzJ9$+9Er^wzx3W6fmpXWDdLB6(>r;R>`OY=BAh(H z>E-2)l^R;Ah$+=>LrW}ZgaP%tuqXXtb8lhUw$m{Q3=G8j0#EwB-lY-D_ST8wU0x(n zjFRjZ=jL8XL`yo|gLt9?%cmfvGdnGNmI z1A0XxPcdFBeJT97ap)I+%~u}aT#jAYozs`nK-X6sH7c5fPhCfV^Wu9(R@f?tDC-Py z>4uUjNfI@&J~(236iXPmyEIhmarNi?eS-I0iROl^m6e=V=1xt2GJai3TQ>O(kw`75 zmT^U;K=M`XP(IM2p!xK+rmYjJIx>=yI@w!Qf=KF&+;C)6)CcrF!S`IcV<32Vr};n0 z!=bI8G;30PN-!t;Ko~wD(;$=b||XSyrKHC5IzQtP4}s zhi!hF-^DN*(Ee20@O{9LT&3h9R6XMiJrDanU40Gsb%HBS*!qH6*SY+Dcs%pZ z)Z5#?KR${sBGPI&bhMzWK7n(40ekUbZ}30zFMcAU<|7g~CBJlp+S{*+sieuLUu%eZWz zGfIBJ=Eu-~pMdE)+Pu;PMf*>X`Sh3Td>&IFk*w@}*A|?{Wo?I{Wh?wA7VD-rR3h;i zY3z}y3At{{{RU774rUEK3{KFymVAsNDt|+ADRCER(c4yU}JtKQQzwCPZb<3zL zO^KF{Jx!-nwXYp2E~|rbW&XGJgL`ux&$to9$3gbCI#aYquXM5=k6+nS)qSuO@euLH zERq2o(a4ew7Y>p{Zp6Nz!HK`*dx#8r7s#LUe7ciXO-;o9eJ6J&C9=4B%2`;pRBKR@JkiAzY|w>J0VI?$;#9VcsYasUUR2NjkIo>=CM zj{q=`GDx=6P${*ZL4Wb~*N6b9{{Rp2=(>2S3ez9z&*jj+g2=~L1Vu%xz@0>S6@ehB zQfF0^2&mG3XYJ@r$I74p39-_CpG$I6>&371{=V#8bdg+o z^h-Q!O-~&E0LApU$E#d9xd8Gl_+kRsUiahuhr6PYLQXw8A-G{eqmTNl($TF1Uv5iLIbPMx-LAAX=kH@vDc#+Y3g?<+_`SmSz3kx=vV`0V6f(3~N z+C|XnS0TQiIWarjEm)gEvl?PTt!22xMr^>%-Jy zD_~arx#Xpocq$nz2B_4pKTt=qsp$ssX&^t^p;A3*!1QYanf8mQ*neWdhswN1Livrq z0{;N*?f%5upRcoyiL2K}C;o%{K()UD-;>Dq>UF(canQr-{@;#&AMAbloo`UbUebR6 z*nLPGety5}``52tua$a5_BO!VeW$SZZ(MHrLs_=>o(Ca-%EX#{(ZO8{M;&D&5JXk9 z6X}{3{7D%0miEfuakZMt=`}$hq4{}&JqR=)`i_oydw<+{V|&{sksRVt#eRao{d4|KAxle269kVu9cFN#X5{<#p zsrZq@A^DE8v^BLme{WK0rfITSoE{pSfgH7UINFI3>L7J?D$7j;E0$n25X*n3G4OaJ z+_yP_Z4p5%r-)UM0u+z*#f1k99);*($)-6f^`A^02A&?RVoh?{;w{h0^#Z8 zKh?*s23L)kYGq=oq0}f)eIdd6>eXSv`ulJ(A13wk`Sq}h)HKJYdTXhu5l3qVa?$`* zbm}Mc*d8tZKIqf~0C7DkjVj->q|H?9Qdf35-pX_i6arZ41A;gL-r1(5VtCifrKo@q z0P_BSV-6ZQOi(uxy7o|TC6o}fK{ik{cu+>ij|lu$u7 zYp6H;`*}gpLrj|V`oc?(QRUP|tv67_sWvyi7Sn(5H@WtqW6cTAPKZ4?bkjam+?9PT zsEcq|-;1B2^z;4~KK;Xn4@%>-{*RYXC&_?{ia`-Ig}4saCz}#asPV_UH^LUYKg0g4 zbf!B}PNp13?CGvt%961yjmD-Rl0ekJk#24H_StIwm=&)|63hTyjy$?7pCx)n{g}O{ zgxZf@cKo=V!wy~z$5l*{wH+sddTfOiJqdW~Czl}`rj~6ex&b%(dnDhvVY!CZ+SS}d z5=}wQXedDeaC7D5j)(k#&!5x{#{T*%L2{GZnA$yBL14j=i%|SDH3K9Q!=U$Id=ThO zk|LigLtDLaC;@t`^pO}EKoBuXC03_c-GTI#Hr4g^-rw!!!Da!tSGbea_NfFC~^{H6@sme$sM!P<`zjaR_3jqmC5? zRw(IUNPs5f2*L!?PvhIAV;Bem`cPA?Evua5x7*YyYw1-*JT4!vGcR%aWU#LZJhi0+{JBLC}t&E>CJ+aC;WY) zHutuD_A_gQeg?@uVd-GEg5YSmi%g%yF;BOpM%C?nX6SdJb(asGrd>6-TIvRoi$Z%g1_4YS&D$-=H&8!)P?^5ZhfX{DO1vz_VUJqk4cKm z?2YPYx`iMrmLvzY{X7yrob&nijl;DViu7j{lw$!i{%)FN%@$J3;iOUei)ubTMTPHj z2>SbP!Yxw5t^Q7*7J&&>N-z0($a5Y@7uFCb1dEdVi+U|_Vl98Cz4(471;8C>TIpgK zcOD%=Z1{-2mu^B09D^C1Rl3?&q(goM;tjjV6TB=hyK_ojDs zqgI4)ALQxu+hbF$R9Dph0Eeb5#_prSQGM=OaTF0;qAlf?u4BNC2#}z6Vl98tzg8f7 z)1M7B$N*9NC+$rQCb{{WEaIXQjnzoC;wLE3v-Sqi}Lq5dh5g-N>;t!2tIb(Fy&edi8X%jT)hPnNile7QYFSz~!*9XDBl`+T2D=+~F0BCXL(p}eK+xN|{ za@n_AaW30+14Sxu)f|ddmZKt|oR7<*1G)bImoC+wurA&1{>a5*DHcdD*gTri=HbCm zc?_`QXlkBXdXKTCXKewkZAbc_d9$_s_j!ia+Bo-rZ??;;<4+Q3-bhTXOuHo+LpPl< z))-Is6xiXoyM9>rA9UOH`D892F~uNC`Y_O5gBq9?Z!=zleaG;_wKiaSjhXTWmorxo z5>w(ghB~S#DiJ}@f~Jy6=^(p>1eFVGoA3b{Z6AGJNV}0C=D%)dwTZaBtf?UtBR(61 zBvQYMzqg=IFnz|k(g-AeUFYi?*A=99cIGWyapFg;0!=utpC2xQ*|*2Yj;EN#zxw8{ zaN=pg>)d-frc8w*AiFe-P)@EDN9k`94lnihIP%Z9{>S@{v9B!i-L1an#-B}hNG7iU zG`^bG$f;m_y2P(={_Xzga&u26{{Zdf*U_k{xw0QsZBH^v0?Wf7flo2e)z^P1dgpr6 zj6|7=cxo#X!BvIaG5x5QS<&E;Yt?CIW^MphV}J4XCEj@hciWrC`eI`l4w=WOrfE+) zb&I#WyC{%d?Uw@Kf19h%j*76R_#QK4S65rLA!@H13=xOwy} z+4-J1Qr6pkkVki2B2X!-(7iqu^*jmmJrbV8>aEMRWL&&)KH|Zs26~zmsF2YtYynJ- zEsXSQBK=(hL=F8w@$6@{?p7Dd*5;61o&eLk{VCwo^f~!-Gm=S?L~Dm>kRQa%YCS7b zN2WgBvu&-xhN_@yS{M@@Jv0(XXgIUzjFyrKMU6)*$!}lvdeCK+xViPOcjeZ4cPl!p8|X-N3*P=DU1XIP zuxWWCk?gYPYf^=RCsnWF{TLg|HGk{8lZEz{Q zj*!feI5yympQ!d(ak8U8!^0IOmHofxA7@53`{ShQ+RXr|{$Jst`+DQJYChj`?Hs7o zJki(VCsb=)XN_i9$>0#O6ZQOo{XMt0Y>Ot{y4scCRlz?aPv$AnX7j!qern}C$T|jVW!OoS`0x2EUYqDEiY!yfcDSjSt?g#1si}~-{Q4>2Z}7YOK23-MRa4M@z(2}I z?C6jB#=%wD>s?3lW+(gr{?pLCvb!sDV8sqI6<g=ytl_5aWf z>UNgrq{>$BF1*Lr6D?(GcO?68 z40y7w8Cto;Dn8L#gXnSB&<&?Ha=q28PaiPYkOdFx#l&F#FJ6RgvA!O)QarZX+_(zV zvPzX0Or*4h{*R(~=}gh6{*ov^v^?yEWX?3(e74=JHw^4@&uC(0+C46~{C3`o?0l-fb0p&y5{_ z_UV0&82_lw14y$PqboH zO)VUv{Bs-!`LzE4oYDUP&|Nu3jih=c;{O0x-uL|f z0B7BVQvU!0e#6pd-*#HJ`?t0K0GzS^0MK0o-Q@L0WBrXKB~4WM47CDypn_=}K}ue# zXR=1+Liok5KBw6qG_Aned??^{cacQ^HK57i(XTFVI}zMWvTs(3i5qd6J|=_Bx+Uv` z$=6LIO^3@z7}cN(8ufW2(PX(;QHg6>?*-<%w!r_p&B)P4gUbv_VQTY2+E5&Ki(Vs z-DvYKE|w?y!DasdIpY5Spt_&@FC!>I*qowS)rx(ES~1d=7GntsbAPY<*Si}Fvrq9U zf8JaC-D$a>m#L@s^_TqTi~fS^iej?fO;J$f(S@0ydJ5LMAhFXUKs`*O>Gk&8*j|&U zT1#4R(BJ0igUsB#0Uy6?zvnz(^cPDkNAW6nMx1s{C0its{gp|G@p8dhE3p6zlll5v z+h0j~6w=CS{{WwVacuM2s!IR5~DNB;mpbTVUS zr7^ClB0jDocTnoTL9Kz~pU<;c?Ji1p*-A}#X*@q?uR%Ml>uA(;?-s)xM5+G(L3FC4 znv5GYR0^&2w91Mucqi%wzr)(7ZEkACt)$N$*8c!EM7LYk)Yx6l+aK`6KlArM*5P>e zr*-YE#*&#Z+m9a}8zVe7nm8K&0A%viXe=X*9K$HT_Eh^Tn$q&uc!GbWo5GQFk`R&U z>BE8jy*iuT)p4|3LHo|z#*FG8s(||Wo<3inMmeOQ<5gV~k?C?KiG5cJSO#u*AM1NQ zdrPotU~~S|{{Wky*YB;YPz}ZqIR5}@haQ-2v%@w$29a4vK{o_V5}W>Rb$va#9j(Jc|YdqEStvMKm%}t{p~#e z06w{`RyYIxT}So*0F{V<9Dl)w_4fRB*8o$&f7pM`(s?&+y@>w+b`aK|#=qz2D4L=T z%iH+6YDb1@4WEgb>M956lPg%-;ewh%G*0o$DydW?`da?Vo+;+t(D)7^f-_bsX;bs3 z+4~Phk?xy(J5+<~;WJL)1rD{K^QCK=e}kd8;;RQHmY{!+f?x;w{-4LS;#kiK2S|RV zFZb&H(br9jtsnA2)(W#kn%s) zU#+gOnf5ty=UK2)t82zKD?Mo_~ z7$gSYLmPb$(A!P@@5E2y9XK6N1|PSofc|IQ50Tsrv-?kM?drVET-fY}$=x(m7`nRI z#HP*?@HW0aT!YK@5tyS)fnpXvNEl-#o zX5ZaUpDe95{$b?Z<8q29k%i5_iz1@Y`zA#!z*f2*gVdj1s`C}p`|lsQHX@yky6UNE z8oMP>zulbrD@7JDkOh!aF@gj4OcWb2AO+{%IZti7Ty6XDJ5|V$!YCdaX0lZN9G={f zf#=p@$IP6tlfuWEHt+yB`iO98PdBHZ1DtT`=e`8gXOnL3-Kn0yX0Y{Gy6CH@mm!JB zP(eKm(n|o67OaLTY8(b#OU{iV{F8i-_Ac^su+Ow!!7Nu6#8X-os<)+SS`tB~00Y;o z7yHcHZHdkhZ`)SuZER6_uAQbW)E=H{^0w1CLTzj$8g3da5 zE?@-GMEQ3Q^Yp`&g0&)&M53=TMFm4Dr7YUn!Z8{NPFM^5exK`mtd4+HTeJhx+j$@+ zjXG*1ej)tx(he`;RT%0@g`&z7o}M>fJq1j2E$z#L5)&h$i|_#adtx~?MuZbWJu}gk zyJeA=>Laaum{aBF!=@>zvYOpihawLwZAnw~2S_6El6^<(Z?C%`$s)9`MiI+t+p6Xx z{@H)e(@fO)J0cu@Kofhpq^Pi7P1tzs4;=eapfFXXe7aVW+6uSS#s2oc=jk1quFO(Y zV&I1pl$9$oUu`td(Nro!0F1GDT1eFCB#k^=+TYXNB$T7Xh@^&URC;t}ZY)`3V|f)q z)`i!P?dtr-V2*IMMvfGhxV&vcRe{Z5OVsxLD4@x|H0JQqJss5cu`Fg-< za_mbz1$Y6U`?5qdV{lB%5*|8wVXuN5}{{Wk+HsQCe0$fB-uBE5=bJjB! zLOohBm9dj;OepFL8-G?Y+}r)*+PL9J$7+9{q|I}0Dg8_6sp+ji{gvt@i<3WED&xWb z0F+9LkWc)x_WqOTe`i}0ZR3sXKksY)exb-~*7~TcK)2?WqWu1C!pu z2XVIt{%R-r`frw6;r{?AbwF`@QqAcONB;mpbk{9ScA{36tc!gO zH9$8f`h+~6&$Q1B;GHnZ{_=m#(&XKFev4i1%pdu!AN>W?392#&fk#+AgZ=`~^)~+i zXtja%ouIfl7SB)gr~KV2i+1JEYIn;s{{T0m{{W!6!qa3w~ zclvvhKd^ou!rfVSeqN~m0C#qIKkw+j=q`|Zvt=&o3s?5l_^j-ay9Xy@8xx*^OCvknXt*X3MirAfc?`~yJWESe+b<46AhL3GWxH#X~9 znRc$~#pIhYMu+V3sYO!sxp-7+*CeY>BNZV%N=>zkhO-0jaIOBMZF6k?FyPuv8~IYb zc<#Km4~ZW8?VbHU)B798*Xc&3S}N+OtP`bEBqui^mWrrYr8DGa-6%H;37OkZrIVzL zZYauBn1nSA8Cr2_$`Q7)W>_{Go0`pLW}j`opYQqg`!9TdegAY_@0;uWe7_#ob-lw@ z&f&F|*Ma zR#JD*M;9&2bKC;w^o713_>hL)klNGGymTOX&}a%NlJMRoN7NNSI8U1J_%ADbyr1bt zwk6WT?gle(k#w2lG1?(-wdhggu~qgbye$m5oQn;G#LY`~U`CLQFT5JR2L1_)?KekE zs-cA`7B_TxES{<`p;k~PBBxdhBo@_A2eZfpUXNew7yK0jgK5Chfm#@n|1}_4Y_Fq; zc@t}`&*=}EAQdH$wbl4LpIfYb+_p9Z2>k<%`@ifMUUc)-65~HnvLD=@1uRN_4;s=B8Tsx$YZ8PVdBu^f*Bl)+ zpp097WB2-GyOc0_Sg$(M%!;b}5S%Z7G?xQKdD=lqMU z(-~9Q`*RcC$J#~?TUd2f%9c<5+*{y(3+6D1x`d zF5l_v5)j@`SwkchqE?(0CU}O6b}UWSw_v{ajWM#~(qI!i=^w%nX(QOkq*~8ATcB=p zdqmIDTTj^885{YP8TpBbnVyA;yUT7|E92bs13jckO>X^1uv;2!heD&DRjK?srh@(` z*=`?|5PRsvwzOLxK22WHy;L0;3c^xonNe?sL$($6PcBGW+@5)*t}JI1y)O~I>+<5U zgfy4g`Oq)nq8Xcjm|*(3MC`$^p|@NAKH^TbT{pe2ZuIf#n}=Rj+}za`S(>L7#0IC> z@A`_2b)6By6Owkg;vcJkpxT;)AJVSc!d@WSYF+S)YUYi_HY2VWtG;lW-V{1= zmxBd0gLYMB_AQO;%q(x#qQeXyWPYT)XMcQ0?o#u(~A-FulIZeb%pZ?UF|?iyDZ(7N8ow?B7!1<{@ild06FlE+c=7sPeXGYGhfO zeQmTZ+QUDR6FPC$eY$khN_WK?vy4`+C(T`Tp|sxN{OOd`psPT>@*;Z-75dPYlflQd z?`OqAxd3`>DL0~Jd@ z{G`0H*S9X$=@r!6VIMUtpw>xK7WR!Nmdc`2${2p?L+TxRv%8`p<+I;fp&$~=7L=0( zbYnXhNpj*uiBm#;$9a#!OdY^hrN%Za$~%{BskPJ&t@3F$#(T%W;4%o9CI2WEPdDEnn_bB4 zC|S^BcCDD?6clKX9i{MhdY&o96k_Ijc>*4FCUi#H%5DWoiIW)I*^w*qDPE_r1W_zx@JP>oudJtKfsi+F|TA| z{aqm{%a_C|Pdh3ef1RPM>7Gt0+2T^~_kmOZReZTRDJ89!Xl;5)tbv^NM)6rih*u#J zRRi5wQZ1%_tXHETX;mJTez)0YI z0PX;*!C;geNde&qd1t&5x-9T(b2{}%0dP)=hU6|NFXgUS69tLmAX0&*jMwq#@-s4f zoaR$eT#biwDgh+(O=-7h-G=rK+tkUii~$NjnV_k;99LR)iD{xKy1oM0r<%4U_2EJ^ zi9P6t<&i~cZ<%FV$MsTRV_PyZ7Z;t{LB?DkqD^JJV>JnK)q&69R>4S|i!5eKHqM6RyNAml{!0d!g*RvtgX_U~o^ z1y9!pt2GOeeV+)O70&qYdYoRNo{?diQBZgQvY=W8Srnm*Kc$Fo8 yxq2T=)66N-D0_mP3NDf&1Nq(44>Z-18f<%KC#u}m_jxNq_7qTGU_0z#nwe(3-9 z=5A>%swJoJ-@g97y{5PI@NgC7;(Gu7J?DEqP8W9@E*=q)zcP5aczHSgQgFb0oIRl4 z9L_L?|B)bP1+#FsbM>%uaR&V(5o+$@>G7KWucrSF!O8Xih;@ejcbfiA7?(HHm5Yay z`=25G522dc|39gd)BmA{d1zVvUw!{S1;ccFT&=jYtY9vl?iPO+&YIz$u3SZB-L0S= zF77%mE{^{*iyF2r9xgCj7grGPUzI>CYETP1=YLvQ|HGoDCaUBN^ME>ASSiW9rvEF1 z)6ULPR78+RUY=V>gjbkbhKEO9Rz#SOUrt^|o>z`rR!)$c|9^PpTr51Dteidmhu8A| z@=E`&y#H8(lk4A}<*eN8ysRu0++CbN{~5KY-T$tO(Elp$zr2?JyDq~2D=*hyWw`!X z+yB>E|4-9j1N!Ij|5)zdm;Yn?R?dG7-u^<+#Gb93%W}LNGJ43 zI}V}|50AkWmDx3;tTmbC?Y}KDc4kh$9Q$cKJ4p5Ob*Em1*HXou{ptE)*8Qg6qw{-x zq{D33?3%3Zsh_Fep^<}MF4Wq-`T1wB@FnfjM!^33v-frO>Fmej>edyX-QR8Nhu$35 zpH9`fxdx4_ciL|GeB%#CGw^1OIz~^gai~?|oJd=S^N%Drx?4Yg{b2?*Vmo|gxS6=) zr#&)_eXU7O)!9(}+wQ}=S*2rRYv@l`Bfl86`(wAza3>eO*Zn@K8L!;kavyx|Vif+g z#%z>`cT-KA^VTy-whDS`L~0S76D>Y}E|MM*2RNd(Y3qhvV+T=j%T=$zlFG zpH60@5~D-1lI-pewY2!p8ItC>FMXw%hP+wvokhbm+tO~rw;2$(zEZ=Zh|XWsDsoA`FK_B9lBwGFop*O+XfgNt$t8+XR_=}$b#YczC8>Izz@ z&|T@{!+CmRd5(wg9}X3Ne`NHgns9jwM^?w=}-Pm z$1#9L%I*Ani$$>L$H(0)60rg7n{g7s=+TVtwsHBMXCN5rrLO1JVjsmQ>n=B-%QBAF zZPiSi?>OxsHWbxj`1kp*N2VzX28Iz-`1DBU(34Z!tW$Jq(nb1*4uYnTm1XwEqRuZ* zOWhn*Ste%wYWD&KS{CbO;*EZp5CKcCSrY<`$)glD-e2{-7r9TLa_>&DLLPUY z?|w_(r02H%Zlv-3v%HZ>9Ae@G@}iERqID80@wtJPzx@I!*gwhHXb$010Ds9Qw%Yg`{rcw@qg8c5b?Wcz)<8 zX4y8~7arh8RKv@QYV)5U4mMt(KV8ta#j-~TvNu{?xs=)P-FVm9Kno^DX8pXqvnNIi&^oR{!}<~(CrA>} ziZkFW{t}=0bVc%VCii(#^3V3H+Tl}kK-2Tq^U;f!58miz-G8o_(V?|WppUrlRnnl+ zX`NGV)9%mg-=_5xlMZ}Xt;v|Hh6&w}AJRq0i*Z#+g5YW}$1)mG{>3pa7?w8z7pE%F zLQ1j?i8AsK`@zwav`<0^kw~#!d^8?q@BAcY$P30or*S<4}L%YRUCi~J_w zt$^$s9TEl|)iX67o-OLjfY9ED%mXqpjK6LZZy+sk?3f}(fV6Bm!>WZQ{=HZ%nmI>Z z=(Y1S^< zs*V6sXGP8w;1!P{QCb~8_MoBBRdpQKjv$h&uwTtdu7Qx&t&&QaLcLp9~bs@ z-~60+d>8rQul5HON*)iAkAm}RqmpPQ%r2y1?GGcrxb9Uc&%GX&MdJ-J-YWt|<<6ai zhp2ZNIO7(k)=+}63nY5ic80)?2nymie3&s#c2QHY(REVC-=7*Pd?zvYIXRC+Ju+OV zHWFeK;R8spAnZq!6XUoky*#7vu>o<_JclYIo0+$;(Ea|3QJgHKFS?>Z(P z?%*SkIA2jK*!|ZVILt((hvrtjd5w1FpAmZ#PnDs#$YS*lsINjNz4)HK*}Lpejl@z# zX*4<}%OD3^LCQjq54hlu39qZTX|$%hYt7paT?*yh97gdX@uJV({%Xcw=Ef00eAD06 zh(vg*yH%x`KU_D91<9)u7Hdnh2;L8IR>oL%Gf`5)z#;J6xNT1Pq2Umi%D{rBDV5ON zh4#C;07{52cfc8rMsWvh*Cru%Uz|d%i~^^Tv!EYpjg^Vo$T|-oG6GHK(HN_kQTr;` zH2Jo@z~U~GJT)U{BX|So*w1V-t{}ED0_3A8rz#HEIa-oHa7av&s9N_h)}u= z!OA+N=oBHHT3v5t4xJA>(|O}8+l?N#2K92{p9r}##$7#^sQGjR)-%fYm;e=Wf^6`8 z!SK0?9=z{a14C7Q*AKy5H!EbX{eQja*n93F?GfH6 zAvL|XS&wG3FDB^Z+_eTM12eMB9Uy_~ND3l$S%5K3lkPQO-Qtbr=c%*cA4<+&7!ZY4 zhS$yvqqB&P^%P-YmQIP;a z=9-0$-|LzEWlmF(cJVewy39aw8Lt|F@AHX(G`;fPmu7Q5y;8kWmYmzs`H$7sC zbZtE2)`*mbVb;TOQhY)HVmC=&Fr=4=g-T}si$U)+?i0DR_Ky$G7$lxH+Pc|{nehZ% z5q0HLt)z_A6;IxS@pLsv+GuVG=QH3>ZyVDTqU*Id!UwR3?L>$zRoVKKu(C5dDqvn; zIRM`1Q2o|(rU5D!y4D&BuaI*q)S(bf4|`5M><<<+A%B*QTwc9oq1kWKM}q8dtyhbh zaDXe2yfeN!g{+WPHk^OD4q_tA3@!R#N^JP2-<5tGqO{89D~Ltp*&EyrO)YhBo1=vtanHfk ze4M~$cmGKk-CBjA7N0Bj6wEV#HM*F3#B}LV(ph}DlHud=>Gb*ywAmcm9c9@i zeqp_ym{&y+h}YTq`&ch zP&(pju(OP7167dnLS3zou312=O^*;OA#W+`pTFWa9=2?>Ba$tSlB7BY5J`)5b3zHnXcw~po%H!LG1T4gVg5{fur1f-}B#7(=+ixVk1Gj zAv^*fnWZL+CKO??uF)D&ie+htOSdP!*KfZXG`5!Uw%dsNcWK1KX|wJ1b#`73b0-^3 z2DB)KDxwx@&{dPJmt<0uLaVshV%DT1Mf<{}{kq6gEmF$`iSH*qx`Wc9qECnXPfGvX z_&m=RzPuKvl#Qk9Wn-K}R|-s2-lq@C9!c?Vc6u#@ciEEk^OIQ`Pd%?-Aox?C;f?E_ zp|=N?3ow|TZUED^n#i_e?(CBE`5f-p#@1k|&6y0Z=l8Gt)$0i4uSvZ}Zy=bbu)sz% zdM7q5#V=cFXZgGi)A-gSpBag-XJo62Mu$nvCT$;lnJIB*(Y1brp~P zxD~%ZjF+_zt}W)Ta0`87-4^D}{%Ma^)m$`W&E1}w@K+X`Oox~k-T;_KLn2Puq%BWt z+a9XZxMRxar_R~dbNnlVAF|0xM#Z;&IY-+L{)xUU4W>j!bAT3{sfZ9z_TI;}-#I|$v0tiCC3Qzi zMFZ7v&*BemKx0f{RY!Fo1(IB>g?UYpd%Q#9aygdvoi74lpm=gEHMM!hvu{Lyv`4&Y zS$*y9%hX7Dr)^v$Inj1b^#s} zlxl&CnHiy{pEU0J()ZK{U$ASkH{fkmQ;`nT&bS&~&j&)dDq&!CxIiA9-#(mV4Pk@9 z_{eNhX|ZbhNA{`NoOMhLHHKZh1!sQuehJe!3OnoM!5*f?{s3DLep{-n@ArJ=YU$Gb z$IBePzzqAoi(=_Jwegep$*GF+?8;x@byxO<;ku2cnVzS4iBt{Ycee{i8XJoo@}L1+ zRMf_Q#Bmj_^jd^e1h9;tnRg#Tq zBl@-4%p2wWavWv^_}yTZ5q|~st8p?u`MV$|q;NVp5dtgc8E_=LtWK9*#FBW>{OYS* z<$GqcZTjdDsy&_0g+vAtN>y+4bbq3TOJbz>udp|bf}T-DtPseNyUD&y^3&otVw@o) zLKK>mxb&?C_UX5N29JHhWCqKX&L?yKbz22-p46j~Shhy%Iqxkdz3pBb09jRn>cr}F zNf?&!!>U({6$r&E!p&7)Su)YC)C3U&ndLFWViHS zY^BC-m{@1G)JngXKA4$p?Ue3_JzQ4XJ*)gkqQK~7E%w1gw`l0;zhpb*oW85${k<%Y z+?0^q@|&Sr`LrSS=|`ptAfus^@M%)f`#(aD{FU7TTGo?IT zBi8c#6l2NGVSdv<_UbtS3rK2tyR~sFr}5l%qVmkAOFOlO2`tRm?$a;SJ-0MTk}@(+ z>6NoVp7?(q5lu+9TYAeRh6*S1g$r^vM|UNfSj%q;AXlSn*YLMDrT{5JZR|~#?AGy_ z@4FV>mCbogeRd4BxTm?~gZksE4T_hsQd}haK|Ad-ysm9mRn5^GJK8<@MWr3 zkcE0RXgwo5I;Eca;Eo{)AkJ~w2#jMCj}ahN)tKt){QFU+0LP?I*U&(!at>s35Y9xN zMVcQL5ks0vE zcy^P*wWUh*mYD)}=+M7Kk&(@S*H;^=gx$##Sq2KzMoqqa?e2tTxE?Z#z~zXyn5!d_ zK=wwlL1mijs|GMek@dQ6M{k8_HH8-qeVJjv`t#!-jIpM(ZAP;GKXP&5k>W<>+@A{D zTMU(pX75$zp8!7F9rN+_RJq2ud+R5h}PwB{z&BLJJ93 zVW65-Nzyj9TH+h6i;5X@C<_O7B$|{8TH*)sMLgUYe>vN1(e;E<+k<=kQ8;+PAe1u% zQoVQVmagJJ*TO4ezJHr*GC+dhFj$!!j7x zOj}aF&|}IbRl?Fs7=4256~T0>22G_c>K`;(05oj$6|&W|`+e==hgu>e1+r%9QA$Ar z5n!Dzb;ryQp>{=49n5__C60(xLh03?+)PisUyNmNqvvId$AI3#HF<*Yc! z4qV6Au||XG^jh{`Cf&2Y`YA--T6{*~0&vBsFc=sXx7qy_kNgLj^}W7hNna|oqNSUM zH!`f&Uq*ri*!I^M9iQ4iPIY3Loq!dg+^1$T-S}w6SYMsQd+f@-PZrpau2z#yhGCP= zUVduJFPp($kw2W)37c(dKPZ?dAH=66an&}FgtQHU`Jc)Ij{6Z}`<6Hbg0*ngnRo*d zq~*wBpu#JMSj^r0)Me>+F@%l800iS2l_il0rj2OA-g_NLGW&I3C~76?uloFt@=-hX zh!Pw3sZ{)YP5L5*l>KW$;Y*m$joR~CxS#&k@x8Zby*coNF?S}dt77dn`uG`%wStKN zIz04H)Etr*5kQsQTTHS4H1ZRSNkF{JEvn#`uwL|v z)Va|D?=y^~^I{`er5`i9G%RdAhLA;h++JX;9ZoP@4IO|gW3e!hTOq;$N{Oo0)P<)x zu(55JD+Pxc0*F67booae&DSc(UPkUH(P{83DOmZjvY_j*D?_v?~MILa2o~vvvc0Q(!b!z`q*FA z;n`s&*NoKWmI-yxmC$qi1mw$X8frp-=f0e0+6{IINTrZEW@o>>RuRKxUn4~AOVT;# zdQ96oV2T<*Scn7w$dBtyvncvvYWgx=ad=;2HpO6W=Q+*Gt>RqxD(sVCY9#)U4}S_R z(0OrdOwnaQ&bwcku2Y^~iLb4=1TcE_=-S8IJoGk_#K@lbzGMxwb_kj|{UIy&kydpx zGaUbeDl8}4mmPjtkM=80Cza!DoY$T7=xY1ru8>pTE z_aSKHX)^b<`MW8n=gv(l6?ww()b1r8r@YGX_X#^k zIJ}TnQ?e1#)8=l$97R45TZL)?(q1rBtX_K;`RR6;JZ#9g!tRk4DKD-#$Q7uM4B*X@ zw9=Qe%gO$r;Nw5S#9bl#B)FTc=vJnQlo|kf; z@;)m`NxXyCw20Yn1<2w)`O6c$mmaYJiXIm$45@ZYJe(JoyXKFZ#&7P_$RHm6FH_q!s4$j?Xb6T|4_vhH-qd zp=*6%eQRQkee{iEyDm^f?YJF!5*uwqfCQ9vEji)36kyta z;U-=w9g7X&Q@)i$X%8}p@I+-NAWOq5Cq)5KO6^e#qeuPp4ruFW_*_y~Zd+`XI1iYY zc?VqePC1(A@{zh~ANqBgdW@*g*1px(`^rUHL5^M~&ZL15x}-%Li!m%V3g7mx2W!(( zrRyOTVt=q{Jd^9VO6GmSO|g@Lc|Lvo{-5!FL`JGpGyBfFChRNwn8tPWf$l2G#ITI$B>9P7c{agsbBbG$NR`_oe)s&?R^9 z7VEJG62MH~AqLZS%nTKLCCqdZpYUma`w=V|JrR_{#HnF4!MGeXdG&3W{MWj56)xG< zn5B)$WV1Gjt$^0luwwzG8=;~xYus2k^y{pDb(n#-mbHZ9T+-DKQ@wDub_ za}0N&T7pfgG#N4DSdT&|BW^iZ0TF;yoEkDl@$9=fdwfP(W1h_{Tm=4S$2I8dFv6QKB5)g%!v%$Lm1Pv8ZA5#MB_^moqECWKmL|yMx6U?zB zu1jjf65HRW$h3Re7nN=X`>j?m7(l?pF@pWnt^J3GG(evHOYiME!VnGlOnMYceEn|I z8hcskM|8>MazhJE(3XO!m7ts?I?Sf#G$8W7Ak9mJiIeqo*=TB3FqIx(>;=DCUF(q- zK~M&&NK|nF9E`KD`qqeax@kD(E@nMV6e18=rP&zpfd^+wuWaTcD+N=j6FXc6-Ap=% z1|W_(8rjNt5UC~?$pP(|BJKcwb0+|BYb-CbV^^Yxp@Bj~TtwbX^#?`iX)?f9p?DrJ zUP%B~IDC956+yAM>J#!gwhu>hjysbMHunl9uPYHkAFOe@lZ#LDpvC_-R|;BDKuslN zZY^&l>0#DWw>rRI;n}RnEd>s&x~f) zl6}C{iy`Cc6y4vI%p@;n0X(l~r&lBylom3QqJ}78C056*NC@yq547fc+ z#5enDWf-tPO#@D#it9bw`p}PDzjZl!-+_)H?e?70Gz2LBgAdKT(_U?~Ov}2HJQ7weda4fq2 zC#Rwo0vEP86}!9{rGwr1!>O6&MDxHu%yT*nzp^2(T%3E5K45$|-)3IMF8XC!-8(%} zyTzn$YaG4YZaPzGV;$-z18@4eVd zHkLf8umSbtIVx3Oiwb|(Gus1szjxuCq>_Ubi<5|u7KE1v>TRPqE_s|fl@EOvC40Vi z2K1t1ZS7xo^Em}b8N|oXJ%s0Bbn`a~*KhzdYvir6$IFr=g>Va~$QB9E3% zi+%6~WNg3FmY%wk#HLFkp!mxl_~wX!bwgyDKMt_RO=}loEK;^PHBSuuy=*0cW;77b zD^V~|pnGeRAS75dv5ygxTW5KD9l@1S+*1K40@@BL8aG^ehd1{QEr7n?l4D@iFI*H4no^Pj&!f03)#$?vVO%@kL*RHb7b0SgHE)}m-T456U z+FVY)f^Hx~M0Mb;5mrDe4fxrD#kNQoYCortTPy5kR}5{?!hR4X6Y#%tYDA=D^!#$6b& zh{=>MLeNGG(%-E8Uq~Z?XsJFjni^!d&98j0l1(Q?!p+OF18H=JL*&mUfD8)qqYe!+ z%8`%s5)OUp<057qN&0(joE9=0wAi~$g+t!jw$n;S3l;Zo0&THRPoW-MB( zQXD>uoLVTy=xg)j?6~^x(5r-d9m$SHh}Rx|ziZmCv}M zP^lsI^2E{>WwFl_CH^$%TEi_v8dHVadYT(@I_^%CH@mOptS5MHDqEA39?ay`{2T4g zK)q;DLm%_thYC(5bG~6^RvB)CGu=uI_I9RBR#NyYx@~^1%+=vkMSqMV>{LX&9JiNu z>GQ+s6ZzTsMs74o>Vhv#nyXv!B`T@(w0IY4OT`@lbmDQ2__N6?G(95TlIbw3K1)Fl3n*R%%8#%QH>#n2*a%C$7Zx*jW@&@sDn)Bk&gjyt zO!x;sL}mtxTTYHW$oc)8)u5jto9GlcVZ-Z;R}M*sGMCovc$kZ8I!q$0ft z`Q3Dj$~yYi%Vo9wT~$ehz8Tcx$e9(yfdrE~<0uV9XZbD|;t(*aNP|7EAU4{*wv5E5 zAao>?c_;K=AR=#%@4i@HCOw;!rk0t0bDOl5M&QW+pL2)z9(SCc3OgU}Tjer~vL=Pn zo@OAHOkZVMdh$J97S7mI{d!?CFCoiOr$GN)(>n|9ipj}UumS59jw>N3sptzZuj9`S-#VyH5d6gc9hA?4`}*6fBC6J}CRS`!_|3C=>VtpMP?dx08`12q2Z1$WV?#Bb76_=r=r}hWT6{VmgY! z{EFd>r@?+uqh^YQ zDhS1lmod$jz0zu?x*+L+Q#D1+?_0$5)6vU8uY}^lx0;Ta= z3nakKAAmbiFh`myrB8VKMBe0bdmx^SFN5CVz~dAyD0whai=9Vf*^27*>H&J>6%Zsw zvrl)#{CsixbZNx;!!uhg!vuM6B%ScX2rXvVWLwCz#b>F>dE%8h%TY#4%FHl3A&yQx z{x!$u3&c!hUaH~2me^C&f1-fsrH51CCy|jSW9NeB5*V9P>F_KGIWM-!LWhD%)TIiT zvXL7kBt>;*#yta~0*HuNm*YzzDNpej^+grGExF1bq87TqX)-rqBu-3|lw$G)@5mI0 zx^P4nR>*%K2JG5bGNLr%;7r0-JoD0dZq2YY$dTZBK1R+nsvSDhtb%IEV-@Ca(G(qD zv8=-OB>c=0^@Dl~ZnU#;rF$M~N-&A*26O4Atx zs5Vgd*JbBk%)X1J@80YGbeUT#E(}xZWm8l{*?$^bP#V)8=~B*cZ|ShS?KphOial)L zA{HUcie7$x-A)b%4LOuY04I-ifzd{Qw3?Qae=wK77Y~s8O`cmj3}e=74mSzPI6Tp% zqjv;N7f)38k=r7twb6OO-+R`ULcj3ahq{uc{Pr0P(kVVeP!8pl=;?ZJPstV#VUQo5 zSS>#$g=+QfM1dRK)G;5}0%AOYw#ZAVpDchTBP8F$eZkltAV6nAmSkt#dscq%3HgL9 zW6OA)ygNOaIEzn0U&Cr5*y<5lwx)v2OKA`_K$1u*^;^4 zR_m5^8(X$C4m(2d+gqjmJDid_gP*>OF`4XD#wdQfU=y)94XXJqoeGU&`bDO&d1eY+ zg5hil$mlJ`rEtdpKBabeC=DAM*hosB69vP^7m5GwSf!Lo-m`+v?2y1UycdYtm#^!&QCmvy#(uyLY%b|WfJ@>{5xAFN}{oQ5Y05J_3( z6Jh65jJHm6X@?7$$fi?Znw+2E?X$y;%a?1*;5 zkrezqO?Iju^#(b|2K&36x5ml^e#=L^&4HeJPuG1=0b&=`;Kx$lm+5RxoQAUgh&pe) znpC31RT2P!b|*T1o#}`a2^h}az@!TKN(RJI;}I#%uge6I7Qch4BCT%6BW04yTr}bM z;fh!JqfWvm!xz*&Xq#vz#?&^MLkH0ZC|u8*=K zRO~M4KE7cNnIb@G+Y>PIc3?1AGtCtE zYh=C_s;lBwS9w;71lX{DaRBMzl115|2nn7H-2Q+(m97{N0k4J6R6UYLVQC=^j}6=S ziKeaEGnFT58p)xaKUW0c0f)9?MzhWjDW2Dnd0_$b8l4OcHY!_R{|!VATX74>zuIEE z$$m}MS-wWj3bh}Vj~Q!jW#|tIfd?ywrsFFLtk(ZPOt@wlEv1zFlw`{*rs$>+3>}8V zll8~jDjEO`V}QlV%7AJce!d9PSO!K9m0w<_MV?7_knn>N@T4cEiJsC?38VMhuMjd2 zUmPm=XP|ZjeKimtRu2flXl@GUhM*7QF6t_BzJv<@)p{D?%K2 z0@cj62Sl>is61{kc7I>W-i&!P4b<7;$~sm6#h zmH~@;BxTPsurAJc;yiFrCfqLHw0!Ra*pXhD#7wt5OB>9KuKjDK!MmKbPgNz!%##(_ zD73F*f@+tgCPTVr%yrDKSv{X0I(&tNF%Bn#(58%G)P{}`J@S}vCpzWMccGVzN0NR4 z+(LAy;<2~W$@z@pl8c4H1~!!i_Jx7iZ&0fms}rjMhA*)OS+O3>>qE-X(Y~d4l?^7Q z{vOhBMk3T`kAjI7y|}TH+>gH{@!Wx@Nh_SibLeE_wRYf$Av}>mnQ!c`_J8j zS8pb8H{4_7;WD14pLQ~6HVUNXUWQQ;9oW*bIE-*p_4x7ypM|AqE$9=C(15ow7I#V? zM}dmujsX$TD9FKXqg|2_BoG{I;%L zbu5U?Tz+<%_<-GlR)4BPsfH(nl5bO;Zf{EUQ)$dwh;5{hAy#RAN!zc$|hVyk(_i2}6u`55 zG~oE~sXBdMPFzIJ?(527A0}G0zC5*I^c!T^npSQIUbKp1QkfLs@Y_R}-*q@~1*fGm zbQA^h0_1xyK3BZ;>+-JjUx=!k1KWKLjc26rWzNR!BRRc87(w~mi|pJIREzS>041E| z{IHcUB*A@7ZwXSSQ{7zyvh=#0ly|-}vQJs?4NoLx@}F5Egmo3?DrT03+dN2OAu|d` zD7Fw0?xq?zJ+~Mzjrka4R3uQ8w2&d{5}h3PiE%T!Dh$Gbxhm6_Fz6?kVPTZ;rth3v z&#gdj$>WP>Izu^ra|xOdVbDtoz)K)hZ{@{6Dr9NAX3v+$+ejUjG6N-q6O3qyOEh9$ zYmg6v_2&izXqNo4`pRjfT5x4@MA$Q#Z3Gs#-z`25dg8!bzjI#+2`ixXQJ!m$v5AYv z0M0ZXg?aK)B#ROp#|So5YTs5DL=F3Y*i^X7x<+{a+ZtjR!Kp8W8>&U8-HhQpdCxH7Ml zMEudTT=z5E=dn;bdi?jPpAmnNUA_`QwO5d_YRy~ax`>5UKxWlc!SK8-`^#vO&QdHk z@(M7YECP~?a65ou~3E@}D$qEG`k55ljB~{~gu7sCk5qyqTF|$*oaRt9uQ{hiQ zE7T!ZZ?~rN5UEnmNjK1>x$_$C2R+}wskxxVO{Q78E3$wtP1TK}d}cZ$PRu{(m^voz z7j8V__q|+qmnMn;w-}S0114l;F`N8Rl$`4@Uj4X5-{Oz#IL}Q15~uO7k!QEUtwXeD z-w}0I^NV#HCL1@=&)@&M!N!zLILY@cgh%4Gf0seW(~Vr5gq zOwoc&To@)jzA=CwK-3uG)yXT(P9CZ==u%J(A-GCyq$GZ5O2|O23D!9y#{fsC){rWF z-GpuXEoIe$)`}>?z%t}32X0ti%=Q9Z=AQi;TKX|hy_~^_dD)@H?>=LoSVOLDt{a2b z=|~cC+UQPRZV5on;@CmEog+q`MVBu}ess)|e0+)NMLhN~MvLjyEIPI1i>geF-&nyS8c3gr#IOy`*uV`eBA;Fi zoFv10tJkJHv1DnPtxwwliZ2+>*Hzfps&{q*;8`1Q*$uGr!+rh*jl|l`PTWtz$<$XuQ z08_zP2;nvqY#+I$qE~~4?ns4UdNedNh^1;!AgvPmRZzzTi3^rTWg2Lei%i0k9N-7! z4|p_3VeKhmDB$0^#YN?{LiVBGSKND$Jcb$9B=p5g)Z;LP^Ih%IOt@nw(N{Wn`$@O? zQ*O&-g31Qbt_MKu`w%i&MG5`1D*Vp^0Bmr(cZ=~Q4nh^@mPW&}-t>aySohgChyEOk zeFaMSjDV*Fx;m22V!2;rmCJ4}OZ|na-7nt1liu7!fWg;G*LE83Di>U1Ww-ErCExu< z_TJMi$b5~_IW4*QjaJAz#7o%g-}HD6zN&e>AbIhA&E?JD8EIH@Xm==y4X1jP6_3#r zV`FaKkCL>qJf`Y8J-oE?wa%=NnaNPJXjBYnZsy~HCl9TH92X|a8_bmZQDSHJzB{$( zLRP5wg>IHF^0fFT99W?$kc%W41*BQ=)jgGp<)@0UM;^U*MJ0G>=p(iCKoIC{oPz-x zwkpX8f+M2Z+KYIwQx-QNoVbUvjFUzcx4{~fM)V}gG{0iZoRF>9 zDPkrOa8pHh;vf|st);$99=NRH-}&ivl20lF26q04$}xs22mC_UJVhf=GRwDH-C{%K z7nw8XYKF7}WhwD{?hXPC9Ho~v7F)k=wFByHN05wO?S29;+dM*Yu1CH1=;ywcK3dfN z2YLpDZ}nLe(xlg;x(qpOA2-}Dj-gsij{zb;+OK3=%|%Q4C!jN0Y1rG8aQ1PXDfZay z#&krlCivN2dbZsJI*0f4vGo@9r$`hVzU8lI=2Sp3d*XH!$qQ!lT@+;*alKs%OJ_M* za41i#JI+`V5lZBdF>NVtOMfI*2`R|>1r zE^|apQ`S=o0dWib@oYujGug>9PYh>UHwh}kISN$E;}fA*Y{P&JQH>gjJ`k{SU zsZ>%KyCjOmV~;L$Qgo$~$fX{VGB8Rb&G`l7qcfdm>h)y=Ryw^D68K{kbtBrg({5vr!`qjiPr%$=@s&HU7zBV6dyt z;IIFPLy`-WDOztZUmS5i)o%fmo?kINAE@{nbKOdsQd_if0uU;!=*|JPZMY#8FI=|* zVOqL!bg5ZH3Mg#lk3(i_1pc2R_#;AGOil`8NU&dJEwidPZkJtNl%-A8<>d;}y!(Ah zm@KAi^Y5L@t1z4IQ#?+MDqEz0T)RMF5{03NGEJ$Nl#5?l?_(#}GU|18^nXFs$+_Sv zjY@4*nz#l$)>s~tw2PX0C2XIah zC7WYAq*ZRWh13k;*;#&mu`9Y5!P4J1U}|DqDAT!KW*o-Ps2BP}?gMF}zEPuhLwrpE z2_Wr^hMTMwz76nGx!h^9Mx%I?R@#qq%SPeSlhgK|Bk3dQTN!3_a6?Ewu5}zp}b+1`RDPtH+EjH@21cwrb z{G|E9ux1$f<6E4w(c<5-+{6UnVGQ`;e(%1B@>qBf0zHa#(7h`R6I7G69$?RoJ}@*x z(REEH=$CKk_tKm+N;sICVFE3uEO1BhEL+ZeBGmLs%HlPgnyGQCn=Z9uxSYw8!7DQw|U z1`KDcS5a}PlP1e=sdF;#urM2~J#tUI+FOo%WsXPpDt;2_Pq*qc-j6L}Ap1c3Y^{YY z&z=h&8onhRvO#Jd`Dt22UIFi1@^$jDQdy=)i1e6&UqhrbBs7|GmYT4v67OF7C*PSwjOYDbM8Y z_rf-|KeY5!yvXo+lSy8tr>{GcuJhPj!D?f@XMOvG2<#_yUB2}>wzYPojoJK=+>9Oa z(K=1ZqGGl2k1qtlR+?fCLuF#32%FY&CVKC-CwF-94+L<61OVR)}SgF7;_m^B$ zQ`T`EfMNq8_$Z2L!5(f=adwp#;$NMlR^Fu(D&5#TYKw}N+$jBT3b^0+M!)gJC=yz2 zF-=lhJ%DtCoyQl^X+_y0SJc$(k;=q{T`%aVLxx3Y-KQKlmKMK!{Y!#t zUI;gb9#4n4JE*_4DDd`x?egqg*mZ_|%Is)qfP(vD4q z*VUP$YM?))Taw!gR93e* zzL%3i)~-jNSaCJEo0a2pY6Tyq& zsxM3Mi}FQh)oZo@*INkwZ!)&-uVr#Azrlwme4LI%uy&!AKj%G3lie*_LTE_5qL9vO z;LQt?aFhswhI-bj%H-cPD|v4@jsG>4@zjcKi=*BBy;Pb}U;f|eg1BzXhz_KP<}Rj8 zS$jn~gHcADMsL6f zg(N59)L+rR(%O>QJaz+1%`9+`6uFk=*N-8fjV^Rw)z^7A;#*5ZHUYLFzUqh*OaWwF z-UP8Wig`}QN%*}Erm`0bp!LT&E#6TJ$}|h2g$9-M7bLDC?4sV7rWhoG|QZ-36nG181t+EngPlMxGx+Fun>opBbkMtqUmmG=SO zt%T!{wx;h&aVz#(Gf6TWMV|~# zMRl=b?>f{PX~Cgn{gVePp@BhkIWqW4>i{asheE$3rnDd{ORJj;&rXUf5~0D^+sv?g<-)>Pe;CSTvvrL%#+)Zh=)#ZQfg9nH$=wT{j}5 zhpiUR8vOIBu3#gU#=;R|qH{MVr)#TMJvLrLvYl*Jbqx+S!gp})p&Gzs5RdMRCYt3# z1%i;gq1D62&(_rLtz{+-CD%GQCS`|u6~fpuFWC(?u?TmbME3`?Ctc83Gc1)WjUCMf|!+&{;kbKiRN^x(5i-pjbc!KF!DIG&bbnT{&@`* z{(UMfh7^p?x~e3pbI|>-OwyLebqYlOu_V4+(x)i>SIib`G%sHb0IhrRKxq!6DK2Lk zVIP>S-sG{-UL5`k`w1YzZN&x1i3GVDUnDAo62S|GQ-*VoN6x>XxG6OLX(`*R*TkktgFY||9!E7EnBKP+orFS5;`w&eLnof;<++SLma15>ts^+| zPYk8ZTsVtAglcQ}<4KzcEq{y=_c=?4;uaecBk`Kd#{g_(C?8CxFqEw;6uC|MipfK# z|B8GBWgxjuY~c(TNpgYT3Ccuc9LF4>u^eiRkLhIp6B}&42Lx=Y_DE#5PuWk@Ti2{5f(Cpw>FKiEa*dU|1l#MJeBDF`sO=q z+%fdwHRxK$8{E`Hw;k*QB%pu7#Yr95Jf;3}3=I8LMv%i3Ds`Wt12O!98;&5P zWsH59xbK#9dC2Y~rQlKn=)j)Aok{9NTyoRxQGz7h?c?Z=$Z%wGSE$!EX z*cZNtyJH8pU7^I1=0~i-sL4!0&GCSGfkZ1(lV3~KoP1a%)!P$$eXi5YaQxBbM5AM@^iN*fwV0dR}ZQ`cOiEAW|$KV}VVWJ=MXIYQ-C?N*}V zuEL}sC49*dwDt`_@6f{;C>C#WR%4AuDV+=h?WFm0p&gkH@IYp|-z4Ua+2|8y6V2Kq zviR*hz6q#ajU=}?@MFX<2VfHgM1MN8!q-0F{wrXLqNNIraNy!CYJzTTxcx%1Ftq$b zR~oXcYWX=drvT6%Cw%XRSmHEu(Lb;swsk5b?MGVW_h=MOm8K{%kk6sUjhgzbH|(+C z5ce9}ip7Zz!5_Y7+KLR}Z*(0Y){3C+*hB31yD%^WqQhWdQwhRuB{&q(hz@xZ-ra7< zzet(T=-&^AC;AH@LL)61?N;&(5$dlfOXw$Fo3uDAN>~OJPtrYzh*mSg6tv8S>L1;@i*@2p)N;whNeRrr`QXzr{y( zH~TyFzh!0-wg7|~3h9{EH5~f~R65xH^Z2ZtgkX47`ewKGo#9@O(YA&quW(J@^_kvG zWq8rjQQ7=yw4#__}*fIwz!2ws9spTi*f^>2bzAqcze6faS%_t$XldEiFx%0{d zQ6r}Vp9$f2un&PiPlMlWX72u+wIjJ3O{paZ4c_q42ui z@Vw;>D%8#POOX$N8$TmZh`Lyoz~2a7%~{y`-!ZB6i{~Ot<&%a__$9bIM8nZoLQ`H7 z1N(!!HDlkfBtwInJ`Yqn)oHAUu>Uvt11+Ge^WyGgu~ICAByx5f z`(^-h8B;JzsWE%+pr=v0dNh_|#oB8jUw z(D}l4HmH^@IWZ+C6$;eGsrLp)Q0lFrtr-v^2Mc}vzy`01X_6N134SxOEy+t~TJT!` zMq_S=51jk9Cya7&=L6dA9VC5vAc+y`)BNu0qQGq)u^~IPg6M0ZE8A3#URa8AED2jq zMvFW?-%#j_5G+2=tFaNrefGZ zT*I1w)QJ0up7vCqvIddNa}vfm?^lV6b~Jae=JFI^OvIciV$R=1tt*8bE}|!{r|f0D zwH5Z08s`|le{Sqg@=*(?|K6g6&6pr{X?x;EhvO$__ zhjdoJ5L9PW`eH2)GeQ>#sxcg*@P#1!t@mmXZfGpS zjlwi3BFs&LiPZ=ip5TSs2AMY19QPPhca6JK2IbG>ns2AGVj*OL>nvjm8P zEnAo4#;x`ZmaIvB$x$$i4G`ULe8vvRmXIVW3z7E{R_kOwBmdJje}oD?LJa-d$v$ex zxgrV1m%I)s%mHg35n@c%17%;;7X&qGyRx|`dSzP*G%bu{R0yTdk3YonuM7YU7WWR`pD39se4U4 zWTp_q>EwfF6Yj)hq0rLJge1)aYQq zAwC(m7UvyZAZ|`4Hb8mG-snruIt%mP%rA%KunFeSr z@DU%AVsljrqYZ@w61|y6BtlOEmAMU`;ZT$(jS*6@S+pSDjml03T5*`Ug&@BF+Zp-X zzhbvx=8VYhm42JW$GwOq^Er0ub7|FutLndfj%o~xNKIFBEIbDrddD51zUkAuvyYqZ z5c*mes3&5l1~C?)Nv#^RYzTt(NiXgqHkMvFW1bH1go3=2`Z7?LnHeX-YP675eH6p6 z0BnIwl`0S-l%La6cvmEyYam@QfICVp2}UAb3N=0~yY5d1Hz&}GvJ;c5Kk}=4K?;Dv zT~!nCIP~X_DSA6{IWa-}1r|IJ8dAyF1V|53!fJ*I3+IU(k}nOBTIf?lPio>&N_iT! zaV_#x5zRGb0o^G^cq0$GKL`4?Xt3-mK0QI-b$D0-9Fu83=G38q0 zY&04Tcv)?L&6mIh$G)zpo%B9Gk3HNK{Uk$Zl#wC@!`MseRAs|d+zSL_XG*?rxwCCF zT1L3%G4#P@-sr}?I?Kh7jO>{j}M_s@vR;(qRYjHd2 z1Z)dq85dPq6#E*QhNpZLh#eq`Mz;QO=M41WI|889G#tV?YbOzu(Cx&4!9aFqrS{-n^N{ z^X%?^OM+jwZO=J8zmOl@_lR4`xYxv~w>2=RIQ&s`h4Rh^dbG)}exse${m>=9m%p$7 z7S461uOOtpnjbBr@r6UPU4n}vCwc>-G7TOCL|{DXxpVk8+y&iUUXa2TpDFPTr3(je zj_@si+XSLV-&ATcJgud>wc!0+x;_aWRD|{JnTb=Xnda728JD&d{K(T~ghIcpW^@DzodLI`R3HD|qmxp1}Kwy&3~v$oAwX7g#D48Dy0> z1-52Ymf}giGk*>LqVlAm2V!LO#> zhn@V8)nQjxTLvBI3r|74c>}SLqR={d6tkzlk7W$n#a!w3Xje{N?{moAAIIOF-(5*x zNbK1B|rxivxMh%+JkdUdRJOj{kgqv%vqaqew_IH0uOe+ zsPNsOBn!%vo*gG|F`PY!k2AQ2rYP1DxOM-~W849@+x)mrogshU{OYv=i_aMdZzlGq z*vJN+g^|Hsl6;Eu%xEI>N{cTQQnenPoEe2-#)L2_x)Qx$>ds=Y(oAgX;UdJ zLjrw(2BMs5+!vLQb8%Cvi(=?w*-4UP#ZBFp@ zCg?Z6g2$B6Zc2o;#7IQO^0cZ!!M(C~MiHbtbH`|pyA-8y(-7n$mLMA$#feZiQ^bsj z1Ar2U7f!7vYH)R(ng89ICwg~M>U;hFcrY7YAh(5AD`r@D0f4)nNa9bcf~f@<#dISB zKYS&xWkfL*<&W|TA;Ybon;(R-mldnYi1aLMF>)DZ%G4Tkdn|OdpI zm0HCxmcjLXm*D0b=*R8r7Z#m|ExTtUcVIJ5<0&N0J@~#~%;y!!8=Mg)unn+M(A zR3`_k3SM^DlVxTZbATaOg+ST{4jw|=r57$ymp|uoN?hY6z;pZs*+tzE97$8ijoe5d zIb!wwJq^%;y#0*$=cBl6pb)65V$>0P9$niEfaDyeY`qO}3tEOGiCuU*kn(qs-)nqN z%xP&vw-F~&d1B}f0@GmG#BVy78dSz~=N#w@D#EpVmnR^yQHQtPG`y((3d>KZa@v^A z)aGlABl@u^qdd->uxN`CD6}_Ut|T7GIWM*IEw)WU9T!x40ibq_mgX#0PoU_l*0Ym@2PVTkj$t{_WTN#aDK#`g#%N~%00}t>1Wt}ukX)* ztqNdauSV7zc`_PQ8w36F`ZhJ*->vM^81hGK2_*mFS$K5wOgwDk4HdW|#d_NUQ9pNq z=~>O}z~q8mFZ_?4I%26I4i!<0Y+oHI*V6{I^Nv-8I(9{( z$si+xpts*v42x_GCr<%S#!dhD0V=X4y8IU0NPPWXZ^?}ut_<6Y#GRsDGE?P_SThq` zMwnnY4&ZhWI;fbLTv~#xKHer!sG2T>9);uP;POpVdIj}#i~gt^V$5{AIm&8)48~We z#~LUiSGPUug=a%=gw*~y{49~ZY-$s;-v;dsVz#+!OSn&05!b)UY8Th0kMSr>v{<{MbF}E$(eTlJWZG(2E*NgXhCd{`WpREsJK?`UlBW&~f9J=B)Gt(#daF04n z?-_R%DduJAhpWPV%ujoP;9P2%JPLTLxemEH++uUjO3c*wm#NjyU9@wb4ryql-u}iU zF_6VHdZ*D5n#D7j`n@^w6R-RSYp>nsM1#E7CFF8dX~dh3*2ZO=II>goMCj`cjBqN5 zgjKyMfm8^hw(}#^tmCc56??QoaU0(h-Z(kFY7MBQCM-fK&ZGLNB9o~ZIKJuWU1GQU zd&l)THu$O+JpH>=27oodp^wcvQj-R2jI@tz8(f#bt}_C{krFRWW74Kk5SxJgEn zC_c=G!=3g{J8TUJv-QCX1Y#lGbik3J`LNbWT)fXFE>B6q=~eI9bO`O=a2P18>;VN+|)skqO7FqUWjj3U+PC zkg*L058E6wLJ@>-%J<)rFq+amc6@P+fQWe)>wvNerx{A?WoX(-5mbHP!E2xQ7*x16 zzq$LpV)wG3kn?cJ0S{37f*kk_>MOiz9O(7W<7TtKh2Q80uyhsyc6*||PGa~p+Ijb- zF|u@EWkHY-%t2*y2i?Seb7>i2*-vGp7YCu6_hHaqEo5LWgD(zgrNRR}YZWY>w~a`k zv&h{~e!ZMv_ob5*@;_)KPQpup$(!kYIa4a2>uv|jURwy}I{!igi##T4ArDo2%oINN zQ%2SPtBWN(vJNE)JN3)rcS-&EPkWO>m58l2P{0n8RLe#d-tRW4K@KV|(tLPsCN-v` zk<%is$|`5&HD5+>4(+p>l;<#!*{{iMrPGJRR*4{6iFSR zkXhsGQj$b&7x^7=v&ukkJv9Bo(DjjlrV)N+4?Ks2Pq>11p%2^=IXr)E&ZJjOlY1!k zoygcEASg@8jwU;u6^tCc`vn$4K(n3LDM+VGx*z)!CycB_>IcJnaBwi}78Jx+O20h~o*| z|MkhU%fFYbawd{&y3MiNuz}67-+rJ-l&_%K9*QxHZ8Dh$a?BK3+)dAif!Q!r4HB(U z)*IBRIQqQgFw_95?$NX~v9R!BRMoVs_9*tI#||gN%o$VUt;U*Pv7OF^HidkvD9%I9 zY~7pncQ3;I3(1?0s$z(<5c)kBC<;K^eq%d1VK;BPcwy&n@8(Xj4$`K^Ol|O7=i@{uTPGC{ke>uvH3c-T@(6JJ-c?oY)+H zrj48itDeC}*V@Uf=5A&>PTUr3Rv7sa9ImeVeH1Y_jkDYUkgAfapi7#+8tSoXo1}qM zrh5NrdZjA!@@V(rj-~aY5mH)upxYElazz z+O0Vul^H3!A8Y_t)0ZoWm#D+A&irQc4MjB8HEIV2AQVu7~e>d zUsi`WKVy~;rHU3`a{=flH}_~ID&!j|>1kH2aRV(I&5G~KGAYACZnE!VPL9t+NS2N= zLiN1)_Ic#UWXsrww|!cW;Ips8?%!B8C2lA1jPU6K*F;!76ov&KT+j^9wP5L~?|6e! zUTzuo+CZ=JX!Ji87P|2r(3J7;d#kk<|^6y7*P-YyB23d-o)mq{W-&pf2&?Y z9;DOIbwm6y0xcy`*d6?s>26M`Cbca#f_(&)NUe@809aBfR9?FdrXQG7{-Ocx3*_22>MFWn=6}n zH=;7wq&@=cNmUJae``|<_IQ!nk=ej=)y#Q9oK1PZFt@aQy9ZqviCw%|#W9Ep1zI1~ zvKZ+2q)^9Z?@Cc2B=l44@=(>-9gryn_Wz@!?%PZY^<*xW`e5r{D_{r^u{jn1QA9@T zv{h|~2J;#nxXx^}rt(A_{Q?XIf6|^iSBKa?OdN70(|!{obSmL(dJ=w&iNp3i@!XX# zu)~$h^gtwn$gcYIu7W0kFd4w3J=bb2tCqG7i9NHVttWnOr&@pf5`CAM4 zG+_1%1_bGt`|eZlA2`kMH==xF5di6demLw$??wLIl|S$cU2_PaZ))I#_`26$lWX(F z(F=0K?XWql>wa8u>E!g2*u@Li$FCep@i<>ISC|MC=dPS9{%^6E&rf^f|K`jUf2zrjBSll>y!wYM_#+`u*90ZsAvD^Q#~){3>Dtkc`pk3WFHb;+yhUs6xrEp1ed9e5gewf zy3-El8AyCP6re?aJPE8{F7B9k==~w(vgnxh;ZL{I_pzHt9M346?oaK0^}*zSF4YKf zJ@E(?cx?WRq~WDLG27ivB${M+n$=}j0H=#h(uKCT00YH{&~7@65X(^7x7s)H@5HWU zp!DdLK5;En^h?Y%7?1-8byCy*{Oo^;+aJ9rO1i`I#Q4=@3&~Gkz)|PQ*tVK^12bez z)UFA^xVDHZ3K&7T9Y^U6bnK#D1`PvQ_i!Ix7@nMSd zM`Ojx%V*Iz=(r@C#mb>-151XUKLT0ys{(Bes-Rwe_UkG>8ycQ`+t1Ewy9yP=mmgVD z3|A2Sx#OfCVbu06Uq<&ifN7sA^!*gikVRx!z;_Mp&3OLSQJwt4iZd-QbjM%tJ*Wiy zA^fVTUfq{&|FKI-(KMnq()mw#biZ$|PB^wMjM{fvQ*QB!I8AmGinL5GTTF|N!T@Od zewITi&&3q z9cAn7QDOTk&Aj>E=JRHOCP6~s{(|;093v*=kE`IAd2$}Q5Z8-KO}}r@9@S<^or*ZV znd1GrGmfE=)mosFQVlMK1A^gZSE2IWVtv8YgNP#tzEmeUo}XMp)~ivxSaMlXkYuJ_ zn)RfrLq_-rQRc}aqhOd5pb?4xu%CBcuK$1R78I~r)xQgp$aJ`st&*5NUGhN7X^H`T zfwo|Ns~E@DX7Uf!{1U)fHp-L1a>S{mrec9dtGL&ZfyH4gSYiz&Z(mdX@c=S9Ug=iMONvaXM8q<4+E(a7|q6@2okXDP@~><6lC zCq+&l@bFydSZujkc4q9Cn8;So>1x;N?T7Az8qxj?68Q-~y7uHg!?Bvt=zXHE{yp>V zDm6Js&y6j2ZOp${Lp!f?|2)>Zy1BNDJ_nO67YmG`O^Bk_x_D;j30g=ugYA!C?>1c@ zsjqMHIzkUL1&#a(gQ!1?2wqcfj#5o>FJAnH#89%;4W7P3pqeed5zg0vf2D=r`SUX&xUz^sd~>J&gNeS~5uwrMo3C zd}cb6RpDQtw5tD$5AU=|=5?)~g1cab>saGEqfpFiUZI?|hR97T$Q6XqFqK$g0RCQP zm>}x!s7~HGQ9{Mf9%mP`H_78D){DGauE0|(+P`RF(PQWurHP>iFwa0F?7kYc4`MEN z-iV5UUh2i{-ZY@qd+~V!w?#zU0km`ew4UgGC?rAT)2CY^#{HasPq1!OEoVmYvdP`= zRz{9tY#N!sn6sievZ}w|uSn1oKzAty=aVe255YYoA`w)(KAq?$)bJW}9lD0RH(r+Y zv!ax=85i9ue7%6JZ*Gz41EF{S3(#)rP{^SGx-uN>q~6R<;J%g*YS)so=_(;lUj;*Z zzEuDcQK<>POMnu^s&NKd$!u-Lf@Q{f-C^6d)_aoD`^UwtY*TVy6Sbp4D(Z z$wnNf%478`rE%x-Pub^8I34Pj+`o)~qVL5%7?kLXS|0+AT7gThFxw7Z0%;I3EAji& z>z|qGghQgy8y(SBAN|*4(($LmD|}DV951r)6C*ZgeW||UUrdO-;=6@%yu9G!TUpwS>;^ZiU;ezPj?0&l!s>K8+8J@2x4== zHzhwFMbdA#+T{yGvz+Zr_bgQb+k0!$B)(Ru2GJlVYUY|p`eo9ynaxG=v{cQkYxn}C z^|a_Fq}b7r!UKJ=u8N&T(dx(}9M+qYvFBj`=o7i17j?eF=hAp*Qk4h6H$g1^x5gGP zU>^kq?*3(xT|fS0F!L>kWtGFl$T;wbz1Xwsjz@r0kIX#;PXFTR>Kn^2fA(>R?Bf?^ zAQM#&J9Z_L=#8|tKX}=BVx@ARfkx6qy(N>b1PFIVoZHaTO^63gs zs?saBa!bY808_seAvcKiMH-`@bZzpvf>ad)w~MKOWt1xdoJ)d+tmu;v2p*bTH62$k z&~WIK-jCZSeTufrj$wrNt5$H(;f_zt;gCn@{lm6*0crn}nbDQ+r(_tJYLj~VEdNz- z(82Z%-46`@7o2=$Go`&e(D~MfA&oRfHP-R$lm$xvOHw@*;=mjdhHM-|t8N0iqf%Ql z`Zn&{!qMi648n8Q^iYh&nIAD6UV!?Sb~7gN%f0xawL+$Y;kIkCRoB>ys{gl1&V|no zwLuNrs9lhH2W)VTrv@SQ-^4h&ajn;r@@_FFFZdZGFOKMPhkdGEtzT=K&WR* z-cWk8tTVb)>RYNcQ?F4Dg%Ey%WkrtjOCqQ*8f(iw>mj%b@E3!9P~eqK%;$PKRPRkq z=M?;!GxS>fR~8!GfDbP_N-y5bmfMXMCxj%H59~TG;c+x;{@3}^vEq;qc@FD0Kf31N z365;5ohR??3plI9Ye+t=nr_B>r8^vYh7^{zN~H;wjEY<5v)#6mUds1uXx_3O^B}9< zACC@v+aRC0Zf~j;{K}nZ;eG}Xm#Fm2kB2QDz@aL;7uV|o*Uwd(|3s}gX}MTSXkFni zr@155Kby27#;b;Hk0UvBdVbC^bNG(tUwet3Z7MJzZtE7jhUv4=u@=XL9WNE8U4;{WZ98gV#njg;-gb>P2c1#Lo zD;8$vrCEBLkk5ZJ*c1<|i05qLya{TP9{P1Brh+T+d+xJkwSZc8MKw^m11-W0U`YDL zE0*&nS*zs;mNg!r8ihuqW$aRbTG}azWluNZ82d}c!Xte3J}XG(J{C~jum1TPfi-j( z#3l0Yg3h_t_P3o)^Kaf8m9saFkW0ANLs}%Ik{!&c+P|X~`gMXjD#;{S_THk#{Au09 z_YI2I+o9097JXuu>%59yU>?fkX;Njot~RmP@@=;^K43fR+l*7=vorV0HOBp#L3X#xItvI=WX#BEi6WrqQZHEEOP^-%!`0J9zyD~8Y z^2~zi71@1B*m$8g0V#CZzr)HmB7q71eV5*`>xBS4fm>y_|)F7I?Q1_8laOUK{Y{0|!MRD-RN0Wy+=1ipf0b zqimVRiu)c5F)RReCM^kmz87E8FUjJS^3{!rVhTaf-Tw#>T9^0aWe9+HNK5zMN+_-j zTF5q7Ip?`ucC#&D6W}5|0dPikOZ?4?) z@1Ef8r#io=ecQa#eSgbXeW-2HFhp6!h}0d`fHrnu*`7MSx0eqgbcCol8_ukh={^R( zTUKl#=Yfz&?6c4&b_@_<;J}jEN`2-au-7Ws%aW;;xaVyIa)e^mhl$npUwTB!@O#JR zvvZ177=IzAwAf<`iGyPf4)|We~Zyg z-ztRaiHgXr3}Rh_K+>f=Gw}8L_Gtx$)iOJomg^~%>0R+0gI-J_@lcnP?70|@=ZB9# zG@}f3-Uw!)z)Z6;Kg2%OZy6DYM5nwy*|o(S+6ao>F2)QU z4-M9)JxfAmnBbm-Gvm{)=fnVHue(eS;#!l5MZwOO?cM^Ump8}5kBOu^3Get!aKQb~ z=0rAWxt#+QXE0>@y;s~mpKPyVh~6Bg3$0jLmw&;?wfqxAW<9#h6|uM^)oyW?u<^3m zwh=lcOAaCdZNe|g$WFm2i-~N56cb?q|Fd(X&?hkPa(8r z6N;Z2-@}5)W=g+M<1=6f3GjWQvwy93{}60;F`2_5RdrJ1QNFpj@rVBf88!fdnM{lx zIy5MvB^^;Z(F7q8+aQP-b^Nb=Aed=Qkftx0GQHS1Hvao;{#PX(VRQgD6!JX*Fgg3^ z&IY8ul$4aF%4N5ip$hV-ZU>!AMY?WWc*!tmY9>)ncRpk)`!Q>ZkKA9hEooABUW@x) zyqWoUdMxo7Ipfct3qChP2)y3#Z@GFx5=S{Qu09U-b;kVe;0QT)jQp!xn`=;^&RRSZ z@bkDA@1E?z6qHka2l6^_HEbmI*mvC2D#9NO3P$tjaVY>ld80kMc-Y^&f?E%m?!XVB zRwI10mVtF1$QtE((>V~;Y0q29kMEs#Gt56}iw%wa>uKSV@0#`7; z)PnJP^|-~E-7gy(10wsb=$Kc2Qt1O%^!xTTRzsY?1vPCO|7hP3^~5`5 z=e~ID>!%YTYbLVD&!P41MkWBH;btx7 zQf%!cl0h;DQ`#nx=lK`;XYS?F=Vf=FsbIVXw&`^LpV!j{~<_|gr7Tjco zw?FU*-EsZuRQ)qEEh6M4IfUVI-KF(u%>C}cNVOl9%G_C3vWpqwA@GKBYHqm%8){t4jZ#Sf^N4iiuf z=h+f~WVVPBmuEZcIe?~mAd)vK#o}59%s)GI&IZ){atAaw^FureyW;vgi^B`HWw!KM z)m;gdo4g%u##9tSnRx1-ckVR$OnUwHuUWM$Kl^K3Gv-Bfef(bX^!h2U=6Ig|L&5sP746uLor2mOXmBoua* z|Lfye^%HR+r+Hp$*LKp5di`3o&5JF>TC1z z1u8qYgtdx780c*7tif85Ihe)((i1ziZe&RH-=a{~oU6@9cnZ$wH*hBp95h9W1`(i6 zY57M9OC1#pw@m2+@4r6i?ZOVS{?%P$VVGIk3LXy~tF`(o?`AU?NI=~oyx=(=P)&30 z&?HP3=_>M$T z50mg*t+`e=O+w%Dq>4oBcx?GGLc1{30prL|+Sr-csZNH~gf(m$RWI)@S)B>zR-Cn+ z3_AQ9Bq1HeyoqqBa3)pO!r7C>HixA}u7oFX!|Ww8B0rJFZJ;IZDFp`<;Glk0!mI6L zq*}LwyQC!G^&GHOU5sJW+)M-Vf=BYYpSyHO-4@5>uHix;s+;nTtM9yynriEJAO;n| zEBz#~8?S05P3zav4~z}mfKYFbB>}|CFnyG;{S9uIPB^`_a)h1^sNyj+?i&tB*CA&& zc9_d$Cjn!Rmro#4PmGjYp+KAo#JhN(cbNp?X+*g%vC@2$D{$&{yiYXOI-;}9u$0RT`#>9avGkOK~ zr)u!Lwk&Q)z_tE*0usDRjtW6IkK7!@t%e(sN_iF#%>n89^?UTM&0}FTG%8dOREx)2 zL^-PLic8716FhL($LG^6O)Qm@)zSm$E6j8%%2F=3zL!AcZxUaQUsS%Uvjf&BMulnk zfALL+U44G$U6Sp7ZL`lG&vR;0(0}{V%z@5K=TcEj7e=M~CKXK6=ohBxrr>e{2e|Np+X_z5cP#)P>09xj z4Ww6wrRAAI(w*Pgf#uN-H&6XW4LjZw>;Ivk0feC$#O@)9S4?iIodo3R$aE}gTv|_rGeWR2q)z@Q<$YYzqv-dV-+N2q zs#xT2ygOz)V)(vz>^No&B-xn@>$!i3zqP!mp^dmR-%rs2mOOwi_8S3VXSzNp!G+F4 zHJ^CbvaJ9Y;7BtNiBBAh;y~h|Fm{T@&>=OSJ_+k^EL3u;eY3#8r!B&BZ#zxi8)&jJ|S#-x(l<86=tQql2;G>Q{z;NrRW;jLZ#s*Q0o5iC85*k@T@ z>0cA_yeyxf?vj2nVUZa(^_7Ai@~eTQL0sZlbY$5_lt#_%1`G_W!!>o?3!g#na^W{w z<4QRFc|IOYtcREP|D)+D7~;yB;O_1cT!S;X26qYW z?#?`R_j~_f?wxbHtE;N(kgG7oeL>-FdRx-MRdbjo&E-qmsI@w>5!dl3Rcx$^b~%4 zc+m@0HLa{@uZ{l>yQ2zX(3a-rPLy9dp_&l9302K~mxw7?T6dR_3^wV+^zH69gnJV6 z;YRADkUhXaTG1RQ8)V$T6HFo0cMxLFKn*nzY`~|Daq?1LT-lMT>MDyL{Hj$Q5^1F zd{3KP1vd^f5^j1NK_M(crwR8W4{8P*E+{JblLG=@3C)O!GN6je@mWR9z+3c~P_;@*T#p0&L_9&{A%Z0G70*w19a$B*Empa@>cb4M zzQhpD{qY84%=kdJ=fUM>7ye?u|i77}Of#zd6!B@Y6l@r02t;tb)MuWS)aS%AxW^DvU#TO-hH z_afX@Us*Zn@fkye<-|SpKXft`IdVJhqw1P%jJ32xA9NpQ7{Wbl`=VV8L*O=gyU?9h z7!b-Un~-`)mbdv)a|KK{xGhRMEC~lJ*d$C$oS=)G;z#z@`}TR?I)=VWZQ#&Sb+gRg zIS5kbUzD{Kx~;=LjGse$or65(8_t9E3yQVy>bA2Ox}c3nA6MS%Oqgt|KP$H~y+IsQ zmqcB=X=f(EJ^OV4%!(uVXAxx{e`*s`?;GdD2ofU{od;7rQ-}3oMQmOK1wqD_n`z>DchI-s@hQOFYe`YPfQ=$8>CdS@DC&3V! zSNf%S-{NkvL|`87&YxE4Xb;)Ki%m+Q+K<075i#Cv z?O!>H(DXR-MX`j|kgx@O(efCsT}Q+Vi9@w1K6ezVM{_E#9Ma%I;Uur8%4fj~+Jzb@ zfW@TlbAa2*B)d%UtvvrN0{1X0Qu@!-!+_wK8gp9Vw;1xQEH+F77&E$z-`R>UWnA?5 zN}R*{A^6k;B_R1ooSH8z984mNPGg9*0GTHQRC{4;oK`g`r6gN(z! z(ST##^!>6%fg8E8V+i13`VG*gbW;qP>Q8tpit+BeH0R;J=MVR7v&*4Br3slTN>bq~ z29#}Fje3PV5H~u`p2TSz6yHvaK>_R1ThZHUpV515 zwVz6MjdORC{^E1SKLSm`SSNDV{7k1mom_zry?TP}(%Z)Up@fa6SLhUQN&{=d_=F#L zo#%f+)nK7{^#7&bV~uLn+`lCnVjPAHu>!sBay(Eg3Rb$&1;bO%+_4-=YHv#*0$@VJ z^uL7oCB1JGD+UTarLB<$k-XZdmzgy?2BG)zw0;EeLOqh%kTuQ|M}LYPI`K=DgvfO- zx_F3xvDsU6t+nhgQC~>MjfbC{(tjvjs6y2Ckh=^emK)AHc$i^@`)DH=+18pYq5+3L z6p`Yr9@Qj4S6L!>zk>RM4OM*W_D)n2R*wh3Xh__3!V7!D8A1tu_E|l)ME!gz_S8*3 z@J;`&RmboZ4^aJw6}1G zsFiBU#{CMyQ4l_pAydDINzWVLPTV+hMq8j2_M%b*30H-SNL$wq=R$CH(5d>m8wP|gCdfz{hX#TE4*X;R*0_0qKYgZD8zNqZXkWAa0s5W>6(F#f*f=Y zY7AjHpDb!@L)^$tTa=)@UNqaCUScDwcLld#5|x2kN3Rryf$BU;9A^51g`9LjCxIzu z@Uc}v;#=N>Jw^HnNbOg`veO7G9$AgmJ{TMD)c`$@{Qug21ys!+pxW@g#hHMd`c>nr zv(i9Xp;su@Fq%4ytD=~knL;|aNi-#-EjG}G*Kk4QBMhx$=2_P{1Or_DURrD5zpi*D zLiP+F73-vk?IVHZidokxzfs<)dlBh#s8ye$oLCXKn(GG`+_O$#4MhK)2Rm&n zVu3>DhGK_{UmgAS$^~BV=@7}e2i&m)qnkWbP+IG|Uri?fa$cSRO1=%gn{4W`P*md} z>I-UZwnsjbR%5vxGZ`J5;0cP+=X_0;NNF8zmzuua3iVQZE1Y1d-N26$R1%e^vf<}DsYs?)2j|I zep5TYqdfC_i)zkG8-Ue|A5iPk>_WH)lD&>6cu%uVfRczDex{1QE&8g8Sug)*yuN3b zhRt@WX9!sJwg~zLz1s2@;#)7WPvZ6W%(v^&8}ht;emrrl3Cw;F?TYd?q*Qw!@#pR~ z7OOu(nKhgF%Ka`-C$s*UAs^|y@6>~+#^J0Hf5*#inw_h+!e^OkxbQ_p`cxOGG?&Q?TrFzACHyT;MwJ+#+d7wkKE0o}e57}qgc_U%v+1di5x zeeRlqtV1V&-o8VAfXvffbSC4qaS+#~Bj=(LLs$x`w2J3hZNuG-k;84cLxNY7y9p)} zunL77BF%j(?O$@?b-&$jl*8*j^K_KmE3dWQAwDVHyB$br^SA_SV3Y7#sDXk0DN9Z??sOxK==JNp^J7w4?#3h+Y*Qtq^0`RGiUI2 zvkNiMH5Hm|3F_yUc&C=Is@TOG!5Gqxm32czduDT~hm5_zoMgY4RPsxh~Xn zFb$BiYoPFu+}+$c@e;A(#~dJS(+uSI?OvC%kD<+}oDp4>XUZ%1IRe7Rq1 z(L0+sANdG~5n2hX+<%7TT#;2Q9arx*iGcRYhc%u4qmw~z3!q`4tU(M_oxkBT^_|2VU7!Q06C z26(wB&#u)aeL6=S{Cy_{qtrpV@fZUX{A-vny3pf-!e_K5_Etd{?6&03C;Bg;H0SCI zTzp-eknQ?(ofM^kkC3MvDf<;y9#&Bc!5L|Dp3g{Q1#a6(1I#Ra^-H#`IoZCavu;q{%8VekDq?m+QM6c@8)g}$QFP1 zF?Co7Iw2Ut+wmFnGN`EN+QpphT-Tg9_r@9pge?YUCWa3c<hZ%1SYK!r~nI%g2iRVc}28=~&eIXDy z-UmfrkL*MLA>>z^Z%@OWsH*UR{n4f}RZp+P?Ng97$lFUbK=7?B6Sg%aH$zf7>ce-v zn9*8E_?ctpD+0b>%|}#2q(0TQyUmf9*DR7CA8x-au9>rd z_wWg`A^}&yJf*y0XWF0V@4KICq>v0D(YLdl+reuIh`wg+p>2xBYva;s_rf*leb{Xk z*y!Pn-%sg+;gMkG&&0w3^2xubl^0YlYw@R0!hjh=VFgSzRaB$~XMaBc&hVIx_i` zKICz(b3)T|GePL#Nj?TI=Q@}1OxIK-CAKtP~VsI=^K7=@n7AKa&M7`g_HkXSJvQO68iYif?<4RuxU{OZma>L8r)$ z!)+JjVid6c;LQr!ia+`N+k0IAnVOdI(m&^FaJ#3V;hUh2R#)i+9IQvaQ_H^xa+!pK z-xT`AocgPp2i~6KsQBkSCjuAl3YZJ@>+_hTG~V9ixnh&MA$in_5q336o)Bzn!tn6Z zvvUcV6B|zMFhgm)zfTVnfYmouHeHJq7nI3o5@`3U{f=>L_NhsX11;HWi#5%>BS)jo zXy{Pu64Q-o^rP2aztqt+>lH9><+S5jPZz5f+{T|SsAkW#k7`qE?WhKkieYa98Sh|{ zHzzT=V*IcCLg8NQfET4g7@{ygq3YC@-JcQ-)r3-`b6DFLWaqgC+NH+UA zS#~~}tqX@^;(WR+T^^Kha{+R$ojxBUT*YQIAD}J+VDrC>^V=pYa+%5_F!;R|DM1Ok z{0U4ba2fI!hdd{da0)`=h+;<(U#ZAzRdN$gbp4?oj?RKEw)p|_*eG>F-Qqy?t#y{Z zgR82}%Qisytt2oi*J_thBiw`D zLZIBYM}@mirm4H^Ql57+k%h11{z|SQR<&O5>X?y;Dc(O`7!IOz7$fyNu?cxq85?o^ zg^&w||BIvNT-OhOdbYB#0wnZA8!Hl$27x9vWsq|@w9m1;i~SjAT~UJzpaD- z<*rQ}Q}IibXKQR_oUP(*$0{h%HBi_+<_!ik&CB@!+|M(wDnaCnyK=z#%Nkkevf^fM zUd+1-U^V6k+q}!6kEux4{`a=KG(I7P&UB|>&LQ6upx60?_ZFm*$9wB_KG}`Np)*F2 zWe3X;@GvR&a!R@x_Xm*@HZ^K28d~7Ba0TW<3YU%sR((*oKU2keG5V)n>*RbKIwBW- zNu|Y;Z)TB#uORCUcv}_pA=|+q{&l@=!kx?2&+AI~)Vu z$I>@Q59*JDclA`dGupQRc3#uIPLP6?1-C?}=`I~l?0mCda;sw_7s%=4!LE=;-36e1 zmjJs}!Cf*;qHgw=mjTE^;EM0L^N`*{EhO*uNi<;YDdQNN9SpKg<-KJTe_tJtlhL;tO7^nu|NfoCrHR7K;AYA;Fy5|-{ zd)g+A;vct{N8qdd^J2PFi7rMIhaFZ==6XYq#-O}2J9=%=f^49fr+3u)L?>g6apOd)Tz z0@3e7`4%Za&!;B_6*1SroVp*GIes*Tk5}^42aR>U@8uuW<1e64!T*mofc>};)d8R7 zb))Be6dg9Jn?5;i#XFvb_giliVp#Ola)D9NOqfqtJZz2V6?Eh;UZauQtK~MsI|-bP zD!?g)p4%ywP^o((jI%K|!(4{_! z3;;>@@1vBIp<1whwI(Mpc*s&fnjQSAXJ6~o1q)#nm_1y!~(rQpbNoSPo8tC7x!rA*q2jRO?df7Gqm5+sH zjabzZ@bbzXDe_<|Qe%;1w9uzv=`pUnStyX$s~;w&|2iyJbJGhars#$`I+bU33qI1N zvb)79tIHNq)%Dqaj zwj~?P-WVPyl{V`Tg^EIDa1jHVrL7|2YTy8=41F*+3c5~u1FC(8SKx?A-Eoi4+6)R9 zIrL}c@6(}mjypxZb-p_oN|s!Z_SWAcj@|_jz{&JiP{lk@&*jxs)n_EheAI*HXryPoIp7Y6Tu7GscB&6q@lEP{#0sO z=8Ummswy&=5WfaFl~8nL2afk$e?$o59+YPh)%u**ESfeWR-o7Qi9H}BZ41GV^W{)< z(+B-cP_a8>W&iK^cVW+H)Yghfu1wN{ut-_XWgkGOXo3=>1a?wiy(E{agb5HaqsAqk=J`*roH$xYK>1UIs2U_jC$zDZ4Bi5Li}f^ z)lUHa&VBLfDux?sKbv=o7lI2ue%CS1?mOiBV`p$&w^J)=EPeS}!nOte+Dx-Yu0N|y zl(xhc6T%;BX?vVp59%RI`&T1?;{}E4VkV}Yh3%GYPS*cbE1T*IGS8$b-h`G1XwcXS zYe^D6QYCAJ6sif$BCPGK|NnMxa#|RAU5}gT0DhwhBX*Myn6E%BS3l#Tv-5gzQVsA z>ym7=zBa!J{JlR}j(LfPc*=}_BU7M8*D-W5=7ySPfwx%d@k2SLm=x=L_WD;bS?Px| zDOufL9chAbYJjm7=EF{7bgU?xG!ApE$P~1=8AX^DEcy8()a4z_an&k?Iq~hx*>Jc? zSDH~5op-}wTLw`K*3i(8A&&NjKWUG%@tc&akwn_%P1pr0uh9pas$l0w_QOrxV5-95 znq7*j;lG^pAznN9-0`8gch_s8F6TsTt0&xtD#Gc$KC`|w|E7H!>3Sb9C2~IgJndWM zV{Tem@Vs~;0rU7yd^A|`?EE(09X?cRL;9#ozHmmDl;x0PwOz|iv4D=V!Z6#7J5se# zhL{J%v)3@pu#lc=_zvauy~tbxys+)Qw8|7VZZMWr#)eha)WS4>{vM;jnX6)&{B0Aq zq+O;iAo>rlS;)Mlp4{|L1f^7(@noD|=wZOn>5b3$Y*Lk^Ujw{(-?rZ}(Vlb4Q(jlb z=iyDY9J2yTgLbz)Y}<3#V6jX~QAcyFU(k?qu!>p@{lcHxP9#1*YlkDK8P{_7u@52` zK)dfr0Ni|dt%Cba9W^8re{Ct2CK3VgVRCU7CE>xDqQ^%3EMT>nqOixMN5Z$1_HP9p zm{*>$np)hkT1l6k6__~xd~-q>yywX10;bGt9DpTEW$79w%{~(ox~znHYZ-O!bi|+B zcy2?bqUr&`;P{OX=K8=PKnuh3+%A?K+;=EX2?{ssQd?VW^gQ<l3Ir+{aWd`YEHGss^9@FHHs2eXyys@qvW7Tk1N+z!9jC`^@!9gQ` z-9N5RUEC9Fz@hpxj8-D(t9Q_`l$9h_T(^UtK0>-Axhy=fb!UoEx8)~cXjX?WR7j0K zTn>0Q`t80JHb51Lw3A}de3B2PYv*GwgDZ>Tf+A({77JiE$*ZhTRYUo3|94Zx_lFQ* z=`RwQgz=c!kWB>z46K$vu<5}ER^TUHIA$!+OBGB^SB`$R-5j_M5)2i=*v@yL+ zqQ@6|bk*5fBXaLa_{12n`9-GBcdww^ov6=axE~pp1lw{w@TyqT8RU;R&u!~_@;`@~ z?P95?mCE;+rCPq+5R)DjcHTNdUVz#zJJmCk)euTl7zH`8E{1ul(fbU~N%QFPo}U9i z;S*X^$ZL)lghGTvZ23k}v#ugPfAv7MVygbd`~+zS_e<##dGO?7cP%`&XIq(ABY$&{ zBJnzR{$fmjBG=QNG_JBnhN}NmxGi;!=^()|vxo4@?Lgq!DPyNK$K}4Q7t4atBrzcM zn5X39-Rw`G@C6nd4ud4L!)%U{?0At&MQXjtux=q+-j?@~=pW?&0Hpx2jt4q80*Mh) z59eUkC8-SewUC^tW_RY(F&?bE<@MYUQ3GBZ9j2IZg@(Z|<5IswxMkIC*%}4e1GFo| z#Cnb7DJTK}0nS8^y!SdFD4sYX$Hi}Jx@rO0xy6`88b#_aPX4%k92d(JzdvkwbdOXI zUu=FeRH_lW^Cz}8@~8Fcj`e-N{skgR+;XyQX-)5(Q-fPoY{i4Q!`RC;F0<7Hm?rqj z6K*NBKTpKFi);fL|J5<*uUX?bn5obDb?UK7JJ!u{PNGTj=`UhYBkf>qcBAq`G3(b& z{7-$)N9e^btamg7Kh)zLxA^pRhA`7*QLw3$D zr#vn^#dnheX2Vyq&yG>FaH3(@fW9TFQ)!?g0haD`{>%%NV{a|l`@LuVa~1&CDmahu zd0&Sb0&61_B>|>gCjV?pme2Nmk zIlSKQ8l?6NNc{=mQ|p(A)~V7rH!f7h*8(3>v33>{2ago4LpqVd-rBnBq-WN}cQcvq z`k`e1ta?*-7sC9wTTqm&OZ$mw#;8|RFpBCta*viGP{W@sw@oda{X_T1U&>Txy`naXn*xI7dhS+jUo(!LfLMdGF3(zAn)qFe^7*H)&yopuO`QuQPGfbzk( zRRImtN^GkQW-xB;!*lt0#$XQgqIJo6ld&yt8bV1rWP0BlA9KEky4&bw=eF(%nKOfS zJyb#VK;=fLR4IRX7q%tmuSD6c>(PqysRr-{KO)z1Dd>_YsPaqt;%6d-G zh|(2eW=|_~gdb@O1xKkugtH}1pGg)Nt%s!3d|*uj%n#-e;|biGYvj=UDcYx{LwlwA`wRX%X6 zR{~k|>h;#U;hqY7W}4^waO=8k?e@;}Ge<+CpqCQSXy+o1dc%HZA;ELJlY#mb(lieImMW77)iOP5k}-xn>&9aBW{(^p?Tvv4pMfT6gTQ>z{fAR#=m z-9?aLt7b{c;qs=0b>GS%uk**JHz~4o|61wk=UB6DIQ`c8e&I%8{Q)^Feq0@5d>F)5 zZ}``^q@oznPq_4k3}6eS5TVk#MI(#}ncl-K{7iTLKFgwwMTGD6vNT}o2kz}%27Sg) zSaZgf`$?VC(00kP>%rSzy2|F=74g|;{Bp&ABrw-}g6|TJv(Fy3gv4lepHj5vd4{1E zjJh4{1Jk)Md^3s}sw3Vld=d)SJ<-vxI$_~l7*%pt)pVc& z6|(qwsk$XvHP0hO2%*gN-mkZ&Cc&9)ryQMN3~_BBJ)TSekP6L9)Z%jQEF-9P>%>3} zpsy^SA#X?t)DXpJqXspRc)Bv|Z17nsc5a>B&gQP5kgIOqVIc@P(y*nrwhUt8WV3?A z9G(AFBCVp}hsLr(qE>3Y3nORvVWGFIv|$I9(nnhOGISiZu3<&A%jfsai>sNx zlupEVeE3;EuREO!&f5eG7@3d?XzmG??nT&@a z3m(bKzT}LcMn7697^sx_?-#0KITKP#0`r?q_xZ)pnu?!LLHbZ{M_)l;xom}GNtp323eMk8QG<3e@W+w&oBy7RowUse zQ6SS7+9@Zm)22z2h$r=<6b=O=v@!943x)L*#;V^(KW=ytv-aqFW5^58XZeq;2lOgg z8i5mGN)!nB`pfUe2^G!Kj@<1}zy5y2Wx98pp2EqmVdhAsLrdnRQ3q+c_&`% z*ez=W=MRKWASkJ9El>Tb!b@X5vD{D1VLQCJqfR4RR86pWtRP#Vckeosc=`p1+emX( zj2}a84>8i3Gk#q=;E(yQBjrf39=*VD+sv%JdPk*RvOk-PY$b`l-*=>BWiPD~X*Rcg zB)b9msKO0UP?E${X~U-j;xq&c1NVG^W=r3x<#A0{YR(Jfl;G$=_Q`*P+H2gryWty< zLh-yU`KYv(9hbd3B@67%T9p4|Pn<-Xz*G;}C(nh3gFRSIpRxlc$rLM`ZdztUv$SX0 z(JsZURAAOS3+Pj5(qQE3VCZ^OaM{%GS(z(>GKlZ6DKx4g;MyNsMUU*`9tixK5c>IR zT5*0+h{@|O6LSXXgZd9$D)(r9C2 zw{Os0BLI8ZtrWSBz3Xev~s>1$#*5 zUp|+B|9#$#(+%3k`vb7A<>HsR#=;_Te7e@><~jNP3fE;Y<+Wx zNC7ABX1GH{+%q`GC^Nda$j_fQ_Zh^}T?|64q79%{WdtFm|1>1eLNUB4dH@0bdmogS zcJ@P1b%<~0Nx7Dw6*Sj_yNJ9YN#LT(X5fe-H-P;)X7)q@WaHthKaxhIOXyVl1=A>L z#pLHx$q~ymrBchxbuUApMm-ROZN^f*OJM{AZuu>}@M^=B#Gc1r5u-cXD$5(6=iVT7|GKZ9ZF7#JE{R3(4N=?`l9xn?4@=(<2kVPUolxS`~ zo8n#j4f>cRlYXS!cx*T`dI?(1UNU^-W}~o&9Z5}1s9d@=+1QV&@mUP)Ngpf;4Jp=a zGcL|qFp!pK0k(4G|H7kOp)tdKgbE+t&y_*mp6>RL$)(Xe03gj>7v>1ET;eg2Z z!sA3aO$S4%!sx1amg=u2m-8dI^s1d^7m=&CwyC3#BPhA0U||Ox8?;P5qZLkiKgC7< zkp&}$6(ovX(bytz5!b^*tzX9UyD8(Jm9y)cae{Au<(C^tf)ahJ0=-PeozxXEoAmNI z%H;hBk2Ube`W(>k=rKe9Y!TXV`e~_gy&PYitva*HRtmg{ziN%vkx?KvHIVy{q%sEA zsTg~}Ft})S2a^*M?){>0a|=*R%P*3Oua(lm{`?zBRR-|6tR(4WEi@Q&`N@rAHUl9` zHQEqk1Wm;BO>h4^s-v8oKm@ShnBff}{tL(Z_x^`*G#_COX=xj?B?|F}u-%Pe}=WAz^irt_(F!mP%C-z_c;yfN8NLSt(AM zng}>>h)q2bQ|cToW+`sf;cAWev5xW?Vp+P9ZhbBX%}4MMew}=_sM_M-_e;NlQw%9} z_{jQQu|>dGx?wcdoSgk>N>gA;| zsL%d}>}0ti$2JooS1=^XYD8)KwY%CIZZZ-Ii6Rbff$lwJ<{zhf)5mgq!QOLLZDI>7 zn4A*+-3ZKBW}&|URvgx#n*diWdib9#_|OADEe=Gv4bw-att-a{DtM4ofO~Nht4Q?; zGETA;Ow4L4{Ov_%lAwrf-8B~bNZ|zl;OZt+Uhli$JLvJ*epDE&M-9id>sGTQ9B?DZ zyJEQ;W-Ys?e4y*xtqKTPZeliSp9!on7ib26saE-KR@lL7_kgMnDlZ*A^n~GuC?`n% zDF~@%BlXew)5mBK7eG#b=mHH!l5F?3Trv_Ghq7Ge=w2J=24lY)biobE^@{!th~`i;1mV?)tDG)lwx;S+bnEMP_4PHW8E4Y^T-ASPxYTV<)d= zY*)0_AU@qxX9^ay-`eM;N$%lp0cDI2sCqtmLmjYpdE^^K`b3dI%=u@{gD%0zubSPb zR6SE8>z|sGm{Anun|_)J@JqUJl}YQ{p(+|bhiNKcGbJa=*fzt_XUqyJ{OYLnH zHbx`5BO8=316tLIlC83+8x#+<+k=fIvc zAcKoElJA)q%TiGvOk%0vLXVV746d-u&KenjA6I%v=4-lZ!7LReuL{qt*MZiZ^JvQ_ z$Fn+h&RV9a3{dB4Uqm$Nc4chijz#LAumG|zTqeL`2uAYRB%>X6NGRhvDO|KCVr=G# z@7H=1K_Hc7IRnqt=UsC^@Dwp5%~6-wRC%c$ph7B9dULr*no3e~D|CpRHyol)^X@bz zaoKSBFkliwuk+&A01{h9)**~*l}h#!z0AdrC+s1xnMmX_9-`|NrC4V&MmAqe2r9B+ z#fOF?p)z}P{mhe*6rWn~Z3ZR}9ErKyo1*A&mg1G2JJ&y6@;CaZ9 z6Rc6p1womfpYp0ulZl0QBjRiePWu1HaT~XBqk9TPjsM~vW(IzV@S|qQKo4Cs!}&cW zFDeghwhj5y4{fwv>&7QK(pq73m_PM3eN|#O8KF^joeoZnvRY}SlkYDI0m`Y+TPI3{ zjUo_wwDrpRF&e{0!s)TrL^*pm8PP<=KIi$fQxqqM9QnZc?b^+;%hQB&43 zX!tqk=E95;&C!O{T_)VrLH?g@oU5LIyAOugGIneR1i#j*5#71`Je4K3)Sjb}3dSNpq5RJB%7%3@B#J%Z=;Xa4 z9y`cboh~8?);Cye>an-t7P%slEmIFlY{|OD_&D5uu?7dbQpO$@du)xPE#cb1L`!e2 z3VyfT+^e}^hr@1hoxQ9p*37-y>Sr)zhs*1BKM+%whw_gO@vvDCz@F49|2y5B8Pe!)zODnh&od0kc<|S%Q1K<21%RZ@Tt&c8lq+X9U>BYa#dh)OUB}iPuiqEs zW16m^go2?|;lDGHhkRmW{5JnPKvCL^%jgY>7wJWa#e)0WJBbQAaw?hT)B5hy2`yCF zB&E5DhcPGc8LRqNLT4;65&I9*F+R!7Mn2pO$QUE96W;fngp70C2>aFK#*fZkIf!fp z9Cz7RO1rd0wbUw@{lSw&7t3e<{p0qjH46icMlC7@v%sWtcmrOxRq3dBt>~u!_^%Wq ze@xgK6XdMfBS>hsP-*9n7TJsj*Ms`J5PscD^N^R3>`ufLh8iUVa`>4+H7m2Ci^1Of zCqUYTu;H7BL-|>wFU8~$M+t16gtFQV4T3)X8tuM{ktr1IYdOP~j zYOQ93m%6CICy3_~sHI=w&dmvU7MK0!no8d*sH6F@*cqW%C8ugm%IDAk%Rsfbv?gc6 zn$I~h+K36NWqUNeS)4#p(qv<-qa${tHPy3cS&A;{`g(#TqRE73EPciiF%Y~Um0$K) z!U&kXXkffhy=~aJ&MB$Fc~q;W`7|0xZJ{vx^hT7L0i8q0?Pbq(OFi*(wxL-04n*$} z@y?ts7%37e5P;K&A`iFw8Sv=4s+RwVnGhD9PX*B((!2G`KUPXJ6%s2~|sYV-usL6T?xEd-o? z_dD$iPrcJrF>W_=`ZyI}Is@2Q9US%nSjetXh}ao*xk`%P_X<)evx&#=ZXIoMvU8S( zI)C2ONPJfAG0~w@tFv7W`W)FphM7QjkkCNG7hh|hD#zs@#Edu_?HTK^6VAgw;n(6- zlS(-M+4#$027jRT*D9Smp|}z*U6;t~7+B_gq?AG%;km6pqafNdexb9VdR#-@3< zukT;MAA?csS*hC6fZ^q^vZ)<-1rL9j0q~&B2N<{7|8(3i!Yq`SIE^rKudaq)hLKo2 z*whkCxh%-?t^Uow9O!}Za;Tt@x1$Fb6P^X&D$n!!+ zZ?%~<)i{=Yrvf$0Fx~UTX=cW79gPElHQOtPE`ZFbYPA8syCwM_5|M5UJ1dv{vVZ=; zLP+_F9cc=fJJdsBQta!AXPEMEnN+N{30UbFjYA?*`bD_H0dmXahiOI{8sOHq^m8(X zA97)$3=2@ugt_G;`N+s0WdL*>*f&_p^o?M$Tk}Ly>sU6v0Csg;;38n0e$K!Zz)jmQc+;%#$1mO2Py?2`lVf_< zTMB(owAWRHvbr^vvI)(*9X4Sh2FhG^>SY>Wih&io`ADZtp7#LC9ddF|F;p0VeZT7p zdm&onV_hxIHS2F7BfE!Va;C$ln;LlI^4QEAY(zh{?QC5KV?G$B9AjtWZ8{dc-nf4x z$Ey(9XCz$lfDaGxTC$(LjfX$LM;6-JSXC=<=i26w%6IkHyO9b3xD{t@43|=NjyE`7 ze)(5C2++eF=rps%8BQ|LSqL&J3AQ_GH!pqg9oBLhd3Z$@P$aY!Kq+UQIN)6&=4pT{ zmPcmZsuP}jTI46O>gcPM^#Oe4mVsjH%$mMTUEvA(mN98)YHz%47@YnVuwbnWeNX}UA5GZ!RUed@GM6-qUmAS!5f!ikTme-WzdKX0_i=59)m&Kn|U z!nF1p6aV_}_*jG;>Yr*J0h)pnNREoD*kdTVF1=&RMYc#!TnU)q-Pm2M{t4$d74nT; zzhECHQnWDVydbN)jiE*l!xZqaB{HBRw+Y91R} zCU3bZ{qsbfx3VjosIazx#^oe53vB@#zAI0U!|I_P@l8rDyh+MmcnLJ^X(co0Nd*Ry zeaulV0)kbe=V2FmY(%PcO5G4D#9Qvox5SlwqjFzgmyHOrWo8XYsOzU1K8D8fZ(nK+ z*i`9i{;TMS;02;8oxaY=y|(`8%gL9c>|JCz3!uw8$}7ncG>b59Y(8Ofe2dA^|6AgRBQ?3dr?)Iiw5XeOeLG z^Q@TP<6k#Uz5nf5ueR3>aF;z36NbCW6IS~Wf=r)I{`2#zkS2L5z-K^J)`o)d1kVuP zj3LqCQrRQ4Ge+O!jm)&RGP7%*Rbw*-;6PO#E_uaZf`-0Z|KE~*Wn=}C?5&x6(3KdH z)3kogaXxy9*W$bWsa|MlCm2wDhtWEVtyMioC7^O=uG&<4hd8MMvWBr|F2xBJOyiS9 z(+tUmvAS}o=sUV><6yFk{DNqYZdXo*1t5^!(=+J39lms_HssQ{luAQFLb@=vV3}Rx_Q6wwx$?`jx1hgFb}KW5GUy3w#x8=AffCl64A5}tiha(AHtpx}Ixy*B?^iC6|D z@s+APl^7QeyC*RVblhXgUGsT70VNsvMo)?$c?=gd^>eWU?tAFLI~Sq80#`8`U-H|$ zxiW;GI~FlE$+e((s%J#{nwi?3E1=q0(L>u7`t4k#71xn|46sey z)9;?x|6}j1g5%)1ZNWA(#mvmqhL|a4W@ct)#}G3!Gc!A8W@hHZ%*>qepYQxtQ>W&h zJ5Q(XnVJW^v`T8Vq`g~OT6=A>JhF6OY?r=`)Wc*0h9OQ+)}J+$Q*kaqV;ds5_~WQG z>Gi@vnN3UM5Q9q}=+&QD72L}T1 zrAEp%PD>`w0W4qtGTt9?`<^pe0}gv!o^c)~0zeovIJYHW59}^w5^-()P4*g3eigps zCkhd(`S%qed72IoQ4VuW_6j8Mte@vYtXRx!73H1z_!gkjo*|%U% z(OE)Lsa3ssG}29CqV~fXz>T5aKZr0FZ2SV+D$=9KN(Ahhf)h-?W_~?zH_10BG2}p9 zp*WCWI9B^kXyf};+~~E}(l-i2dMrwY7K=2^Y1pc|(ZT^li#b#dKN>od891VN=@kWB zxDI772M8a?G4UgjvM@pB-{K&+?&%TVo~s=U+>nCjhWQ$f00HCgjuOv83<x-n zBD~ zlyf)AGrk`8ta{x}tdX%4X=09LRlG7~Ob3aMB{Eb@k5H0e7%s!IB^BJMgLU&1jYP{f zsoc8^>12@tbrAi7)_Oqap*OXSFh-31-L1K1FWo>jI+t85E-oE*S0pxoQBhq*1502` zwgm$V>fUrwA0*Mlh!Ws}kU5CV2x-r){ARmjhRZdS;cxFItN31_O>KvFm&Gf?z6 zP#``Dkmrn;Tb?#g@y?HVI4@jO$&AiEHvEVcSP%-NR2@owNMj29>_g{r;HSU~zSGB}AdolG*LBgI*o@uB#*(|{$WaY>2eR;m{U>|F+sKh-JeE1S13deLbX zprofgYPeWyRIA9%oaP}xk6ETG7xV9zDZEr!U`!Zrp|#r1DnEUa=|+lUAfpttX+Tny z7uitjt9a{!o7Z3hB@Ut@9U@?jU?IloqN0k^ZX>MvKhHf?O&%E5y-H1Y_RNnV;}p@Y z@3BqHjOS}I->2T(4)H*0jcVc%PaXZ)YsiFb3nwYC(l&Uyf<>Dn!iF+kK;q?zu$NPx zJ|a(m;9yS*umXz)0nbl)$c{KK*CTMwTub$z4$bVBnl^RLVW|ZJTxp=JLl~y%N=iKu z*UI!Jras#{fhV*(q!syFl@EGdQkFbw1+=dg^iy^UiGC|-FhRtYvk9)9bj6w%!cx`bind!?FoT&y8}VY9LQMYsTO32XC-_Qe>2m?}r;Y_al(oh^9{B zub|T6d<<&)`?lBDi9HA@RS%CgKkg}Crg=e(E;3!;jM3|Tb%_$xIsCGf#6aH?0S&76 zsX)=-NZ208LT;I5yV6MOv-_;|X+R$pqpkYS8QOOlID+u>6w`mMVsFCDvq}!ciUrS< z)fg94`@yk&wPa`Nw_Ahi^`C#NK{&>gu*8~GG0ZPhQY*kwl=Z!To=gxiZTH0mT&PusucyD* z%+xvl3MM{lfz2DM>Irp`1}q0HTy)HKyM3)S(LppVH1JSV?)fsr!eq<}KOICT-3OmP z>67;8hn3MHfCvS<%fcMC%IhmVKXHHS05~WT!J&bJ-`A{o@eI1QvRM0vUbBj-KiguH zjiSX`uegc{R06rkw2WA>!)aLx)dXjz3gcSTSaCL~WwPHI*CQN7?G<=DFz zU)GAJ-$A%JE`8s>v)(9io+GfgF!&n^*nacQAY%8`vqS^A6`5W0`BQr2 zAI&^^F=frw1q*dz8h(2gcy)IHN~CAg?;JUlxcS7476@U#)WBIpM2GVMqw>^h;3P0k zxgz=*Dq7E6X)9%!_V(F>wW;6?@oCs(xcS))&XpjAZH_#56jNs4CRXBTpU0Gwp2!%5 zJ%Ii>>P_?dmJ>AbDqrLes5W4&u7jt|_>k0{uyO8C5EYcsWr=l-SVS60E&BUcbT3W{ zmZD& zO737THQH(Cuf!-ha8aVk#VFf73|wTas8{O0?}=qgaM{B5<0r}D-1RETGsk0SMhzww zZ-`dcjEjaLdONsd#^w8Ht8XnxrG!E&uWB!t~(?s<||DuL_vt}|6YTEikaN>}MDz(`41s=X+GUrwT6nF>ca z)(?wN6$Mf|1lWRo3=mm}p;bmZJ^;&MkP)QH)#N|#Psz&&{XsoJ_PRr$=mMDr zNRkyIW`6MwGAunsrAHZ#SZ7%26w?yY0{k))JAghQ)IK=wNGlp&$XcJscm|x&UnWC^ z%`=M`1-~@C?fgv()pC!Za!)vu*l-x)`p?8(Z!ql*d99^#Op}Fi>sf7bDg{o~P!E6Do#KF7xwhKppuNC|f{MmTv!0RueSf-DPoI(E&9T&S?jp zlr7rA)F?>)K|qJ_5FQ)Hih^EQD_njIKiM*EXXPI?RxNnJJydfEEO7V(p(JB@fxZ?? z>r1D6UMQWcCr_9o&3JaRXA2yC5X?a@SZSQ37)%6e_|w|PpC8ta4Ahqq)A@$n#%s{q z%-+ROzZv)WlaV9+k?}&gOli(Zv1}*~hTmIwn5F_7{Z>!%pPkuNl(^1oi372Rionp% zbz$wL&Pr62NcYz(`>->m$|=DrXKpSS>P!xtB$#Exf2|TJ)%jNf2jiQ*txQ~j=sSU| z{WJBbb^1$VN%|U3q|cQGXx=p%jA=3c{@XYedzB_nFyrl}i+sqkWR%hRM210#y`U|S ztkrO<0yFUYXae7svK$=)m8S$ypM)nMlWj1(%s-${~(_b4#1?H>35`kU{yIVqc_A6(Ty&X8~Ia(ZtV>uOaZ zc&`?3CC8Kq%kXQ*)G@0XnAGnYeK*3chsq7EPBA8ojI_uy`8?CGSuM&r4UHRm@CM3( z`v_<^ArRO)j|*)e{$YoUVL!{U;xi#k$>B$oyq`Fsz%d&SFTUn!yHP?ve31o%aFRQL zILxLWY_tl5JA$At9(&CjeQX>sj9((z7*5#G_@SRFY%vMY7=GD6eiAkixApsgUm1kS zo_pNoYu!XOt0q$~LcjHb|A{69JE!2@nWkQe zdH3|XgQ@Wbr>#bUoEb0ULSW@PKR#na_KT5M6#nB?Byy|Q0A01Xc=E_H@{Ne#TiIV& zk*x~nD?nBKm*|qYdREP#l4llwCbMJIoIPpn8>Zo905M&fxh#Yy)-YZqDoNd<1IJSI zzC)`7^M#r%(%=aPff=Utr!b5!I0Gp%no6wE;%>T%)6PI&)S|m&q?<8mI>cRnB$jP) zpe+-%rmdRM3hRvZo!1uT5fRk-bj(`PMyF;;z{IJq9zs1j%MMGmMF=KYm1l z4e3n^m5Exg)5>S6I(67b#Ka-xzXPw5m@h^=gm%4}=Sd^?4?P@fD5_ zIykt1JiFA-CBmFkP0ybR@(Gjhu}1e{$mRidb_N4clA zEoad8YJ(>OnjE(Tb+QkGI8+!BkVet#9~@BU8TM2{&p1SRtBrmz^fM8J@Wi&v>B0D7 ztIeYH4Bna|Ew~d5q-Jpt4jKn?HqB$w@xWpMM&6T z1GQezdxi@N)R&&}Wr^Wc?*|+OTdllw)Po?mEF--i>hOz+!ul(A&wonHoVXsmZrm^C zzWf;f!TvA^;OdQGbUQoWCjyy$^sEOfusZ~pes+QPQk^k0eRZb(>WSv|-r_LKhJow+ zVRVt&#PDhqH9VEJX7Iz!B?JPyDSFw`n;S5;rMxxN=KwIf$PC%#fIS@DfQ6i%-VGzh ztv+w6@sH}Uw-;^Mi}~Hjw|Dk6f5l)wrtB}`wNSUhg`U6X#pw_yo_<3e{J1j4<^QER z23;+zAX|}}2|UgsG~otF>^9$T0f4GNp30*h05iD3RePiTa}^DUi7wf7KssOu#1e}| zSuFwfvLnDHg=N-q7%1r*?Qpi8M-!Q$Cr+;#V}UH&kANh$dW%&gD%5fNt|JzA>DGLP zt{G$QoN$fdRemOGZ^xfbXXiEN!ybVIKV zIdLGOQp#A%pi&ImW-%v>V3lsCHocK`aAgi{mg@d;4<-TqlUEZBDi6Kfe}4!lM+BSU z%;vlNAf)*XO62g{1xGVLWs(?d-8P3fFRRZ3Vb?U|esY%8HXWcGf~<9f2|Ud*-D|}#9`Q|kGaVoE}8oa$BW8}tB42WN| zM`AVj2Gl+UkYt5-w|8B5ZKQ@jX1;1{UcY;J)nE48|K_$o9{RY_f#P`R<9y`jmV4oI zeT_CU0g!PMjI>@x!zIwW#su&7aPVEeOe=|J$JDf2o%BeidW`MC&0-tH85Pez;J(=q)pcY`0!k4H0@=XWF4HNl=m2)V48Ik%6_hlfKW0On1r z<-Qe5uWr&#N7JT`f4v!rfa)1A7s>9mvXUeY-nxAzA~EXvB4_@_&|Ho^KDyiQw9eln zdbJ!3wFQzWQsw^1CBZIFEtJAHe&$}0ex{HZk%Lp{1z&Tg^9z|}#>HCt!6VEq%PMIe zu~d214M*!~+yjHHAEsZ3kh2Nb697W+bE2#9ye z7Iz70q;DzJ|G^=%VLlbFM&vBw93bqAkBghI8`zCc;h9Qt1pS{`SZ#lF_q^PyVVV~gt z^ct(p^#z$)yEfqCwCPxy5FFvCCi@;+>sgdPK?m1!8he=C+@`6Kf~8Qo{KQFptVw(2 zeef8?RSHz7x9WdUv(z6&Y-Sw;C^C*2?h}NC;U&Itnn+W$_fsQ{G5LfvV?##5?53)U zMN4C8QME|bo;WJKD5%i^^|iQvwTY`_Gd?++Mx$>gj+cbdqlS@rf1%jUJzdC)Z%*A% zdehyFz>@??s`TG~-10$kjX?z6r6ho4CS1%qv_&ZfWu^{s;E(%3? zhQus(_)QLBB;T>Za7|8egS|q35Mo!SPT4Xr1EBexBUMtFEP`w#C=f<5HXR^5>sH=N z(M`EeozE-^bR#K+{Pk%?T5%xb9otX+b3jdo)j4GJ9;^wTN;tZ-;B{6nF;F1dF?Jhmp%4bYZ@~z>R*2G&h`8W1SfcAHm@G;><5*UbxpjHuN*oSC& zke)Ml99Drw0D}g*0b-&`8XS{tM1Zt(?V4epk%8FOVqAVqTWkeuc+*gz1Ih_bpKIb+ zopr&E0D$XN7($OoyRacMr?UK$KAaue6shB-2Z}YS?hs5@&!AKdGhMc80ZWEK#Q}vp z3aQo6_k~*TDry=A^4CA|GjmYjM?HawVGg7cw8~heBA@9eaV^g97>wqPj|!*|YNUtK ztG*ac0qn~V5X^l+pc|1XK zpscL@Xsvq}#J!%p78=(Z)e7`Q3Oj?n?T0 zB>Xgl@iQm=xPFEX2ukp2OcW1duzk-)vk*YX0H&ALelav;2)cjNm=8v=a8(EG zp-7+#bEppFPGC~Ls_4x{!MqRKtpWD!f3M`W3?w@y7_ zJj68z{vjU8-55HcAG#pyA#Ys(JCTB+E4F|MvFdHJX$6^U-J+WMmP(;Hfu-p)y_0F- zWyGj&GG+b`+UJ;=7l^$8vz{6X13zR@c8#~94;qDDTPZsLia}gq>4a#V30?|=ES;+A z5N-1A<=@ajgv~+Rn>q_00hQ}3Jcxu;8mS`V8XDqLyFn@Z{iczkZxke0)%g?pvu06k zB=y(L6$pAG{gU9q!JyWO)wr@$xif9y#W`8_jZxYc?y(g^X&wI;lGWHd^Q?63mtC#w z2z`S%7B0}t>wHX_+7Zn-K;2-5@vb}o3;8`Pm$J)ABer-H_39f7?%`qz2UB($p+yPZ zQfdepQ=S#tBLSoO?1c)S*I!E-3%1#augx*GgAap2h2DaRwg`wlFt-2~EEbTpEtD3> z0J=L(VC{`|ep#>_0j6D=DDv$4Mzaru3enWFr1 zi?+VEOH89697uu^`oJ$CO!2aPOQ-?vVM~U6!1(%Us|uxif*nE7Nbu7>s9=MAzA62P z^A4fBV}EwI_UgLkz$F&TqXVjFYgdq3eFEv$H){ajGWGt_;EX{(JcJoYeUvCCWO!`q zvp6~iqU?nVG=R8(kR(S9l^aO#0oIWtB26lI5cW5aav+o@PCI+SM4TEM8?`tXM5<|0 zn2he7{*pjqDjxHT_NkEwA^@RS1;SL4UkX4?yYb{;rjmkCA4md;NL+e6{#&DwY;KQ= z4LTwm{GCG6>Dr5q{4L!NH3(aJkAR3jMUf%3!&ZFnFcmYnevGHrg)jzw|-_A;XKfN->$#Gnl_}sU={#9OiR;8j4d0@d!cC)`U1`Krs*DIUUNZLKzo-UEHR@0h-!lsABy%yuu_bO0rziuaV8?@ z4Nrxi7$tR_CoaD@*qV?$;)xHHYhB@+^*8;i@#A#i5J! zYm6B&_9y8(Z8x%MGh^T+2nb$yYO3`6@Ih3i2QIlVzQdE$C~!vx#9(O_$a`~^pk}y?8Eg?9FcZSJ&y^}sw#szXn+W{Bm zt+qDaCfXx?5vSJF4+1?B8#yCQ#rPssHI6fa5CIYiZAiv@g_aIwg3NM!RrNq1txX9B z)wfmW%M{hQ+4c^Elm1Y-p>0wEfJ?soA@vR%Gd*i?ii3ZHjxwY-F)Ii+%uypABs9p! zX7xVW@&&)bF|wwSJ2zy99U{8ccY75%HobB+@<9&;1P20V*7N7Ui)FGTI7uWN%QPl+ z6FkH*0nqtfxceW}d$Pt6T{zJFr_8uKQM|aum(eaV!uWJbQhIk^yPnFV@~08#KPIwvS6ijR2iIFR*~+vKr$YCqX@}GelP($6NRh=yB2E zWGVEU?{gO zw-W;5l(_Iq`Y*s9_GKJ!J-J5~lp#MY4Cf$%fG)=QgF>>3iqkoghsGld-#mP$BJNz! zRs)TeNT`MGzz0F^*gps*P}n;UsTh<&y#EgoCSNI*&#g~v5PoR@tdyGctv&d7mn3$E z*Y7|!f#@8OZ8ibP`${?j;5=dCRck9-(T0_BXO6^l%3tV_K&8*>+y0IrMUcJ+!D^;@ z+1+CRUISn+c=jaZupF9<#iUjsx2kVc9Al|tj|j7If-YQm5tBZTtkNkxO+Ea5zA$IF zb>>1lCqo&qmlOufX)o5;CCjM4nHGm~O248)QW(wulG<(uzv~2_OZ_>19em&9*Dd`$ zd>Z_AkRpf&DG+rbl|5I#YfzC;Rgfh|Vxmiy>IhNT@dBoZHJ0E3cVgxhI+0{SbkU?Q z=(%8u3Hb8@)O!H=s^9V(oPe7XDUB_o#(yoyxdM6XQ6(GebYK!R?RmQ@Yc-aMFzyWf z%UdMDB3^qlbdBV#IkP&GdiHMjNKDBdjKp&wn-n8Gh@NUU&8S%+AaAEdQCCPPLlU-< zp?ro`x#hah(?;NClxx+vH2!R9jE$6b2}n5FlZ*gCB)w}1ZD1Qz=mn8!34tiU1s#`E zH76*Ua7A>@t1?^-xcXu+@Bc~lqHi#gQ6Dko45-{M&rf1Fuj0CsU2| z3N^bi(167Nh#l|ij~-e)r7x+MOI+OsP)A>7_Kgy(C0|IjsECuLGPQhJ%cFw1z%FPh z<8-3l;7&2_E;R2uq8-4#f`lMeqw!@)1#!km(A4Jasf;Oo)5X2->vO{$#GsD5Hs^(Q z8hgRQu8q}$gy5zC(&(npQ8<^=vcEBq7i#Hf#miHFDlx|*Yg#M5BEoS7?{l>3#CfsTSu~y8PKo+oM%e< zg=!^_#6GslfTZzTK{?F2`mm+Mm44K?x_!~7fW(l`3cIeKpS9FI_HZKYI_|H+#YmY@xcB7>hotKGhN zC!U%ZEcNWZzJf`X+@(L*Ej*M9I@d}l(ASiN$H5UG8?Q5ZrD)K=<6DhUF&#S;v%(T- zNTQpSn|R0c=t6^%=h1`yrjVVI8{(*iU6IaSHnq!N*wN&xKm!A}iyWD7!bIs1=sne;V; zu-QUq%62-bQ%tE7iHie0Kc$fd(b*xw)4v~Y6f&_(SgfzJsv$&4KvMLGkf{rrh)nx| zOiAlg38X~D1b({fVWrkc3T&(K%+6|8Vpb*=$~i)921A*rsIq0~&HWm8N;DG;sgx95AA zp#wbM!L&aq3|vvLbAPYSVo5LwNZ^_+Tsoj=7<+aT-yi4!avX40JGX-B5QbIHq;Em%b#1dfG9=#82|3>fPCDq?U-EO%5YAg9!aa9pbRVM^qCfVs7W02grEp=&b*Yi!WuU7QS*CVf zHMcDp8~p==27;t$Lb%}c)Jm+xqnX0Mvf!c#^iMGC1tceqHO}=b5is;gkG@FsjBEc% zDo2p(@6-657c{IkR-gW=Ymp*)w7@0zvy_%9L*A@SQ_@e6EqVs>GOd?oFZ^Nvi%?NM z%h(M!(-?~bII1q1jZ0-B_vHPV4I9s(bSfqc+)(jbLgNsL=PQb~k{Q)i#4hQ_d|2iX z1z|MlmMvCk614cZhw{q3bcD>_xdd{IWNKo!-oHrS576xS9w06@7i;2fV~PYiW2x$q z@V%9(REi#r;lY;d=oAU$YlY;yry656)K;M^L@SEr?6ROi$cKtRUaR^BKSWH+1rTgv zDLN$1TKr0n7Ov6kUln8p7JWboNGT>N&_)Mn^*`ZIUiJhmd-77tmjk8 zc2W2{BAOI3h$LdB%e6w8KAlVRko69zZ;iAzX$Bek0zzhX9h)S-g{HlRIF3t#t3_T= zk&ECA9IjBp`5p@PJ`E1BnE>-d$XH|i9HIKq^+~G&_8xfR$5))dAU=dz^srSE~fl>Y&XEEaXj>rTB*luc;ia)yR7D=R?82szo-Ou`-FUYj&&;mbD4LSjeNsLhaQ2wN*;u5WPKZ9|h>db0X9 z4=W*mnrC5AKv_b$NntfMJ0^woIF(m5vi~ckB^#g4gu$2ZdI&TEft=LFD&1d>c5XsQY3*}Fbt~5On&{(6JWyf17Yi?h8b;xR8LeTNn>`Vy8fQwKD zMS7!7`~7nWrP~1G$Z<@PR*nq`z(A29H*u%pm*3W<`IyH$nd!z{oOuo;7E$KhA}Y9C zaP%CbG_dTsL&`iSAUBf^p8v9IiqbSHofEVGn31+bkr9Y*h|Q1hPXHlxK;&3P!Rvvp zWvsw<_(qV`=-%TmgJ4K3#w4yh9UdaSnz-=NZdg9kQMIFkB1BVg{JdLu%{>4e6lWN1ta1OfgYN8)q%b_D*@a_ zwxA^cEDZmAePY#c?=zAwa1dcZA~)kCayEBs&3c1 z2{-o6I+xQg8xMX&a~`m>Rn0K95J^R;Hj)MQlFI3}dRK=V^7Q}W2(F^t;i>-wmlfeL z440&{a({&%^uly6fi7^tV2(Rs*wYwnodqf#XME`d@~k}U(f!1G#jVQq0cZ)t_olv^kES(ilL7YCJ7{83ue&<$PM*`&c;Ee@>f zL|(D2;CXsV92PXv5;0kIq&H@N@f59spgpjpv5UFY*1AYL*9g8J@>$hQO{Dh`#G2`n zjJ}l}Ryr&?-@Wzt$zr#Acnnzd1Z6=2T`T3+s4!L4_SkLC-jQ??s!yZ`kE5wFPU`w$ zLOh@O0OqMT_p`;*(%yvoPBX{!(WVG*RHUjj1?^G#b?kK=aUZFQGb#L{&Jk}a(q`@Z zv>|@aw(mh5TaCEY?Qb7d5{zzR!#|wZw)J4UBcg}(G=U&Whx6+0LJQTJS|GX5Fmaeu zagBMxq5%RiFVT4T{LGM)$E!e(eSyu6#e_$CjKy+{&Kr`bZ(~l?6D4j|9^|Y8!s@c9 zulDkixvylBj91Okc|6d}NpS>Iki0paieYew>0Uw08#^Q>jyZd}$WmnCF;W^UFL)N++`cssT%9EeZ9Hu8h$3ljVmj z{gUWEracVSwcE+Bacb-!dUPpEhjO<&E%>|7pL|eG*z%q$9Y4JJ>q4~RDo)!S6@cGy znlW`f-w$t+9^6XyM9|*PE#KS9jUo?d@x(Z*8e?rsQ;}kHoLG17oi>k9uFt32L6Zj) zJZ4+zF_+a3b@v~`Y#g4z`EQX0tnj8+w}Yxbp(wn~k@b>?aE$WJTKX&pKE3wo5lg9c zea+d{MU1Fz*R}}9W05|;Y1d}-qqXJ>Gh1Gy=->4=YVdzt6l8fEtv9;GputYmToZcF z3M|MswZhw4%ux&D@|wu(S__b$&gYKMQUX?OEAyjUMCU!)+>Z zaQq!LuMUronp6Te4apeu9?LZANm9pbta2$xLgO7nvNr5u!_C^iWL#lndv>AKOn2}N z$c=!h{9cLVzbX9`9Tq}O(#Tji#!Oh^H>2f^!PrT3^su|}wtg<2tH|qkfXh*Zo@D8z za1Kjho0DF?cv2QPs9JKXTQGM97SnGxrwess=}^(&I_+YjUXVt#YSC%QcLc1jDbRh% zYhE4O`bwi=?|R6%R#E3@NJl6>YN8Q+E(AAtt%6|GszCO2Y8bt8Gg&TUJH)bzt39uX z2EeWVx7lSLW@T?p;3(3AJP`Dxb@-;V!-DNeq`|%y~ z@_nWr{O(RGL%yjKdg9!~j=*f)Z^f!vh*mBG&Oo63t69@NxgOuTc>{%umJH2($k?{O zrCuP?{8;;}XIln&O+$K=;Hj&B)$j)6MpH<#!$Mz*Qah1$6@%)vlZHEsBRQ2a=)~&I zojIqx6G^GLzrZM2D=?9vOHR=LRcFjnAi=3o;v>=2wAabvA3vD^Timks*SHII7zBylUR=|a&_$sJbj+F4_ z*gpiDTjeTb(z&yKr2_V}5u;ZjZd`XOW>mB*?BuBID1i-cpbb57o=APltC9vnYnm%; zSyU)gvMg58rh6?Eo{7V&ZMrZK!hja)^=LK9oX)N$k3&>XC<|lduu4--x505UsK$=h z8%3A28!Jx#ReoTz=0Z?I!-4;XPv8=9rT*rXVZ-qT)_DrpG7y~0^6KShl zDvaEVX=QKYjd&30>`sq+-BGCK61*c;CtO35N=ypoOHSsdz3CH0jDCs1<}bl^@;z_a zUfi~~WjNp3)4Dm0|J3?(G4hdBW|tBK+>(K@W~m~6ZmZYhTumW`&h%G%7B=IAc32%l zTYoIhXVj{))y!=EHMtjaK{S5smDy?QR+~?5<5p4G^lo|*71i`ieh+5o_`O1i9X`1H zICx>cs&2ljmQsXc75?J=?Q2r5>ul2zg61Z-y6WYiSjnLI0deeNZf9$fdZ)?CsS&U( zwncQLMp_OU>_HEi-6FVEfmYb(>$uu^xyr^T+Zw)ZoFXG(q(8xV@WY(EbH!~iu3an0io>o4aSO@u=+*I(q6J85v?KNAN-lp1|BHB5<3gBLY7 z5gqiOJ##u2r>)Q53!<$pkP$uCy&nX(;^#PyV?-+o*wAlu&a9eXnukwIwpqvPx(Hli{!4NAbvM~sQAnB- z1<$^s+6LacGuE}e&QVgrER{GT{O3g0q))`9*)HZ8wz#VGG zJi?cqFm3vkP^STZEUF}jum#9gtu33fin~E8iW!T;> z2NAY-=%_w{B05GAJL0tPF(BvB%14#*aemHm@TqZ8u(>|KPHa~&U$Mu{f@hxf6@mobo<*dzpf>z#=OBU9gmeUQa~~NPPSU*=Mg96+5hrdGR8BLFaL#M@zm9mHqQ#Zk%iGm1r1ikUwk4TF2MkJF0aX z@lg+N;f#QJc#0k6y=le7hbz$e^>WImvh$&VUy*aI=lwDexYb6vlaySbfS)_Nc$3jp zRo$9pHi0PRa!S&X;O&%bCZgG3++Lc74R*W)2q_OMY9%l-(jjk$6w&z?yu)!7;D)}^(|!%B>R zEmZbsEMeWt<@u)X0}me*PL5*e#6i8GR9SD1>#Dim?CTIpq^7%cmII2_=`6N;2U}FA z1L7|PlZ7X@Mk;F~ui;-jo&kAsdVvGN%~ezM59Z!_!k#!)AtvSHzc`-)f$kFq9?%^j z3*=;`IEhPMRu#z9c)StLfg*0@X|aNG*M*;FA?(8f&q{NtxPP`r_%r_smVeNTtd z({0?YyV1v8T*`ao&6C68vF)r@W5RK7eTyD{{lIL*Xi}|MKO!ER)frrJdzT3q|2nQ8 z3EEFfBl$XnKa+A6u;`&(kvJfoGgi=hw+8Zb#G^XqPzevw@bi+9n!D~NBSx|aG}vL) z`{3`rlsPu*#TV^8?Ps^@kTz{s{c7;G#AzWzE4ra(5`oH0K=rJcl`9s(mgVQpv+w^l zu!X003Xgj}RoTjH{!m@SPZMCHmfX3xT%|_2S-`dqSG8nhxfY5 zs--TnE8O-84QuPohBvF~wwb7EvY7yHiwprePIT32b7Ha@=ny8j@5drfE9tG*!oZ)w7eDE@eb|r!|R3Gil`( zF-1ggxAx+>F|Sw(<{E~;`4urLAAy^ti>3?wZQ3=OLP{E6c^CZ!@4zl5nB6|_CQX}J zn@2f+tkA_(FPNJjOf-TE?vW3zO~QWFp(M;pqrP^zPVA4GtlPAghK$W}RIe|?8uaYK z+Si+1^s0x>a=?i0RuU%Jz1^r%rlYlHQ?~=aiI!n5=a`65}H3Mt2v8^~Ab5Xju5$l$&ylN-NDeIqGdQ#9z6*fuq zkU6$_ha(L;{Q#rB%bc$uE^nM7Ui{oMz~cAK3c|{u^Vl5yV&ZDs4>qQQlj?@?_fyiM zi}$Hii{#VI<#ou%v4^NMZ~3!`&6Na}f?T`eI-Ngju6E}k^>vbB5Jpxe?l_mP`ft-U zPh5e+RQ%q!YUO{5*u9q?tDrl;HT!&ix5cLvBo6z&YSUD4gQ2S0QBu>|7e?a7OOc8ic_EukjmaW&$?1$ z6xST*aOxxIbTj=^75HoQJdUD&xd;=fQ^3UnKZX^%%j{t~ZjB61&cpVQHV_2(WAMl1 z@i4;SS6tg@jNLXDs;;329_Byp5~m4B7dcjT{i`IVDZ06=AEsyG_B;4Ffi+B6WLxbA zs(yD%y-%X!73A<<)C7d*?hlrAi=alWex1DA7x7o@ZS#erGG(e4lP|R?jSIy|s74c+hMP!s%u# z*@O*gF5ia!Y{ic9*n7Ybx%vLcGqAyLlOp$r528sXH2jUElJ}1t_nx#5)48^V&U$0R zW;Y|vxXXi+ZD7L+R9*d_{OebeJrR2A;+KZzTicH+?VR3@f-ihx-ZKT)zZNteX1_-j z<2yaKw(893XQ}o(+j*EK|G^ob)vB?QCe<-`VY%h~xf#RbH2Z>A2-mzgb~B{kYFjs{ zIe+a;#$)P{kaN*LRn};wmPeGsZ;m0->aRK&5c1>D+e&pqj^)t%RLe53v7X68?Ea@? z_f6kL1gqQ713j1#pX*Pm5_Xo%-xr;O)B8=bNt4Vht`D=%F|zVib%|>JGiRktocI;c zKff^F=;Ny;GrByCPqh3lSR1L)Lawms7T;xR5F6f)^IorTXXZ{kk#@F!`+44drBhPIIAi_mQqw%RoWU7u78S#{+p@0=%VzRTnl?g)&*UkP z^vtaf5CppkuG!Cmwvn*NB3rnP;`?CZ@w7k2qfk|=8zA=$OAn|a(GdeWjhL%s{@O*&(^IbjK0e62b{*ux41f3b?;Aor0QIz@=V>LHyPY= zll~AXB66=Jj-<8iRwaKu>hM9ecOpQWjghf3l-=aA^FZ|}Fn1V-tCFUU(yF~N=FrZv zJN?Q+Pa!55fUl7}``c8j@Md6?zuN0)Xn@D`@wss{gfLz<`ukmev@*o$j*NcrNwM0u&I(Y|LDml&#m{_2b;;c;qmz&eb%+FpXr& zPEX8)H$TCd;2>$*486cKcCv}%)#=wA65WN#AQi&iq_frVfOVf0S(y%|Z-<9O9g-y` z2%JhjBKY}mbAy5?X_z+*G&F1 zPkMt~awy*v*&HAMKnxEMfCl?pK7AeFUnTJKV@Ncspy6^=!#0&#`^G23^0%soHP&aR z=XOn)GhOs&U5Upv=7Zh`35l$)pUoNI4I6XJM0vBlFDLF)4>1$Exqn{NuN$}~?yDY2 zMd@>t-|)VsFI|dWmO;$Uu6*@C)}7bS5;Nc^x+l*2jtRzsNkaRL7xL91|K|H6D5;Ef zz%OS{A=CS&L-U-2u<5=tt{4Ukv*^p!{Udxrrl&ti5lgd&L=~w>fGf!(RLFl>HQ>|z z{Vjr60KjMYbTfa;e;ED$uIgW{{}-+Pqw3$)|Mw36Q`Nt|^MBw_Qe^=D6Nml3Ug!Vw z7W4nRo9Dl275;5j|Alq`pSSA&Pd?~Bxs3llZ(@r2zx9v*{|x>YEB0Sh{oA_#hx-5j zCKLYG?)p!=|KAh#Z|nYlzX7kPj6Y8^Dp&Ab4B?J0v3 z@3?OFn^X5)b52aA(@Vi`&&PxukH?6d_o*14+t-};_gyv=K#z*|d3X19+>iG&OrIN; z?weD+r<+a2?2y_7#`neHKU+#U?w4lZOaR|gi2p0X06qV(FMai$zxdQoeeGAbzdY*` zcK63W{QOV9`w##0gMV`O2HOk(;CT4D%T#ySstjOv&RW8@e*brV_J@D`lVAD8AN|C8 zpZ=cj_{I+p$?_zxBI+`d>5e`+orj Y0B*3QbIN+QT>t<807*qoM6N<$f*x&?!2kdN literal 0 HcmV?d00001 diff --git a/ruoyi-segchk-web/src/main/resources/test.http b/ruoyi-segchk-web/src/main/resources/test.http new file mode 100644 index 0000000..d506744 --- /dev/null +++ b/ruoyi-segchk-web/src/main/resources/test.http @@ -0,0 +1,998 @@ +PUT http://{{hostbak}}/system/user/resetadminself +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +### +POST http://{{host}}/default/index/customService?providerId=2 +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +### +GET http://{{host}}/default/html/vipServiceAgreement +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +### +GET http://{{host}}/default/html/userPrivacyAgreement +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +### +GET http://{{host}}/default/html/registerProtocol +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +### +POST {{host}}/default/index/shareInfo +Accept: */* +Cache-Control: no-ca +Content-Type: application/x-www-form-urlencoded + +page=sss/sddd&remark=999999 + +### +POST {{host}}/qRCode +Accept: */* +Cache-Control: no-cache +Content-Type: application/x-www-form-urlencoded + +savePath=C:\Users\Administrator\Pictures\test\test.jpg + +### +### 测试图片上传 +POST {{host}}//default/common/upload +Accept: */* +Cache-Control: no-cache +Content-Type: multipart/form-data; charset=UTF-8; boundary=WebAppBoundary + +--WebAppBoundary +Content-Disposition: form-data; name="file"; filename="checkqr.jpg" + +< C:\Users\Public\Desktop/checkqr.jpg +--WebAppBoundary-- + +### +POST {{host}}/default/user/userLikeGoQr +Accept: */* +Cache-Control: no-cache +Content-Type: application/x-www-form-urlencoded + +likegoId=4&remark=999999&qrw=300&qrh=500 + +### +POST http://api.ksd106.com:8088/SMSSend.aspx +Content-Type: application/x-www-form-urlencoded + +Account=KSD8141161&Password=123456a&Mobile=18515184399&Content=测试验证码短信【河北赛格】&Extnum=&Time=* + +### +POST https://segchksaas.xyz//querybaseinfoset +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{} + +### +GET https://api.weixin.qq.com/sns/jscode2session?appid=wx2ce4e2083b3a871a&secret=adc865e9ab24ab23b534f9ca5c0960b3&js_code=053okall2BHyK74GMcol2S8Exc0okaln&grant_type=authorization_code +Accept: */* + +### +GET {{host}}//createqrcode?url="http://yxr8cu.natappfree.cc//tokentest?dfasdf=1+werwer=1231"&w=300&h=300 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + + +### +############### 商家接口测试 #################### + +### 商家核消操作 +POST {{host}}//default/store/giveFreeCard +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 243, + "cardId": 242, + "lableId": 10, + "storeId": 144, + "typeId": 2, + "totalCount": 10, + "freeContent": "demoData", + "remark": "demoData" +} + +### 商家核消操作 +POST {{host}}//default/store/ServiceCheckTest?likegoId=16877&storeId=128&remark=999999 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + + +### 根据用户id,运营商id,查询seg商户提现列表 +POST {{host}}//default/store/storeCashList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 84, + "phoneNo": "demoData", + "providerId": 3, + "remark": "999999" +} + +### +POST {{host}}/default/store/storeUserLikeGoList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "providerId": 4, + "storeId": 123, + "staticMonth": "180", + "remark": "999999" +} + +### +POST {{host}}//default/store/storeServiceAndSaleDetails +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "providerId": 4, + "storeId": 123, + "staticMonth": "2021-06-01", + "srcFlag": 0, + "remark": "999999" +} + +### 根据商家id,运营商id,角色等级,返回核消统计或售卡统计 +POST {{host}}//default/store/storeServiceAndSaleList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "providerId": 4, + "storeId": 123, + "staticMonth": "6", + "srcFlag": 0, + "remark": "999999" +} +############### END #################### + + + +############### 用户接口测试 #################### +### +POST {{host}}//default/user/userCashReq +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken1}} + +{ + "userId": 503, + "cash": 5, + "providerId": 2, + "userLevel": 2, + "remark": "999999" +} + +### +POST {{host}}//default/user/userChargeResult?chargeId=45459&ret=0 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken1}} + + +### 用户充值操作 +#返回结果 +#{ +# "msg": "充值成功", +# "code": 200, +# "data": { +# "flag": 1, +# "data": { +# "return_code": "SUCCESS", +# "return_msg": "OK", +# "appid": "wx2ce4e2083b3a871a", +# "mch_id": "1614166120", +# "nonce_str": "wknhqpLNvr4F6CLI", +# "sign": "2519A7C975E5F38B95D0EE453C1A11D2", +# "result_code": "SUCCESS", +# "err_code": null, +# "err_code_des": null, +# "trade_type": "JSAPI", +# "prepay_id": "wx201612191353691146536bf76294620000", +# "code_url": null, +# "mweb_url": null, +# "time_stamp": "1632125538", +# "package_": "prepay_id=wx201612191353691146536bf76294620000", +# "sign_type": "MD5", +# "pay_sign": "087F0D138F3970B5228A3456E1A5496E" +# } +# } +#} +POST {{host}}//default/user/userChargeReq +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken1}} + +{ + "userId": 503, + "charge": 9.9, + "cardTypeId": 0, + "providerId": 2, + "remark": 999 +} + + +### 用户充值请求 +POST {{host}}//default/user/userChargePre +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken1}} + +{ + "userId": 465, + "providerId": 4, + "userLevel": 2 +} + +### 查询seg用户消息列表 +POST {{host}}//default/user/userMsgList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 392, + "providerId": 4, + "userLevel": 2, + "remark": "999999", + "phoneNo": 1 +} + +### 查询seg用户提现列表 +POST {{host}}//default/user/userCashList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 34, + "providerId": 2, + "remark": "999999" +} + +### 查询seg用户充值列表 +POST {{host}}//default/user/userChargeList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 34, + "providerId": 2, + "remark": "999999" +} + +### seg服务评价提交 +POST {{host}}//default/user/addComment +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "starLevel": 4.5, + "contentText": "测试评价9343", + "chkServiceId": 9343 +} + +### seg服务评价查询 +POST {{host}}//default/user/getComment +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "commentId": 3 +} + +### 删除seg用户想去记录 +POST {{host}}//default/user/removeOrderUserLikego +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 245, + "ids": "16733" +} + +### 查询seg用户收藏列表 +POST {{host}}//default/user/userLikeGOList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 245, + "providerId": 4, + "remark": "999999" +} + +### 查询seg用户收藏列表 "remark": "999999"测试标识 +#{ +# "total": 48,//用户收藏列表数量 +# "rows": [ +# { +# "collectId": 2002,//收藏id +# "providerId": 4,//运营商id +# "storeId": 134,//商家id,跳转商家详情使用 +# "storeName": "4商家名称018",//商家名称,展示使用 +# "storeIcon": "http://10.1.192.113:60902/profile/upload/2021/07/02/706f0a58-6031-4523-abbd-dc5dd823278c.jpg",//图标,展示使用 +# "serviceState": 0,//在线送达 +# "storeLon": 116.4980500000,//商家位置,导航时使用 +# "storeLat": 39.8831020000,//商家位置,导航时使用 +# "chkCount": 280,//核消数量 +# "starAvg": 2.71,//综合评价,展示使用 +# "modTime": "2021-07-16",//收藏时间,展示使用 +# "segchkRecommenderStoreLableWebList": [//商家标签列表 +# { +# "lableId": 0,//标签id +# "lableTypeId": 0,//一级标签id +# "lableName": "99",//标签名称,展示使用 +# }, +# { +# "lableId": 0, +# "lableTypeId": 1, +# "lableName": "美食", +# }, +# ... +# ] +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/user/userCollectList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 439, + "providerId": 4, + "remark": "999999" +} + +### +### 查询seg用户可用会员卡列表或者优惠券列表 "userLevel": 0(查会员卡),1(查优惠券),"remark": "999999"测试标识 +#结果说明 +#{ +# "total": 3,//优惠券数量 +# "rows": [ +# { +# "cardName": "赠卡",//优惠券名称,展示使用 +# "storeName": "4商家名称028",//归属商家名称,展示使用 +# "leftCount": 49,//剩余次数,展示使用 +# "effectiveTime": "2021-07-13",//有效期,展示使用 +# "typeFlag": 1,// +# "cardStatus": "过期"//状态 +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +# +#{ +# "total": 1,//卡包数量 +# "rows": [ +# { +# "cardName": "299",//会员卡名称,展示使用 +# "storeName": null,//商家名称,展示使用,查询优惠券时有效 +# "useCount": 31,//已使用权益次数,展示使用 +# "leftCount": 69,//剩余权益次数,展示使用 +# "effectiveTime": "2021-09-15",//有效期,展示使用 +# "typeFlag": 0,//卡券标识,0会员卡,1券(或赠卡) +# "cardStatus": "可用"//会员卡状态。是否可用,展示使用 +# } +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/user/userCardList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 241, + "providerId": 4, + "userLevel": 0, + "remark": "999999" +} + +### +### 查询seg用户核消列表 +#结果说明 +#{ +# "total": 38,//用户核消列表数量 +# "rows": [//用户核消列表 +# { +# "providerId": 4,//运营商id +# "cardId": 244,//卡号或券号 +# "storeId": 119,//商家id +# "cardTypeId": 0,// +# "userId": 245,//用户id +# "modTime": "2021-07-12",//核消时间,展示使用 +# "chkServiceId": 11168,//核消id +# "commentId": 0,//评价id,0表示未评价,其他表示已评,展示使用 +# "cardTypeName": "99",//卡券名称,展示使用 +# "storeName": "4商家名称003",//商家名称,展示使用 +# "chkSource": 0// +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/user/storeServiceCheckList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 245, + "providerId": 4, + "remark": "999999" +} + +### +### 添加seg用户想去记录 +POST {{host}}//default/user/addOrderUserLikego +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "providerId": 4, + "userId": 245, + "storeId": 128, + "cardId": 244, + "cardType": 0, + "remark": "999999" +} + +### +### 查询该用户在该商户可使用的会员卡或优惠券,remark为测试标识 +#返回结果 +#{ +# "total": 3,//可用卡券列表数量 +# "rows": [//可用卡券列表 +# { +# "providerId": 4,//运营商id +# "storeId": 128,//商家id +# "userId": 245,//用户id +# "cardId": 244,//卡号或券号 +# "lableId": 0,//子标签id +# "typeId": 0,//一级标签id +# "cardName": "99会员卡"//预约下拉中展示使用 +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +### 查询该用户在该商户可使用的会员卡或优惠券,remark为测试标识 +POST {{host}}//default/user/userOrderPredList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "providerId": 11, + "storeId": 196, + "userId": 768, + "remark": "999999" +} + +### + +### 根据收藏id,删除收藏列表 ids:要删除的收藏列表id,删除多个时,使用逗号拼接 +POST {{host}}//default/user/removeUserCollect +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 0, + "ids": "23432,456" +} + +### +### seg用户收藏记录 +POST {{host}}//default/user/addUserCollect +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "collectType": "1", + "providerId": 2, + "userId": 8, + "storeId": 13, + "mgtState": 0, + "remark": "999999" +} + +############### END #################### + + + +############### 运营商接口测试 #################### + +### 根据运营商id,返回运营商下核消统计或售卡统计详情 +#无token时返回 +#{ +# "total": 0, +# "rows": null, +# "code": 300, +# "msg": "请先登录注册" +#} +#token用户信息不一致返回 +#{ +# "total": 0, +# "rows": null, +# "code": 301, +# "msg": "用户信息异常" +#} +#{ +# "total": 106,//该月份的统计 +# "rows": [ +# { +# "cardName": "99",//卡券名称,展示使用 +# "storeName": "2商家名称001",//商家名称,展示使用 +# "staticCount": 24//统计值 +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/provider/providerServiceAndSaleDetails +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{providertoken}} + +{ + "providerId": 2, + "staticMonth": "2021-06-01", + "srcFlag": 0 +} + +### +### 根据运营商id,返回运营商下所有核消统计或售卡统计 +#返回结果说明 +#{//无token时 +# "total": 0, +# "rows": null, +# "code": 300, +# "msg": "请先登录注册" +#} +#{//token与用户标识不一致时 +# "total": 0, +# "rows": null, +# "code": 301, +# "msg": "用户信息异常" +#} +#查询成功 +#{ +# "total": 7,//统计月数 +# "rows": [ +# { +# "staticMonth": "202107",//具体月份,展示使用 +# "queryMon": "2021-07-01",//具体月份,详情查询时使用 +# "staticCount": 1062//统计值,展示使用 +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/provider/providerServiceAndSaleList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{providertoken}} + +{ + "providerId": 3, + "staticMonth": "10", + "srcFlag": 1 +} + +### +GET {{host}}/register +Accept: application/json +Content-Type: application/json + +{ + "mobile": "13000000001", + "code": "1234", + "providerId": "2" +} + +### 无token登录 Authorization: Bearer {{providertoken}}使用token登录 +POST {{host}}/login +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{providertoken}} + +{ + "userId": 9, + "providerId": 2, + "userLevel": 1, + "cardID": "11111", + "remark": "999999" +} + +### 商家评价列表 +#返回结果说明 +#"{ +# ""total"": 151,//该商家的评价列表 +# ""rows"": [ +# { +# ""storeId"": 130,//商家id +# ""starLevel"": 4,//星级评价,展示使用 +# ""contentText"": ""content004542"",//评价内容 +# ""modTime"": ""2021-07-05"",//评价时间,展示使用 +# ""cardName"": ""299"",//卡券名称,展示使用 +# ""userName"": ""nick_name40221""//用户名称,展示使用 +# }, +# ... +# ], +# ""code"": 200, +# ""msg"": ""查询成功"" +#}" +POST {{host}}//default/index/storeCommentList +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 4, + "storeId": 130 +} + + + +############### END #################### + + +############### 小程序展示接口测试 #################### + + +### +### 根据运营商,商户id,查询商户详情 增加后拼接参数意味着是二维码分享?recommenderId=124&recommenderLevel=1 +#返回结果说明 +#{ +# "msg": "获取成功",// +# "recommenderId": "124",//推荐人id,只在在url后面带有该参数时才会返回该值 +# "code": 200, +# "data": { +# "providerId": 4,//运营商id +# "storeId": 124,//商家id +# "storeName": "4商家名称008",//商家名称,展示使用 +# "storePhone": "13000004008",//商家电话,展示联系时使用 +# "serviceState": "0",//商家在线状态 +# "salerId": 1,//对应销售id +# "storeAddr": "4商家名称008商家地址'",//商家地址,展示导航时使用 +# "storeLon": 116.6160200000,//商家位置,导航时使用 +# "storeLat": 39.8341900000,//商家位置,导航时使用 +# "onService": "2商家名称001商家地址",//商家营业信息,展示使用 +# "detail": "

    详情1

    dsfasdfsadfasdf

    fsadfsadfdsafsd

    adsfsadfsaf

    详情2

    sdafasdfsd



    ",//商家详情内容,展示使用 +# "storeCarousel1": "http://10.1.192.113:60902/profile/upload/2021/07/02/fefc46d3-dc55-4c45-af07-f21377386ba9.jpg",//商家轮播图,展示使用 +# "storeCarousel2": "http://10.1.192.113:60902/profile/upload/2021/07/02/ccc51e2e-036b-4d13-9028-adbe7bbfe176.jpg",//商家轮播图,展示使用 +# "storeCarousel3": "http://10.1.192.113:60902/profile/upload/2021/07/02/648f3997-bebf-4e27-8264-b6a2795c6b89.jpg",//商家轮播图,展示使用 +# "storeCarousel4": "http://10.1.192.113:60902/profile/upload/2021/07/02/61127f59-dd36-43ff-827b-baae7a0ea883.jpg",//商家轮播图,展示使用 +# "storeCarousel5": "http://10.1.192.113:60902/profile/upload/2021/07/02/cea01831-ab52-46ec-b8ce-dc9d64bdec6c.jpg",//商家轮播图,展示使用 +# "storeCarousel6": "http://10.1.192.113:60902/profile/upload/2021/07/02/09216bac-25fa-4112-a122-ccf140158b2d.jpg",//商家轮播图,展示使用 +# "chkCount": 262,//商家核消记录数 +# "starAvg": 2.90,//商家综合评价,展示使用 +# "segchkRecommenderStoreLableWebList": [//商家标签 +# { +# "lableSortId": 2,//标签id +# "lableTypeId": 2,//一级标签id +# "lableName": "团购",//标签名称,展示使用 +# }, +# ... +# ] +# }, +# "recommenderLevel": "1"//推荐人角色,只在在url后面带有该参数时才会返回该值 +#} +POST {{host}}//default/index/storeDetails?recommenderId=124&recommenderLevel=1 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 4, + "storeId": 124 +} + +### +### 根据运营商id,返回轮播图列表 +#返回结果 +#{ +# "total": 6,//该运营商轮播图数量 +# "rows": [ +# { +# "providerId": 2,//运营商id,跳转商家详情使用 +# "storeId": 3,//商家id,跳转商家详情使用 +# "storeCarousel": "http://10.1.192.113:60902/profile/upload/2021/07/05/606861e9-02d2-4c66-8e44-31a20ba4112d.jpg",//商家首页轮播图,展示使用 +# "sortId": 0,//轮播图顺序 +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/index/getBannersByProvider +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 3 +} + +### +### 根据标签id,会员卡类型id,搜索商户列表 +# +# + +#{ +# "providerId": 2, +# "sortType": 1, +# "lableId": 2, +# "typeId": 2, +# "cardId": 1, +# "userLon": 116.25849, +# "userLat": 39.684333 +#} +POST {{host}}//default/index/listByProviderwithLable +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 2, + "sortType": 1, + "userLon": 116.25849, + "userLat": 39.684333 +} + +### +### 根据运营商id查询seg首页推荐商户列表 +POST {{host}}//default/index/listByProvider +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 2, + "sortType": 3, + "userLon": 116.25849, + "userLat": 39.684333 +} + +### +### 搜索商户名称,根据名称,标签,充值卡等 +#请求参数 +#{ +# "providerId": 2, //*运营商id +# "sortType": 0, // 排序方式 0,默认排序,1热度,2评价,3距离 +# "storeName": "99", //*商家名称(即搜索内容) +# "lableName": "99", //*标签名称(即搜索内容) +# "userLon": 114.123456, //用户位置 +# "userLat": 43.123456 //用户位置 +#} +#返回结果 +#{ +# "total": 51,搜索的商家数量 +# "rows": [ +# { +# "providerId": 2,运营商id +# "storeId": 3,商家id,用于进行商家详情查询使用 +# "storeName": "2商家名称001", 商家名称,展示使用 +# "serviceState": "0",服务状态,在线 +# "storeSort": 3,商家展示顺序 +# "storeIcon": "http://10.1.192.113:60902/profile/upload/2021/07/02/706f0a58-6031-4523-abbd-dc5dd823278c.jpg", 商家小图片,列表模式时使用 +# "storeGificon": "http://10.1.192.113:60902/profile/upload/2021/07/02/e4c00b15-84f7-491d-bb34-bf5253f7f6b7.jpg", 商家大图片,大图模式时使用 +# "storeLon": 116.2667540000, 商家位置 +# "storeLat": 39.6789740000, +# "userDist": 0, 用户距离,展示使用 +# "chkCount": 89, 热度,展示使用 +# "starAvg": 3.16, 综合评价,展示使用 +# "salerId": 3, 销售id +# "lables": [ 商家支持的标签列表 +# { +# "lableId": 0, 标签id +# "lableTypeId": 2, 一级标签id +# "lableName": "团购", 标签名称,展示使用 +# }, +# ... +# ] +# }, +# ... +# ], +# "code": 200, +# "msg": "查询成功" +#} +POST {{host}}//default/index/StoreSearch +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + +{ + "providerId": 2, + "sortType": 0, + "lableId": 4, + "typeId": 1, + "storeName": "百元尊享", + "lableName": "百元尊享", + "userLon": 114.123456, + "userLat": 43.123456 +} + +###查询seg标签列表 +###返回值说明 +#"{ +# ""total"": 7,首页标签区域运营商的标签列表,超过8个时最后一个标签为更多 +# ""rows"": [ +# { +# ""lableId"": 0, 子标签id,查询使用 +# ""lableSortId"": 0, 标签显示顺序,一级标签下的显示顺序 +# ""lableTypeId"": 0, 一级标签id,查询使用 +# ""lableName"": ""9块9"", 标签名称,展示使用 +# ""lablePic"": ""http://10.1.192.113:60902/profile/upload/2021/07/05/4f8fb474-97d9-4547-afca-47a2ca1d5180.jpg"" 标签图标,展示使用 +# }, +# ... +# ], +# ""code"": 200, +# ""msg"": ""查询成功"" +#}" +GET {{host}}//default/index/lableListByProvider?providerId=2 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + + +### +### 根据用户当前所在地市行政id,返回运营商id 尹志颖 +### 返回值说明 { +# "code": 200, +# data": { +# "provFlag": 1, 0说明用户所选或所在的地区已开放服务,1说明用户所在或所选地区未开放服务,提供的运营商为默认运营商 +# "providerId": 3 +# } +#} +GET {{host}}//default/index/getProviderByadcode?adcode=150100 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + + + +### +### 测试微信账号绑定 +GET {{host}}//bindaccount +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{token1}} + +{ + "userId": "503", + "providerId": "2", + "userLevel": "2", + "code": "0312qnFa1cUYQB0X05Ja151Isp12qnFw" +} + +### 测试token取值 +GET {{host}}/tokentest +Accept: application/json +Content-Type: application/json + +{{bindtoken1}} + +### 用户利用token进行登录 +POST {{host}}/login +Accept: */* +Cache-Control: no-cache +Content-Type: application/json +Authorization: Bearer {{bindtoken}} + +{ + "userId": 3, + "providerId": 2, + "userLevel": 2, + "cardID": "11111" +} + +### 已有用户的登录注册标识 +GET {{host}}/register +Accept: application/json +Content-Type: application/json + +{ + "mobile": "13000020002", + "code": "1234", + "providerId": "2", + "remark": "999999" +} + +> {% client.global.set("token2", response.body.data.token); %} + +### 进行新用户注册 remark测试标识 +GET {{host}}/register +Accept: application/json +Content-Type: application/json + +{ + "mobile": "99999999999", + "code": "1234", + "recommendId": "5", + "recommendLevel": "1", + "providerId": "2", + "remark": "999999" +} + +> {% client.global.set("token1", response.body.data.token); %} + +### 发送短信验证码 +POST {{host}}/sendmobilecode?mobile=99999999999 +Accept: */* +Cache-Control: no-cache +Content-Type: application/json + diff --git a/ruoyi-segchk/pom.xml b/ruoyi-segchk/pom.xml new file mode 100644 index 0000000..eebdb48 --- /dev/null +++ b/ruoyi-segchk/pom.xml @@ -0,0 +1,151 @@ + + + + ruoyi + com.ruoyi + 3.6.0 + + + 4.0.0 + + ruoyi-segchk + + + 4.8.10.ALL + + + system系统模块 + + + + + + + + com.google.zxing + core + 3.4.0 + + + + com.alipay.sdk + alipay-sdk-java + ${alipay.version} + + + fastjson + com.alibaba + + + + + org.bouncycastle + bcprov-jdk16 + 1.46 + + + + dom4j + dom4j + 1.6.1 + + + + + com.github.qcloudsms + qcloudsms + 1.0.6 + + + com.aliyun + aliyun-java-sdk-core + 4.0.6 + + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + + com.qcloud + cos_api + 5.6.8 + + + + com.aliyun.oss + aliyun-sdk-oss + 2.5.0 + + + + + + com.weixin.pay + wxpay-sdk + 0.0.1 + + + org.apache.httpcomponents + httpclient + + + + + + + com.ruoyi + ruoyi-system + + + + io.swagger + swagger-models + 1.6.2 + + + + org.apache.httpcomponents + httpclient + 4.5.6 + + + + org.apache.httpcomponents + httpcore + 4.4.12 + + + + org.apache.httpcomponents + httpmime + 4.5.6 + + + + com.twelvemonkeys.imageio + imageio-jpeg + 3.0-rc5 + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMember.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMember.java new file mode 100644 index 0000000..ea6ef55 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMember.java @@ -0,0 +1,891 @@ +package com.ruoyi.member.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.util.ShareCodeUtils; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.Objects; + +/** + * 会员对象 ums_member + * + * @author 魔金商城 + * @date 2020-07-25 + */ +public class UmsMember extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 用户名 + */ + @Excel(name = "用户名") + private String username; + + /** + * 用户密码 + */ + @Excel(name = "用户密码") + private String password; + + /** + * 昵称 + */ + @Excel(name = "昵称") + private String nickname; + + /** + * 头像地址 + */ + @Excel(name = "头像地址") + private String image; + + /** + * 真实姓名 + */ + @Excel(name = "真实姓名") + private String relename; + + /** + * 身份证 + */ + @Excel(name = "身份证") + private String cardid; + + /** + * 性别 0 保密 1男 2女 默认0 + */ + @Excel(name = "性别 0 保密 1男 2女 默认0") + private String gender; + + /** + * 生日 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "生日", width = 30, dateFormat = "yyyy-MM-dd") + private Date birthday; + + /** + * 月收入 0 无收入 1 2000以下 2 2000-3999 3 4000-59994 6000-7999 5 8000以上 + */ + @Excel(name = "月收入 0 无收入 1 2000以下 2 2000-3999 3 4000-5999 4 6000-7999 5 8000以上") + private String monthlyIncome; + + /** + * 婚姻状况 0 保密 1未婚 2 已婚 默认0 保姆 + */ + @Excel(name = "婚姻状况 0 保密 1未婚 2 已婚 默认0 保姆") + private String marriageStatus; + + /** + * 手机号码 + */ + @Excel(name = "手机号码") + private String mobile; + + /** + * 邮箱地址 + */ + @Excel(name = "邮箱地址") + private String email; + + /** + * 更改中的邮箱(绑定新邮箱使用) + */ + @Excel(name = "更改中的邮箱", readConverterExp = "绑=定新邮箱使用") + private String modifiedEmail; + + /** + * 校验码(绑定新邮箱时使用) + */ + @Excel(name = "校验码", readConverterExp = "绑=定新邮箱时使用") + private String checkCode; + + /** + * 省 + */ + @Excel(name = "省") + private Long province; + + /** + * 市 + */ + @Excel(name = "市") + private Long city; + + /** + * 区 + */ + @Excel(name = "区") + private Long county; + + /** + * 详细地址 + */ + @Excel(name = "详细地址") + private String detailaddress; + + /** + * 兴趣爱好 + */ + @Excel(name = "兴趣爱好") + private String interest; + + /** + * 店铺id 平台的为0 默认为平台 + */ + @Excel(name = "店铺id 平台的为0 默认为平台") + private Long storeId; + + /** + * 1 普通用户 2 商家店铺用户 3 店铺员工 + */ + @Excel(name = "1 普通用户 2 商家店铺用户 3 店铺员工") + private String type; + + private String appletOpenId; + + private String appOpenId; + + private String h5OpenId; + /** + * 总的消费金额 + */ + @Excel(name = "总的消费金额") + private BigDecimal consumptionAmount; + + /** + * 预存款支付密码 + */ + @Excel(name = "预存款支付密码") + private String paypassword; + + /** + * 用户注册来源 1 pc 2app 3 手机h5 4 管理员后台新增 5applet + */ + @Excel(name = "用户注册来源 1 pc 2app 3 手机h5 4 管理员后台新增 ") + private String source; + + /** + * 用户状态 1 正常 2 冻结 3 未启用 默认1 + */ + @Excel(name = "用户状态 1 正常 2 冻结 3 未启用 默认1 ") + private String status; + + /** + * 会员签到次数 + */ + @Excel(name = "会员签到次数") + private int signNum; + + /** + * 手机是否验证 0 否 1 验证 默认0 + */ + @Excel(name = "手机是否验证 0 否 1 验证 默认0 ") + private String isMobileVerification; + + /** + * 邮箱是否验证 0 否 1 验证 默认0 + */ + @Excel(name = "邮箱是否验证 0 否 1 验证 默认0 ") + private String isEmailVerification; + + /** + * 错误登录的次数 + */ + @Excel(name = "错误登录的次数") + private int loginErrorCount; + + /** + * 删除标记 0 未删除 1删除 默认0 + */ + private int delFlag; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modifyTime; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "删除时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date delTime; + + /** + * 锁定时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "锁定时间", width = 30, dateFormat = "yyyy-MM-dd") + private LocalDateTime lockTime; + + /** + * 最近登陆时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "最近登陆时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date lastLoginTime; + + /** + * 推荐人的会员id 如果没有 则为-1 默认为-1 + */ + @Excel(name = "推荐人的会员id 如果没有 则为-1 默认为-1") + private Long recommended = -1L; + + /** + * 二级推荐人的会员id (上级的上级) 如果没有 则为-1 默认为-1 + */ + @Excel(name = "二级推荐人的会员id ", readConverterExp = "上=级的上级") + private Long sRecommended = -1L; + + /** + * 会员自己的推荐码 + */ + @Excel(name = "会员自己的推荐码") + private String selfRecommendCode; + + /** + * 会员的佣金 + */ + @Excel(name = "会员的佣金") + private BigDecimal commission; + + /** + * 会员所属的店铺id + */ + @Excel(name = "会员所属的店铺id") + private Long beloneStoreId; + /** + * 用户积分 + */ + @ApiModelProperty(value = "用户积分") + private int customerPoint; + private int subSpreadCustomerCount; + /** + * 推荐人code 如果为空 则说明没有推荐人 + */ + private String recommondCode; + /** + * 自动注册渠道类型 + */ + @ApiModelProperty(value = "自动注册渠道类型") + private String channelType; + private UmsMemberLevel customerLevel; + + private BigDecimal allPredeposit; + + /** + * 构造app用户注册对象 + * + * @param mobile 手机号码 + * @param password 密码 + * @param recommondCode 推荐吗 + * @return 返回app用户注册对象 + */ + public static UmsMember buildAppRegisterCustomer(String mobile, String password, String recommondCode) { + UmsMember customer = new UmsMember(); + customer.username = mobile; + customer.password = password; + customer.mobile = mobile; + customer.type = "1"; + customer.source = "2"; + customer.isMobileVerification = "1"; + + customer.recommondCode = recommondCode; + return customer; + } + + /** + * 构造h5用户注册对象 + * + * @param mobile 手机号码 + * @param recommondCode 推荐吗 + * @return 返回app用户注册对象 + */ + public static UmsMember buildH5RegisterCustomer(String mobile, String recommondCode) { + UmsMember customer = new UmsMember(); + customer.username = mobile; + customer.password = "123456"; + customer.mobile = mobile; + customer.type = "1"; + customer.source = "3"; + customer.isMobileVerification = "1"; + + customer.recommondCode = recommondCode; + return customer; + } + + /** + * 构造代客下单自动注册对象 + * + * @param mobile 手机号码 + * @return 返回代客下单自动注册对象 + */ + public static UmsMember buildStoreShoppingRegisterCustomer(String mobile, long beloneStoreId) { + UmsMember customer = new UmsMember(); + customer.username = mobile; + customer.password = "123456"; + customer.mobile = mobile; + customer.type = "1"; + customer.source = "4"; + customer.status = "1"; + customer.storeId = 0L; + customer.isMobileVerification = "1"; + customer.beloneStoreId = beloneStoreId; + return customer; + + } + + public int getSubSpreadCustomerCount() { + return subSpreadCustomerCount; + } + + public void setSubSpreadCustomerCount(int subSpreadCustomerCount) { + this.subSpreadCustomerCount = subSpreadCustomerCount; + } + + public String getRecommondCode() { + return recommondCode; + } + + public void setRecommondCode(String recommondCode) { + this.recommondCode = recommondCode; + } + + public UmsMemberLevel getCustomerLevel() { + return customerLevel; + } + + public void setCustomerLevel(UmsMemberLevel customerLevel) { + this.customerLevel = customerLevel; + } + + /** + * 设置下级分销会员数量 + * + * @param subSpreadCustomerCount 下级分销会员数量 + * @return 返回当前对象 + */ + public UmsMember addSubSpreadCustomerCount(int subSpreadCustomerCount) { + this.subSpreadCustomerCount = subSpreadCustomerCount; + return this; + } + + /** + * 设置自己的推荐吗 + * + * @return 返回当前对象 + */ + public UmsMember addSelfRecommondCode() { + this.selfRecommendCode = ShareCodeUtils.toSerialCode(Long.parseLong(this.mobile)); + return this; + } + + /** + * 判断是否有推荐人 有返回true 没有返回false + * + * @return 有返回true 没有返回false + */ + @JsonIgnore + public boolean hasRecommonded() { + return !StringUtils.isEmpty(this.recommondCode) || this.recommended != -1; + } + + /** + * 后端添加用户设置默认值 + * + * @return 返回用户信息 + */ + public UmsMember setDefaultValuesForAdminAdd() { + this.storeId = 0L; + this.type = "1"; + this.source = "4"; + this.status = "1"; + this.isMobileVerification = "1"; + if (!StringUtils.isEmpty(this.email)) { + this.isEmailVerification = "1"; + } + + this.beloneStoreId = 0L; + return this; + } + + /** + * 设置归属门店id + * + * @param beloneStoreId 归属门店id + * @return 返回用户信息 + */ + public UmsMember setBelongStoreIdForStore(long beloneStoreId) { + this.beloneStoreId = beloneStoreId; + return this; + } + + /** + * 清除用户密码 + */ + public UmsMember clearPassword() { + this.password = "**********"; + if (!StringUtils.isEmpty(this.paypassword)) { + this.paypassword = "**********"; + } + return this; + } + + /** + * 获取会员对象 + * + * @param customerId 会员id + * @return 会员对象 + */ + public UmsMember setCustomerId(long customerId) { + this.id = customerId; + return this; + } + + /** + * 获得会员的会员等级id + * + * @return 返回会员的会员等级id + */ + @JsonIgnore + public long getCustomerLevelId() { + return Objects.isNull(this.customerLevel) ? -1 : this.customerLevel.getId(); + } + + /** + * 获得会员等级名称 + * + * @return 返回会员等级名称 + */ + @JsonIgnore + public String getCustomerLevelName() { + return Objects.isNull(this.customerLevel) ? "" : this.customerLevel.getName(); + } + + /** + * 检查更改金额 + * + * @param money 更改金额 + * @return true 可以更改 false 更改后总金额小于0,不可以更改 + */ + public boolean checkConsumptionAmount(BigDecimal money) { + if (money.intValue() >= 0) { + return true; + } + if (money.abs().compareTo(this.consumptionAmount) > 0) { + return false; + } + return true; + } + + /** + * 检查更改佣金金额 + * + * @param money 更改佣金金额 + * @return true 可以更改 false 更改后总金额小于0,不可以更改 + */ + public boolean checkCommission(BigDecimal money) { + if (money.intValue() >= 0) { + return true; + } + if (money.abs().compareTo(this.commission) > 0) { + return false; + } + return true; + } + + + /** + * 为用户添加用户名 + * + * @param username + * @return + */ + public UmsMember addUsername(String username) { + this.username = username; + return this; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + 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 getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public String getRelename() { + return relename; + } + + public void setRelename(String relename) { + this.relename = relename; + } + + public String getCardid() { + return cardid; + } + + public void setCardid(String cardid) { + this.cardid = cardid; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public String getMonthlyIncome() { + return monthlyIncome; + } + + public void setMonthlyIncome(String monthlyIncome) { + this.monthlyIncome = monthlyIncome; + } + + public String getMarriageStatus() { + return marriageStatus; + } + + public void setMarriageStatus(String marriageStatus) { + this.marriageStatus = marriageStatus; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getModifiedEmail() { + return modifiedEmail; + } + + public void setModifiedEmail(String modifiedEmail) { + this.modifiedEmail = modifiedEmail; + } + + public String getCheckCode() { + return checkCode; + } + + public void setCheckCode(String checkCode) { + this.checkCode = checkCode; + } + + public Long getProvince() { + return province; + } + + public void setProvince(Long province) { + this.province = province; + } + + public Long getCity() { + return city; + } + + public void setCity(Long city) { + this.city = city; + } + + public Long getCounty() { + return county; + } + + public void setCounty(Long county) { + this.county = county; + } + + public String getDetailaddress() { + return detailaddress; + } + + public void setDetailaddress(String detailaddress) { + this.detailaddress = detailaddress; + } + + public String getInterest() { + return interest; + } + + public void setInterest(String interest) { + this.interest = interest; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAppletOpenId() { + return appletOpenId; + } + + public void setAppletOpenId(String appletOpenId) { + this.appletOpenId = appletOpenId; + } + + public String getAppOpenId() { + return appOpenId; + } + + public void setAppOpenId(String appOpenId) { + this.appOpenId = appOpenId; + } + + public String getH5OpenId() { + return h5OpenId; + } + + public void setH5OpenId(String h5OpenId) { + this.h5OpenId = h5OpenId; + } + + public BigDecimal getConsumptionAmount() { + return consumptionAmount; + } + + public void setConsumptionAmount(BigDecimal consumptionAmount) { + this.consumptionAmount = consumptionAmount; + } + + public String getPaypassword() { + return paypassword; + } + + public void setPaypassword(String paypassword) { + this.paypassword = paypassword; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getSignNum() { + return signNum; + } + + public void setSignNum(int signNum) { + this.signNum = signNum; + } + + public String getIsMobileVerification() { + return isMobileVerification; + } + + public void setIsMobileVerification(String isMobileVerification) { + this.isMobileVerification = isMobileVerification; + } + + public String getIsEmailVerification() { + return isEmailVerification; + } + + public void setIsEmailVerification(String isEmailVerification) { + this.isEmailVerification = isEmailVerification; + } + + public int getLoginErrorCount() { + return loginErrorCount; + } + + public void setLoginErrorCount(int loginErrorCount) { + this.loginErrorCount = loginErrorCount; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + public Date getDelTime() { + return delTime; + } + + public void setDelTime(Date delTime) { + this.delTime = delTime; + } + + public LocalDateTime getLockTime() { + return lockTime; + } + + public void setLockTime(LocalDateTime lockTime) { + this.lockTime = lockTime; + } + + public Date getLastLoginTime() { + return lastLoginTime; + } + + public void setLastLoginTime(Date lastLoginTime) { + this.lastLoginTime = lastLoginTime; + } + + public Long getRecommended() { + return recommended; + } + + public void setRecommended(Long recommended) { + this.recommended = recommended; + } + + public Long getsRecommended() { + return sRecommended; + } + + public void setsRecommended(Long sRecommended) { + this.sRecommended = sRecommended; + } + + public String getSelfRecommendCode() { + return selfRecommendCode; + } + + public void setSelfRecommendCode(String selfRecommendCode) { + this.selfRecommendCode = selfRecommendCode; + } + + public BigDecimal getCommission() { + return commission; + } + + public void setCommission(BigDecimal commission) { + this.commission = commission; + } + + public Long getBeloneStoreId() { + return beloneStoreId; + } + + public void setBeloneStoreId(Long beloneStoreId) { + this.beloneStoreId = beloneStoreId; + } + + public int getCustomerPoint() { + return customerPoint; + } + + public void setCustomerPoint(int customerPoint) { + this.customerPoint = customerPoint; + } + + public String getChannelType() { + return channelType; + } + + public void setChannelType(String channelType) { + this.channelType = channelType; + } + + public BigDecimal getAllPredeposit() { + return allPredeposit; + } + + public void setAllPredeposit(BigDecimal allPredeposit) { + this.allPredeposit = allPredeposit; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMemberLevel.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMemberLevel.java new file mode 100644 index 0000000..3af9e36 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/domain/UmsMemberLevel.java @@ -0,0 +1,206 @@ +package com.ruoyi.member.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; + +/** + * 会员等级对象 ums_member_level + * + * @author 魔金商城 + * @date 2020-07-25 + */ +public class UmsMemberLevel extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 会员等级名称 + */ + @Excel(name = "会员等级名称") + private String name; + + /** + * 消费小值(包含该值) + */ + @Excel(name = "消费小值", readConverterExp = "包=含该值") + private Long minMoney; + + /** + * 消费金额最大值 不包含该值 + */ + @Excel(name = "消费金额最大值 不包含该值") + private Long maxMoney; + + /** + * 会员折扣 + */ + @Excel(name = "会员折扣") + private BigDecimal discount; + + /** + * 删除标记 0 未删除 1删除 默认0 + */ + private int delFlag; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modifyTime; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "删除时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date delTime; + + /** + * 构造未知等级实体 + * + * @return 返回未知等级实体 + */ + public static UmsMemberLevel buildNoLevel() { + UmsMemberLevel customerLevel = new UmsMemberLevel(); + customerLevel.name = "非会员"; + return customerLevel; + } + + 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 Long getMinMoney() { + return minMoney; + } + + public void setMinMoney(Long minMoney) { + this.minMoney = minMoney; + } + + public Long getMaxMoney() { + return maxMoney; + } + + public void setMaxMoney(Long maxMoney) { + this.maxMoney = maxMoney; + } + + public BigDecimal getDiscount() { + return discount; + } + + public void setDiscount(BigDecimal discount) { + this.discount = discount; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + public Date getDelTime() { + return delTime; + } + + public void setDelTime(Date delTime) { + this.delTime = delTime; + } + + /** + * 根据传入的金额判断 是否是当前等级 + * + * @param money 传入金金额 + * @return 判断规则 [0,100) 前闭后开 包含0 不包含100 + */ + public boolean isCurrentLevl(BigDecimal money) { + if (Objects.isNull(money)) { + return false; + } + return money.intValue() >= this.minMoney && money.intValue() < this.maxMoney; + } + + /** + * 判断传入的会员等级消费金额和当前的会员等级消费金额是否有交集 + * + * @param customerLevel 会员等级 + * @return 有返回true 没有返回false 传入的值为空 返回false + */ + public boolean hasIntersection(UmsMemberLevel customerLevel) { + if (Objects.isNull(customerLevel)) { + return false; + } + + // 如果传入的最小值比当前的最大值要大于等于 则肯定没有交集 + if (customerLevel.minMoney >= this.maxMoney) { + return false; + } + if (customerLevel.minMoney >= customerLevel.maxMoney) { + return true; + } + // 如果传入的最小值在当前会员等级最大值和最小值之间(不包含最大值 包含最小值) 则肯定会有交集 + if (customerLevel.minMoney >= this.minMoney && customerLevel.minMoney < this.maxMoney) { + return true; + } + + // 如果传入的最小值在比当前的最小值还小 则看传入的最大值 + if (customerLevel.minMoney < this.minMoney) { + if (customerLevel.maxMoney <= this.minMoney) { + return false; + } else { + return true; + } + } + return true; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("minMoney", getMinMoney()) + .append("maxMoney", getMaxMoney()) + .append("discount", getDiscount()) + .append("delFlag", getDelFlag()) + .append("createTime", getCreateTime()) + .append("modifyTime", getModifyTime()) + .append("delTime", getDelTime()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/mapper/WeChatCustomerLinkMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/mapper/WeChatCustomerLinkMapper.java new file mode 100644 index 0000000..b8b8090 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/mapper/WeChatCustomerLinkMapper.java @@ -0,0 +1,65 @@ +package com.ruoyi.member.mapper; + + +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import org.springframework.stereotype.Repository; + +/** + * 微信用户关联数据库接口 + */ +@Repository +public interface WeChatCustomerLinkMapper { + + /** + * 根据openId查询关联实体 + * + * @param openId 微信用户唯一标识 + */ + + WeChatCustomerLink queryWeChatCustomerLinkByOpenId(String openId); + + + /** + * 根据customerId查询关联实体 + * + * @param customerId 用户id + */ + + WeChatCustomerLink queryWeChatCustomerLinkByCustomerId(long customerId); + + /** + * 根据unionId查询关联实体 + * + * @param unionId 微信联合登录id + */ + + WeChatCustomerLink queryWeChatCustomerLinkByUnionId(String unionId); + + /** + * 增加关联 + * + * @param weChatCustomerLink 关联实体 + * @return 1:成功 + */ + + int addWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink); + + /** + * 删除关联 + * + * @param customerId 用户id + * @return 1:成功 + */ + + int deleteWeChatCustomerLink(long customerId); + + /** + * 更新微信用户关联 + * + * @param weChatCustomerLink 微信用户关联实体 + * @return 1成功 否则失败 + */ + + int updateWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink); +} + diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/LoginService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/LoginService.java new file mode 100644 index 0000000..7e71349 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/LoginService.java @@ -0,0 +1,21 @@ +package com.ruoyi.member.service; + + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.segchk.domain.SegchkUserWebReq; + +/** + * Created by 魔金商城 on 17/7/17. + * 登录接口 + */ +public interface LoginService { + + + /** + * segchk前端登录 (app,pc,mobile) + * + * @param segchkUserWebReq 登入参数 + * @return 返回码 -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + */ + AjaxResult login(SegchkUserWebReq segchkUserWebReq); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RechargeService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RechargeService.java new file mode 100644 index 0000000..36f5547 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RechargeService.java @@ -0,0 +1,36 @@ +package com.ruoyi.member.service; + + +import com.ruoyi.common.core.domain.AjaxResult; + +import java.math.BigDecimal; + +/** + * 充值服务 + */ +public interface RechargeService { + + /** + * 支付宝pc支付 + * + * @param money 充值金额 + * @param customerId 用户id + * @param type 支付类型 1:订单支付 2:预存款充值 + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -2:生成充值记录出错 -5:支付宝生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + AjaxResult aliPagePay(String transCode, BigDecimal money, int payType, long customerId, int type); + + /** + * 微信扫码支付 + * + * @param money 充值金额 + * @param customerId 用户id + * @param ip 请求真实ip + * @param type 支付类型 1:订单支付 2:预存款充值 + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -2:生成充值记录出错 -5:微信生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + AjaxResult wechatQRPay(String transCode, BigDecimal money, int payType, long customerId, String ip, int type); + + + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterService.java new file mode 100644 index 0000000..7cb153d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterService.java @@ -0,0 +1,68 @@ +package com.ruoyi.member.service; + +import java.util.function.Consumer; + +/** + * Created by 魔金商城 on 17/11/18. + * 注册服务接口 + */ +public interface RegisterService { + + /** + * 发送注册短信验证码 + * + * @param mobile 手机号码 + * @param consumer 回调接口 + * @return 0 成功 1 失败 -1 手机号码已经存在 + */ + int sendRegisterSmsCode(String mobile, Consumer consumer); + /** + * 发送注册短信验证码 + * + * @param mobile 手机号码 + * @param consumer 回调接口 + * @return 0 成功 1 失败 -1 手机号码已经存在 + */ + int sendRegisterSmsCodeFortest(String mobile, Consumer consumer); + + /** + * 发送注册短信验证码(PC端用,带有图片验证码) + * + * @param mobile 手机号码 + * @param kaptcha 用户输入的图片验证码 + * @param oldKaptcha redis中的图片验证码 + * @param consumer 回调接口 + * @return 0 成功 1 失败 -4 手机号码已经存在 -1 图片验证码失效或不存在 -2 图片验证码为空 -3 图片证码不正确 + */ + int sendRegisterSmsCodeForPc(String mobile, String kaptcha, String oldKaptcha, Consumer consumer); + + /** + * 用户注册 + * + * @param mobile 手机号码 + * @param password 密码 + * @param code 用户输入的手机验证码 + * @param originCode 生成的手机验证码 + * @param recommondCode 推荐吗 + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + int registerCustomer(String mobile, String password, String code, String originCode, String recommondCode); + + /** + * 免密用户自动注册 + * + * @param phoneNo 手机号码 + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + Long unAuthRegister(String phoneNo, String channelType); + + /** + * 校验验证码 + * + * @param kaptcha 验证码 + * @param kaptchaInSession session中的验证码 + * @return -1 验证码失效或不存在 -2 验证码为空 -3验证码不正确 1 成功 + */ + int checkKaptcha(String kaptcha, String kaptchaInSession); + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterServiceApi.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterServiceApi.java new file mode 100644 index 0000000..47da24f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/RegisterServiceApi.java @@ -0,0 +1,38 @@ +package com.ruoyi.member.service; + +import com.ruoyi.common.core.domain.AjaxResult; + +/** + * 注册服务聚合接口 + */ +public interface RegisterServiceApi { + + /** + * 用户注册 + * + * @param mobile 手机号码 + * @param password 密码 + * @param code 用户输入的手机验证码 + * @param originCode 生成的手机验证码 + * @param recommondCode 推荐吗 + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ +// int registerCustomer(String mobile, String password, String code, String originCode, String recommondCode); + + + /** + * 用户注册 + * + * @param mobile 手机号码 + * @param code 用户输入的手机验证码 + * @param originCode 生成的手机验证码 + * @param recommondId 推荐吗 + * @param recommondLevel 推荐角色 + * @param providerId + * @param remark + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + AjaxResult registerCustomer(String mobile, String code, String originCode, String recommondId, String recommondLevel, String providerId, String remark); + + String createToke(String subject, Long userId, Long providerId, Integer userLevel); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/SmsService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/SmsService.java new file mode 100644 index 0000000..cae1b2e --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/SmsService.java @@ -0,0 +1,71 @@ +package com.ruoyi.member.service; + +import java.math.BigDecimal; + +/** + * Created by 魔金商城 on 17/11/18. + * 短信验证码服务接口 + */ +public interface SmsService { + + /** + * 发送短信 + * + * @param phone 手机号码 + * @param content 发送内容 + * @return 成功返回0 失败返回1 + */ + int sendSms(String phone, String content); + + /** + * 发送核销码短信 + * + * @param phone 手机号码 + * @param code 订单号 + * @param writeOffCode 核销码 + * @param storeName 店铺名称 + * @return 成功返回0 失败返回1 + */ + int sendWiteOffCodeSms(String phone, String code, String writeOffCode, String storeName); + + /** + * 发送虚拟商品订单核销码短信 + * + * @param phone 手机号码 + * @param code 订单号 + * @param writeOffCode 核销码 + * @param storeName 店铺名称 + * @return 成功返回0 失败返回1 + */ + int sendVirtualOrderWiteOffCodeSms(String phone, String code, String writeOffCode, String storeName); + + + /** + * 发送社区团购审核结果通知短信 + * + * @param phone 手机号码 + * @param submittime 通过时间 + * @return 成功返回0 失败返回1 + */ + int sendAuditTemplateOffCodeSms(String phone, String submittime); + + /** + * 发送社区团购结算短信 + * + * @param communityName 社区团购名称 + * @param price 佣金 + * @param phone 手机号码 + * @return 成功发挥0 失败返回1 + */ + int sendCommunityBuySettlementSms(String phone, String communityName, BigDecimal price); + + /** + * 社区团购提现申请打款通知 + * + * @param phone 手机号码 + * @param submittime 打款时间 + * @param price 金额 + * @return 成功返回0 失败返回1 + */ + int sendCommunityBuyWitudrawSms(String phone, String submittime, BigDecimal price); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatAppletLoginService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatAppletLoginService.java new file mode 100644 index 0000000..f7307e7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatAppletLoginService.java @@ -0,0 +1,66 @@ +package com.ruoyi.member.service; + + +import com.ruoyi.member.vo.AppletLoginInfo; +import com.ruoyi.member.vo.AppletLoginRedisParamResponse; +import com.ruoyi.util.WeChatAppletUserInfo; + +import java.util.function.Consumer; + +/** + * 微信小程序登录服务 + * + * @author SK + * @since 2018/6/13 + */ +public interface WeChatAppletLoginService { + + /** + * 小程序获取登录信息 + * + * @param code 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息 + * @param unionId 联合登录id + * @param claimsConsumer 回调 + * @return 登录信息 + */ + AppletLoginInfo getLoginInfo(String code, String unionId, Consumer claimsConsumer); + + /** + * 处理小程序用户信息 + * + * @param weChatAppletUserInfo 小程序用户信息实体 + * @param openId 微信用户标识 + * @param sessionKey 小程序sessionKey + * @param claimsConsumer 回调 + * @return 登录信息 + */ + AppletLoginInfo dealUserInfo(WeChatAppletUserInfo weChatAppletUserInfo, String openId, String sessionKey, Consumer claimsConsumer); + + + /** + * 检验用户是否已绑定 + * + * @param userName 用户名 + * @return -9已经绑定过 1:没有绑定 + */ + int checkCustomerBind(String userName); + + /** + * 绑定账号 + * + * @param openId 微信用户唯一标识 + * @param unionId 微信联合登录id + * @param customerId 用户id + * @return 1:成功 + */ + int bindAccount(String openId, String unionId, long customerId); + + /** + * 解绑账号 + * + * @param customerId 用户id + * @param unionId 联合登录id,用于redis缓存 + * @return 1:成功 + */ + int unbindAccount(long customerId, String unionId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatCustomerLinkService.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatCustomerLinkService.java new file mode 100644 index 0000000..848c3ab --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/WeChatCustomerLinkService.java @@ -0,0 +1,86 @@ +package com.ruoyi.member.service; + + +import com.ruoyi.common.utils.RedisCahceKey; +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import com.ruoyi.util.Claims; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Repository; + +/** + * 微信用户关联服务接口 + */ +@Repository +public interface WeChatCustomerLinkService { + + /** + * 增加关联 + * + * @param weChatCustomerLink 关联实体 + * @return 1:成功 + */ + int addWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink); + + /** + * 根据openId查询关联实体 + * + * @param openId 微信用户唯一标识 + */ + WeChatCustomerLink queryWeChatCustomerLinkByOpenId(String openId); + + + /** + * 根据用户id查询关联实体 + * + * @param customerId 用户id + */ + WeChatCustomerLink queryWeChatCustomerLinkByCustomerId(long customerId); + + /** + * 根据用户名查询关联实体 + * + * @param userName 用户名 + */ + WeChatCustomerLink queryWeChatCustomerLinkByUserName(String userName); + + /** + * 根据unionId查询关联实体 + * + * @param unionId 微信联合登录id + */ + WeChatCustomerLink queryWeChatCustomerLinkByUnionId(String unionId); + + + /** + * 解绑账号 + * + * @param customerId 用户id + * @param unionId 联合登录id,redis缓存使用 + * @return 1:成功 + */ + int unbindWeChatCustomerLink(long customerId, String unionId); + + + /** + * 更新微信用户关联 + * + * @param weChatCustomerLink 微信用户关联实体 + * @return 1成功 否则失败 + */ + int updateWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink); + + /** + * 更新微信用户关联 + * + * @param segchkUserWechat 微信用户关联实体 + * @param userLevel + * @return 1成功 否则失败 + */ + int addSegchkUserWechat(SegchkUserWechat segchkUserWechat, String userLevel); + + int addSegchkUserWechat(SegchkUserWechat segchkUserWechat, String userLevel, String token); + + public SegchkUserWechat getSegchkUserWechat(Claims claims, String token); +} + diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/BindNewEmailServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/BindNewEmailServiceImpl.java new file mode 100644 index 0000000..e69de29 diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/LoginServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..41dd100 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/LoginServiceImpl.java @@ -0,0 +1,223 @@ +package com.ruoyi.member.service.impl; + + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.member.service.LoginService; +import com.ruoyi.member.service.RegisterService; +import com.ruoyi.segchk.domain.SegchkUserWebReq; +import com.ruoyi.segchk.domain.SegchkUserWebResp; +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.segchk.service.ISegchkProviderIndexService; +import com.ruoyi.segchk.service.ISegchkStoreIndexService; +import com.ruoyi.segchk.service.ISegchkUserIndexService; +import com.ruoyi.util.CommonConstant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +/** + * Created by 魔金商城 on 17/7/17. + * 登录服务接口 + */ +@Service("loginService") +public class LoginServiceImpl implements LoginService { + + /** + * 请求时间戳过期时间5分钟 + */ + private static final int REQUEST_TIME_OUT = 1000 * 60 * 5; + /** + * 注入会员服务接口 + */ +// @Autowired +// private IUmsMemberService customerService; + /** + * 注册接口 + */ + @Autowired + private RegisterService registerService; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + /** + * jwt密钥 + */ + @Value("${token.secret}") + private String jwtSecretKey; +// @Autowired +// private ITStoreInfoService storeInfoService; + /** + * 密码工具类 + */ + @Autowired + private PasswordEncoder passwordEncoder; + @Value("${auth.salt:wsfmall}") + private String salt; + +// @Override + /*public AjaxResult login(LoginParams loginParams) { + log.debug("login and loginParams:{}", loginParams); + + if (Objects.isNull(loginParams)) { + log.info("login fail due to loginParams is null...."); + return AjaxResult.error(-6,"loginParams is null"); + } + + // 验证验证码 + if (!loginParams.validateCode()) { + log.info("login fail due to validateCode fail...."); + return AjaxResult.error(-6,"validateCode fail"); + } + + + // 根据用户名查询出用户信息 + UmsMember customer = customerService.queryCustomerByName(loginParams.getMobile()); + + log.debug("login member:{}", customer); + + // 用户不存在直接返回失败 + if (Objects.isNull(customer)) { + log.info("login fail due to member is not exist...."); + return AjaxResult.error(-4,"member is not exist"); + } + + // 登录次数 + int errorCount = customer.getLoginErrorCount(); + + // 判断用户账号是否正常 + if (!"1".equals(customer.getStatus())) { + log.info("login fail due to member status is error ...."); + return AjaxResult.error(-2,"账号冻结"); + } + + //判断用户的账号是否被锁定 + if (Objects.nonNull(customer.getLockTime())) { + if (LocalDateTime.now().isBefore(customer.getLockTime().plus(30, ChronoUnit.MINUTES))) { + // 账户被锁定或禁用 + log.info("login fail due to member is locked ...."); + return AjaxResult.error(-3,"账号锁定"); + } else { + // 30分钟后解锁用户 + customerService.unlockUser(customer.getId()); + errorCount = 0; + } + } +// -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + + // 判断用户密码是否正确 + if (!passwordEncoder.matches(loginParams.getPassword(), customer.getPassword())) { + log.info("login fail due to password is wrong...."); + + //增加登录失败的次数 + customerService.updateLoginErrorCount(customer.getId()); + + // 如果登录失败次数>= 6次 则锁定帐户 30分钟内不能登录 + if (errorCount + 1 >= 6) { + customerService.lockUser(customer.getId()); + return null; + } else { + return AjaxResult.error(-1,"用户名或密码错误"); + } + } + // 清除密码 + customer.clearPassword(); + + // 更新登录时间 + customerService.updateLoginTime(customer.getId()); + + //清除登录错误次数 + customerService.unlockUser(customer.getId()); + Map res = new HashMap<>(); + final StringBuilder sb = new StringBuilder(); + sb.append(Jwts.builder().setSubject(customer.getUsername()) + .compressWith(CompressionCodecs.DEFLATE) + .signWith(SignatureAlgorithm.HS256, jwtSecretKey) + .setIssuedAt(new Date()) + .claim("userName", customer.getUsername()) + .claim("nickName", customer.getNickname()) + .claim("releName", customer.getRelename()) + .claim("id", customer.getId()) + .setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) // 有效期1小时 + .compact()); + if (customer != null) { + AppletLoginRedisParamResponse appletLoginRedisParamResponse = new AppletLoginRedisParamResponse(); + appletLoginRedisParamResponse.setCustomerId(customer.getId()); + appletLoginRedisParamResponse.setToken(sb.toString()); + redisService.putToRedis(sb.toString(), JSON.toJSONString(appletLoginRedisParamResponse),1, TimeUnit.DAYS); + redisService.putToRedis(loginParams.getMobile(), sb.toString()); + res.put("access_token", sb.toString()); + res.put("refresh_token", sb.toString()); + res.put("member", customer); + } + + log.debug("ok...login success....."); + + return AjaxResult.success(res); + }*/ + + + /** + * segchk前端登录 (app,pc,mobile) + * + * @param segchkUserWebReq 登入参数 + * @return 返回码 -1 用户名或密码错误 -2 账号冻结 -3 账号锁定 1 成功 -4 验证码错误 + */ + @Override + public AjaxResult login(SegchkUserWebReq segchkUserWebReq) { + AjaxResult ajaxResult = null; + SegchkUserWebResp segchkUserWebResp = null; + switch (segchkUserWebReq.getUserLevel()){ + case 0: { + segchkUserWebResp = segchkProviderIndexService.selectSegchkProviderWebInfo(segchkUserWebReq); + segchkUserWebResp.setUserLevel(0); + segchkUserWebResp.setUserId(segchkUserWebReq.getProviderId()); + break; + } + case 1: { + segchkUserWebResp = segchkStoreIndexService.selectSegchkStoreWebInfo(segchkUserWebReq); + segchkUserWebResp.setUserLevel(1); + break; + } + case 2: { + segchkUserWebResp = segchkUserIndexService.selectSegchkUserWebInfo(segchkUserWebReq); + segchkUserWebResp.setUserLevel(2); + break; + } + default: return AjaxResult.error("301", "用户身份异常"); + } + try { + segchkUserWebResp.setUserName(URLDecoder.decode(segchkUserWebResp.getUserName(), "utf-8")); + } catch (UnsupportedEncodingException e) { + + e.printStackTrace(); + } + ajaxResult = AjaxResult.success(segchkUserWebResp); + + return ajaxResult; + } + + private SegchkUserWechat getSegchkUserWechat(String token) { + StringBuilder sb = new StringBuilder(CommonConstant.APPLET_BIND_OPENID).append("-").append(token); + Object segchkUserWechat = redisService.getCacheObject(sb.toString()); + + return ObjectUtils.isEmpty(segchkUserWechat) ? null : (SegchkUserWechat) segchkUserWechat; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceApiImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceApiImpl.java new file mode 100644 index 0000000..f45ac19 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceApiImpl.java @@ -0,0 +1,238 @@ +package com.ruoyi.member.service.impl; + + +//import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.SnowflakeIdWorker; +import com.ruoyi.member.service.RegisterService; +import com.ruoyi.member.service.RegisterServiceApi; +import com.ruoyi.segchk.domain.SegchkUserBasicInfo; +import com.ruoyi.segchk.domain.SegchkUserExtInfo; +import com.ruoyi.segchk.domain.SegchkUserLevelInfo; +import com.ruoyi.segchk.service.*; +import com.ruoyi.util.Claims; +import com.ruoyi.util.CommonConstant; +import io.jsonwebtoken.*; +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 org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 注册服务聚合接口实现 + */ +@Service +public class RegisterServiceApiImpl implements RegisterServiceApi { + + + /** + * 日志 + */ + private Logger logger = LoggerFactory.getLogger(RegisterServiceApiImpl.class); + + + /** + * jwt密钥 + */ + @Value("${token.secret}") + private String jwtSecretKey; + + + // 登录超时时长,单位天,-1永久有效 + @Value("${yzytest.login.loginexpire:#{1}}") + private Integer loginexpire; + + /** + * 注入注册服务 + */ + @Autowired + private RegisterService registerService; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + @Autowired + private SnowflakeIdWorker snowflakeIdWorker; + + /** + * 用户注册 + * + * @param mobile 手机号码 + * @param code 用户输入的手机验证码 + * @param originCode 生成的手机验证码 + * @param recommondId 推荐吗 + * @param recommondLevel 推荐角色 + * @param providerId + * @param remark + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + @Override + @Transactional + public AjaxResult registerCustomer(String mobile, String code, String originCode, String recommondId, String recommondLevel, String providerId, String remark) { + + if(StringUtils.isEmpty(code)){ + logger.error("registerCustomer fail due to code is empty..."); + return AjaxResult.error(500, "验证码为空!"); + } + + if(StringUtils.isEmpty(mobile)){ + logger.error("registerCustomer fail due to mobile is empty..."); + return AjaxResult.error(500, "手机号码为空!"); + } + + if(StringUtils.isEmpty(providerId)){ + logger.error("registerCustomer fail due to providerId is empty..."); + return AjaxResult.error(500, "无法获取您的注册区域!"); + } + + // 校验验证码是否正确TODO + if (!code.equals(originCode)) { + logger.error("registerCustomer fail due to code is error with originCode..."); + return AjaxResult.error(500, "验证码错误!"); + } + + SegchkUserLevelInfo segchkUserLevelInfo = segchkUserIndexService.selectUserLevelByMobile(mobile); + SegchkUserExtInfo segchkUserExtInfo = null; + + if(ObjectUtils.isEmpty(segchkUserLevelInfo)){ + logger.debug("registerCustomer prov {} mobile: {{}} is a new user with recommender:{}---{}", providerId, mobile, recommondId, recommondLevel); + segchkUserLevelInfo = new SegchkUserLevelInfo(); +// 如果用户信息空,则添加新的用户 +// 添加新用户信息 + SegchkUserBasicInfo segchkUserBasicInfo = new SegchkUserBasicInfo(); + segchkUserBasicInfo.setPhoneNo(mobile); + segchkUserBasicInfo.setCardTypeId(-1L); + segchkUserBasicInfo.setHasWechat("0"); + segchkUserBasicInfo.setProviderId(Long.valueOf(providerId)); + segchkUserBasicInfo.setUserIcon(""); + int ret = segchkUserIndexService.addUserBasicInfo(segchkUserBasicInfo); + if(ret != 1){ + logger.error("registerCustomer fail due to register is wrong..."); + return AjaxResult.error(500, "注册异常,请联系客服!"); + } + + if(!StringUtils.isEmpty(recommondId) && !StringUtils.isEmpty(recommondLevel)){ +// 如果推荐人,推荐人角色都非空。要检查推荐人是否存在。否则推荐人设置为运营商 + + Map parmMap = new HashMap<>(); + parmMap.put("recommondId", recommondId); + parmMap.put("recommondLevel", recommondLevel); + parmMap.put("providerId", providerId); + ret = segchkUserIndexService.recommenderIsExit(parmMap); + + switch (ret){ + case 0:{ +// 推荐人不存在,归属平台推荐,注册到某一运营商即可 + logger.warn("registerCustomer recommender is not exit!!! will be register with platform on provider({})", providerId); + break; + } + case 1: { + logger.debug("registerCustomer recommender is exit!!!"); + segchkUserExtInfo = new SegchkUserExtInfo(); + segchkUserExtInfo.setProviderId(Long.valueOf(providerId)); + segchkUserExtInfo.setRecommendersLevel(recommondLevel); + segchkUserExtInfo.setUserRecommenders(Long.valueOf(recommondId)); + segchkUserExtInfo.setUserId(segchkUserBasicInfo.getUserId()); + int xxx = segchkUserIndexService.insertUserExtInfo(segchkUserExtInfo); + if(xxx < 1){ + logger.error("registerCustomer fail due to recommender binding is wrong..."); +// return AjaxResult.error(500, "推荐人绑定异常,请联系客服!"); + } + break; + } + case 2: { + logger.warn("registerCustomer user is different from recommender, will be register with platform on provider({})", providerId); + break; + } + } + } + + segchkUserLevelInfo.setProviderId(Long.valueOf(providerId)); + segchkUserLevelInfo.setUserId(segchkUserBasicInfo.getUserId()); + segchkUserLevelInfo.setUserLevel(2L); + } +// 如果是已经注册的用户。则直接返回用户信息 + + String openId = segchkUserIndexService.getWeChatInfoByUserId(segchkUserLevelInfo); + if("999999".equals(remark)){ + openId = code; + } + if(openId == null){ +// 说明用户之前没有绑定微信 + segchkUserLevelInfo.setToken(null); + } + else { + String token = createToken(CommonConstant.APPLET_LOGIN_KEY, segchkUserLevelInfo.getUserId(), segchkUserLevelInfo.getProviderId(), segchkUserLevelInfo.getUserLevel().intValue()); + segchkUserLevelInfo.setToken(token); + Claims claims = new Claims(); + claims.setUserId(segchkUserLevelInfo.getUserId()); + claims.setOpenId(openId); + claims.setProviderId(segchkUserLevelInfo.getProviderId()); + claims.setUserLevel(segchkUserLevelInfo.getUserLevel().intValue()); +// 将用户的token进行缓存 + if(loginexpire == -1) { + redisService.setCacheObject(token, claims); + } + else { + redisService.setCacheObject(token, claims, loginexpire, TimeUnit.DAYS); + } + } + logger.debug("registerCustomer res: ---{}---{}", segchkUserLevelInfo.toString(), (ObjectUtils.isEmpty(segchkUserExtInfo) ? null : segchkUserExtInfo.toString())); + return AjaxResult.success("注册成功", segchkUserLevelInfo); + } + + @Override + public String createToke(String subject, Long userId, Long providerId, Integer userLevel) { + String token = createToken(subject, userId, providerId, userLevel); + return token; + } + +// @Override +// @Transactional +// public int registerCustomer(String mobile, String password, String code, String originCode, String recommondCode) { +// logger.debug("registerCustomer and mobile :{} \r\n code:{} \r\n: originCode{} \r\n recommondCode:{}", mobile, code, originCode, recommondCode); +// if() +//// 根据手机号查询是否存在用户。可能是用户,商家,运营商。 +// segchkUserIndexService.getUserLoginInfo(); +// return res; +// } + + private String createToken(String subject, Long userId, Long providerId, int userLevel){ + final StringBuilder sb = new StringBuilder(); + sb.append(Jwts.builder().setSubject(subject) + .compressWith(CompressionCodecs.DEFLATE) + .signWith(SignatureAlgorithm.HS256, jwtSecretKey) + .setIssuedAt(new Date()) + .claim("userId", userId) + .claim("providerId", providerId) + .claim("userLevel", userLevel) + .setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) // 有效期1小时 + .compact()); +// sb.append(CommonConstant.APPLET_LOGIN_KEY).append("_").append(snowflakeIdWorker.nextId()).append(jwtSecretKey); + return sb.toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceImpl.java new file mode 100644 index 0000000..c2930f5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/RegisterServiceImpl.java @@ -0,0 +1,221 @@ +package com.ruoyi.member.service.impl; + + +import com.ruoyi.member.service.RegisterService; +import com.ruoyi.member.service.SmsService; +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.util.StringUtils; + +import java.util.Objects; +import java.util.function.Consumer; + +/** + * Created by 魔金商城 on 17/11/18. + * 注册接口 + */ +@Service +public class RegisterServiceImpl implements RegisterService { + + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(RegisterServiceImpl.class); + + + /** + * 注入短信接口 + */ + @Autowired + private SmsService smsService; + + + /** + * 短信测试标志,true/false + */ + @Value("${yzytest.login.smstest}") + private Boolean smstest; + + /** + * 注入会员服务接口 + */ +// @Autowired +// private IUmsMemberService customerService; + + + @Override + public int sendRegisterSmsCode(String mobile, Consumer consumer) { + + logger.debug("sendRegisterSmsCode and mobile:{}"); + // 如果要注册的手机号码存在 则直接返回 + /*if (customerService.isMobileExist(mobile) != 0) { + logger.error("sendRegisterSmsCode fail due to mobile :{} is exist...", mobile); + return -1; + }*/ + + // 生成的6位数数字 + String code = String.format("%06d", (int) (Math.random() * 1000000)); + + + if(true){ + code = "1234"; + } + else if (smsService.sendSms(mobile, code) == 1) { + // 短信验证码发送失败 + logger.error("send sms fail...."); + return 1; + } + // 发送成功后回调 + if (Objects.nonNull(consumer)) { + consumer.accept(code); + } + + return 0; + } + + /** + * 发送注册短信验证码 + * + * @param mobile 手机号码 + * @param consumer 回调接口 + * @return 0 成功 1 失败 -1 手机号码已经存在 + */ + @Override + public int sendRegisterSmsCodeFortest(String mobile, Consumer consumer) { + logger.debug("sendRegisterSmsCodeFortest and mobile:{}"); + // 如果要注册的手机号码存在 则直接返回 + /*if (customerService.isMobileExist(mobile) != 0) { + logger.error("sendRegisterSmsCode fail due to mobile :{} is exist...", mobile); + return -1; + }*/ + + // 生成的6位数数字 + String code = String.format("%06d", (int) (Math.random() * 1000000)); + + logger.warn("sendRegisterSmsCodeFortest smstest: {}", smstest); + if(smstest){ + code = "1234"; + } + else if (smsService.sendSms(mobile, code) == 1) { + // 短信验证码发送失败 + logger.error("send sms fail...."); + return 1; + } + // 发送成功后回调 + if (Objects.nonNull(consumer)) { + consumer.accept(code); + } + + return 0; + } + + @Override + public int sendRegisterSmsCodeForPc(String mobile, String kaptcha, String oldKaptcha, Consumer consumer) { + + logger.debug("sendRegisterSmsCode and mobile:{}"); + + + // 如果要注册的手机号码存在 则直接返回 + /*if (customerService.isMobileExist(mobile) != 0) { + logger.error("sendRegisterSmsCode fail due to mobile :{} is exist...", mobile); + return -4; + }*/ + + int checkKaptchaRes = checkKaptcha(kaptcha, oldKaptcha); + if (checkKaptchaRes != 1) { + logger.error("sendRegisterSmsCode fail due to kaptcha is error..."); + return checkKaptchaRes; + } + + // 生成的6位数数字 + String code = String.format("%06d", (int) (Math.random() * 1000000)); + + // 短信验证码发送失败 + if (smsService.sendSms(mobile, code) == 1) { + logger.error("send sms fail...."); + return 1; + } + + // 发送成功后回调 + if (Objects.nonNull(consumer)) { + consumer.accept(code); + } + + return 0; + } + + @Override + public int registerCustomer(String mobile, String password, String code, String originCode, String recommondCode) { + logger.debug("registerCustomer and mobile :{} \r\n code:{} \r\n: originCode:{} \r\n recommondCode:{}", mobile, code, originCode, recommondCode); + + if (StringUtils.isEmpty(code)) { + logger.error("registerCustomer fail due to code is empty..."); + return -1; + } + + if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) { + logger.error("registerCustomer fail due to mobile or password is empty..."); + return -2; + } + + // 判断手机号码是否存在 + /*if (customerService.isMobileExist(mobile) != 0) { + logger.error("registerCustomer fail due to mobile is exist"); + return -3; + }*/ + + // 校验验证码是否正确TODO + if (!code.equals(originCode)) { + logger.error("registerCustomer fail due to code is error with originCode..."); + return -1; + } + + // 进行会员注册 +// return customerService.(UmsMember.buildAppRegisterCustomer(mobile, password, recommondCode)); + return 1; + } + + /** + * 免密用户自动注册 + * + * @param phoneNo 手机号码 + * @param channelType 渠道类型 + * @return -1 手机验证码错误 -2 参数错误 0 失败 成功>0 -3 手机号码已存在 -10 推荐人不存在 + */ + @Override + public Long unAuthRegister(String phoneNo, String channelType) { + logger.debug("registerCustomer and mobile :{}", phoneNo); + + // 判断手机号码是否存在 + /*if (customerService.isMobileExist(phoneNo) != 0) { + logger.error("registerCustomer fail due to mobile is exist"); + return -3L; + }*/ +// UmsMember customer = UmsMember.buildH5RegisterCustomer(phoneNo, null); +// customer.setChannelType(channelType); + // 进行会员注册 +// return customerService.autoAddCustomer(customer); + return 1L; + } + + @Override + public int checkKaptcha(String kaptcha, String kaptchaInSession) { + logger.debug("register checkKaptcha and kaptcha:{}\r\n kaptchaInSession:{}", kaptcha, kaptchaInSession); + if (StringUtils.isEmpty(kaptchaInSession)) { + logger.error("register checkKaptcha fail:kaptchaInSession is not exist "); + return -1; + } + if (StringUtils.isEmpty(kaptcha)) { + logger.error("register checkKaptcha fail:kaptcha is not exist "); + return -2; + } + if (!kaptcha.equals(kaptchaInSession)) { + logger.error("register checkKaptcha fail:kaptchaInSession is not equal to kaptcha "); + return -3; + } + return 1; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SendTencentSms.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SendTencentSms.java new file mode 100644 index 0000000..9663b74 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SendTencentSms.java @@ -0,0 +1,45 @@ +package com.ruoyi.member.service.impl; + +import com.github.qcloudsms.SmsMultiSender; +import com.github.qcloudsms.SmsResultBase; +import com.github.qcloudsms.SmsSingleSender; +import com.ruoyi.setting.domain.LsSmsSetting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Tencent Cloud Sms Sendsms + * https://cloud.tencent.com/document/product/382/38778 + */ +public class SendTencentSms { + private static final Logger log = LoggerFactory.getLogger(SendTencentSms.class); + /** + * 按模板发送短信 支持单发和群发 + * + * @param smsSet 短信配置 + */ + public static int sendMessage(LsSmsSetting smsSet, String[] params, String phones) { + + String regex = ";"; + String[] phoneNumbers = phones.split(regex); + SmsResultBase result = null; + + try { + log.debug("url:{},phones:{},templateId:{},params:{}", smsSet.getUrl(), phones, smsSet.getTemplateId(), params); + // 是否单发 + if (phoneNumbers.length == 1) { + //APPID getInterfaceUrl + SmsSingleSender ssender = new SmsSingleSender(Integer.parseInt(smsSet.getUrl()), smsSet.getKey()); + result = ssender.sendWithParam("86", phoneNumbers[0], Integer.parseInt(smsSet.getTemplateId()), params, smsSet.getSign(), "", ""); + } else { + SmsMultiSender msender = new SmsMultiSender(Integer.parseInt(smsSet.getUrl()), smsSet.getKey()); + result = msender.sendWithParam("86", phoneNumbers, Integer.parseInt(smsSet.getTemplateId()), params, smsSet.getSign(), "", ""); + } + return 0; + } catch (Exception e) { + log.error("腾讯云短信发送失败,phoneNumbers={},smsSet={}", phoneNumbers, smsSet, e); + return 1; + } + } + +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SmsServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SmsServiceImpl.java new file mode 100644 index 0000000..5b84835 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/SmsServiceImpl.java @@ -0,0 +1,300 @@ +package com.ruoyi.member.service.impl; + + +import com.ruoyi.member.service.SmsService; +import com.ruoyi.setting.domain.LsSmsSetting; +import com.ruoyi.setting.service.ILsSmsSettingService; +import com.ruoyi.util.SmsUtil; +import com.ruoyi.util.WechatUtils; +import com.ruoyi.util.bean.RequestParam; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import 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 java.math.BigDecimal; +import java.util.*; + +/** + * Created by 魔金商城 on 17/11/18. + * 发送短信接口实现 + */ +@Service +public class SmsServiceImpl implements SmsService { + + /** + * 团长审批状态 + */ + private static final String STATUS = "通过"; + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(SmsServiceImpl.class); + /** + * 注入短信设置服务接口 + */ + @Autowired + private ILsSmsSettingService smsSetService; + + /** + * 短信测试标志,true/false + */ + @Value("${yzytest.login.smsplatid}") + private Integer smsplatId; + + @Override + public int sendSms(String phone, String content) { + int result = 1; + logger.debug("sendSms and phone:{} \r\n content:{}", phone, content); + + // SmsSet smsSet = smsSetService.querySmsSet().get(0); + List smsSetList = smsSetService.selectLsSmsSettingList(null); + if (Objects.isNull(smsSetList)) { + logger.error("sendSms fail due to smsSet is null..."); + return result; + } + for (LsSmsSetting smsSet : smsSetList) { + // 阿里云短信 + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getTemplateId()); + requestParam.setTemplateParam("{\"code\":\"" + content + "\"}"); + result = SmsUtil.newSendSms(requestParam); + } + else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[1]; + params[0] = content; + result = SendTencentSms.sendMessage(smsSet, params, phone); + } + else if(smsSet.getId() == smsplatId.longValue() && smsSet.getStatus() && smsSet.getTemplateId().equals("KSD_SMSCODE")){ +// 快速达短信平台发送短信 + List params = new ArrayList(); + params.add(new BasicNameValuePair("Account", smsSet.getKey())); + params.add(new BasicNameValuePair("Password", smsSet.getSecret())); + params.add(new BasicNameValuePair("Mobile", phone)); + params.add(new BasicNameValuePair("Content", smsSet.getSign().replace("content", content))); + params.add(new BasicNameValuePair("Extnum", null)); + params.add(new BasicNameValuePair("Time", null)); + logger.debug("sendsms KSD with: {}", smsSet.toString()); + String smsRet = executeHttpPost(smsSet.getUrl(), params); + if(smsRet.startsWith("SUCCESS")){ + result = 0; + } + else { + logger.error("{} send sms wrong with: {}", smsSet.getTemplateId(), smsRet); + } + } + } + return result; + } + + @Override + public int sendWiteOffCodeSms(String phone, String code, String writeOffCode, String storeName) { + logger.debug("sendWiteOffCodeSms and phone:{} \r\n code:{} \r\n writeOffCode:{} \r\n storeName:{}", phone, code, writeOffCode, storeName); + + List smsSetList = smsSetService.selectLsSmsSettingList(null); + + if (Objects.isNull(smsSetList)) { + logger.error("sendWiteOffCodeSms fail due to smsSet is null..."); + return 0; + } + for (LsSmsSetting smsSet : smsSetList) { + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getWriteoffTemplateId()); + requestParam.setSmsParamString("{\"code\":\"" + code + "\",\"product\":\"\",\"storename\":\"" + storeName + "\",\"writeoffcode\":\"" + writeOffCode + "\"}"); + SmsUtil.newSendSms(requestParam); + } else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[3]; + params[0] = storeName; + params[1] = code; + params[2] = writeOffCode; + SendTencentSms.sendMessage(smsSet, params, phone); + } + } + + return 0; + } + + @Override + public int sendVirtualOrderWiteOffCodeSms(String phone, String code, String writeOffCode, String storeName) { + logger.debug("sendVirtualOrderWiteOffCodeSms and phone :{} \r\n code:{} \r\n writeOffCode:{} \r\n storeName:{}", phone, code, writeOffCode, storeName); + + List smsSetList = smsSetService.selectLsSmsSettingList(null); + + if (Objects.isNull(smsSetList)) { + logger.error("sendVirtualOrderWiteOffCodeSms fail due to smsSet is null..."); + return 0; + } + for (LsSmsSetting smsSet : smsSetList) { + //阿里云短信 + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getVirtualOrderTemplateId()); + requestParam.setSmsParamString("{\"code\":\"" + code + "\",\"product\":\"\",\"storename\":\"" + storeName + "\",\"writeoffcode\":\"" + writeOffCode + "\"}"); + SmsUtil.newSendSmsCommon(requestParam); + } else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[3]; + params[0] = storeName; + params[1] = code; + params[2] = writeOffCode; + SendTencentSms.sendMessage(smsSet, params, phone); + } + } + return 0; + } + + /** + * 发送社区团购审核结果通知短信 + * + * @param phone 手机号码 + * @param submittime 通过时间 + * @return 成功返回0 失败返回1 + */ + @Override + public int sendAuditTemplateOffCodeSms(String phone, String submittime) { + logger.debug("sendAuditTemplateOffCodeSms and phone :{} \r\n submittime:{}", phone, submittime); + List smsSetList = smsSetService.selectLsSmsSettingList(null); + if (Objects.isNull(smsSetList)) { + logger.error("sendAuditTemplateOffCodeSms fail due to smsSet is null..."); + return 0; + } + for (LsSmsSetting smsSet : smsSetList) { + //阿里云短信 + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getAuditTemplateId()); + requestParam.setSmsParamString("{\"submittime\":\"" + submittime + "\",\"product\":\"\",\"status\":\"" + STATUS + "\"}"); + SmsUtil.newSendSmsCommon(requestParam); + } else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[1]; + params[0] = submittime; + SendTencentSms.sendMessage(smsSet, params, phone); + } + } + return 0; + } + + @Override + public int sendCommunityBuySettlementSms(String phone, String communityName, BigDecimal price) { + + logger.debug("sendCommunityBuySettlementSms and communityName :{} \r\n price:{} \r\n phone:{}", communityName, price, phone); + + List smsSetList = smsSetService.selectLsSmsSettingList(null); + + if (Objects.isNull(smsSetList)) { + logger.error("sendCommunityBuySettlementSms fail due to smsSet is null..."); + return 0; + } + for (LsSmsSetting smsSet : smsSetList) { + //阿里云短信 + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getSettlementTemplateId()); + requestParam.setSmsParamString("{\"communityname\":\"" + communityName + "\",\"product\":\"\",\"price\":\"" + price + "\"}"); + SmsUtil.newSendSmsCommon(requestParam); + } else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[2]; + params[0] = communityName; + params[1] = String.valueOf(price); + SendTencentSms.sendMessage(smsSet, params, phone); + } + } + return 0; + } + + @Override + public int sendCommunityBuyWitudrawSms(String phone, String submittime, BigDecimal price) { + + + logger.debug("sendCommunityBuyWitudrawSms and phone :{} \r\n submittime:{} \r\n price:{}", phone, submittime, price); + + List smsSetList = smsSetService.selectLsSmsSettingList(null); + + if (Objects.isNull(smsSetList)) { + logger.error("sendCommunityBuyWitudrawSms fail due to smsSet is null..."); + return 0; + } + for (LsSmsSetting smsSet : smsSetList) { + //阿里云短信 + if (smsSet.getId() == 1 && smsSet.getStatus()) { + RequestParam requestParam = convert(phone, smsSet); + requestParam.setTemplateCode(smsSet.getWithdrawTemplateId()); + requestParam.setSmsParamString("{\"submittime\":\"" + submittime + "\",\"product\":\"\",\"price\":\"" + price + "\"}"); + SmsUtil.newSendSmsCommon(requestParam); + } else if (smsSet.getId() == 2 && smsSet.getStatus()) { // 腾讯云短信 + String[] params = new String[2]; + params[0] = submittime; + params[1] = price.toString(); + SendTencentSms.sendMessage(smsSet, params, phone); + } + } + return 0; + } + + private RequestParam convert(String phone, LsSmsSetting smsSet) { + RequestParam requestParam = new RequestParam(); + requestParam.setPhoneNumbers(phone); + requestParam.setSignName(smsSet.getSign()); + requestParam.setInterfaceUrl(smsSet.getUrl()); + requestParam.setAccessKeyId(smsSet.getKey()); + requestParam.setAccessKeySecret(smsSet.getSecret()); + return requestParam; + } + + /** + * 执行POST方法请求数据 + * + * @param url 请求地址 + * @param params 请求参数 + * @return 返回数据 + */ + private String executeHttpPost(String url, List params) { + logger.debug("executeHttpPost and url:{}", url); + String result = null; + BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + HttpPost httpRequest = new HttpPost(url); + + try { + httpRequest.setEntity(new UrlEncodedFormEntity(params,"UTF-8")); + httpRequest.setHeader("Content-type", "application/x-www-form-urlencoded"); + //使用DefaultHttpClient类的execute方法发送HTTP GET请求,并返回HttpResponse对象。 + HttpResponse httpResponse = httpClient.execute(httpRequest);//其中HttpGet是HttpUriRequst的子类 + HttpEntity httpEntity = httpResponse.getEntity(); + result = EntityUtils.toString(httpEntity, "UTF-8");//取出应答字符串 + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatAppletLoginServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatAppletLoginServiceImpl.java new file mode 100644 index 0000000..a04561e --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatAppletLoginServiceImpl.java @@ -0,0 +1,179 @@ +package com.ruoyi.member.service.impl; + +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SnowflakeIdWorker; +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import com.ruoyi.util.*; +import com.ruoyi.member.service.WeChatAppletLoginService; +import com.ruoyi.member.service.WeChatCustomerLinkService; +import com.ruoyi.member.vo.AppletLoginInfo; +import com.ruoyi.member.vo.AppletLoginRedisParamResponse; +import com.ruoyi.setting.bean.WechatPaySet; +import com.ruoyi.setting.service.ILsPaySettingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.util.Objects; +import java.util.function.Consumer; + +/** + * 微信小程序登录服务实现类 + * + * @author SK + * @since 2018/6/13 + */ +@Service +public class WeChatAppletLoginServiceImpl implements WeChatAppletLoginService { + /** + * 日志 + */ + private Logger log = LoggerFactory.getLogger(WeChatAppletLoginServiceImpl.class); + /** + * 注入微信用户关联服务 + */ + @Autowired + private WeChatCustomerLinkService weChatCustomerLinkService; + + /** + * 注入随机数生成器 + */ + @Autowired + private SnowflakeIdWorker snowflakeIdWorker; + + /** + * 注入支付设置服务 + */ + @Autowired + private ILsPaySettingService paySetService; + + + @Override + public AppletLoginInfo getLoginInfo(String code, String unionId, Consumer claimsConsumer) { + log.debug("getLoginInfo and code:{} \r\n unionId:{}", code, unionId); + AppletLoginRedisParamResponse appletLoginRedisParamResponse = new AppletLoginRedisParamResponse(); + String token = snowflakeIdWorker.nextId() + ""; + appletLoginRedisParamResponse.setToken(token); + WechatPaySet wechatAppletPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + WechatSetting wechatSetting = new WechatSetting(); + wechatSetting.setAppId(wechatAppletPaySet.getAppId()); + wechatSetting.setAppSecret(wechatAppletPaySet.getAppSecret()); + if (!wechatSetting.checkAppletOAuthParams()) { + log.error("getLoginInfo fail:checkAppletOAuthParams fail"); + return buildNotLinked(claimsConsumer, appletLoginRedisParamResponse, token, null); + } + WeChatAppletLoginResponse weChatAppletLoginResponse = WeChatAppletUtils.getLoginInfo(code, wechatSetting); + if (Objects.isNull(weChatAppletLoginResponse)) { + log.error("getLoginInfo fail: getLoginInfo fail"); + return buildNotLinked(claimsConsumer, appletLoginRedisParamResponse, token, null); + } + appletLoginRedisParamResponse.setSessionKey(weChatAppletLoginResponse.getSession_key()); + appletLoginRedisParamResponse.setOpenId(weChatAppletLoginResponse.getOpenid()); + if (!weChatAppletLoginResponse.hasUnionId()) { + weChatAppletLoginResponse.setUnionid(unionId); + } + if (!weChatAppletLoginResponse.hasUnionId()) { + log.info("getLoginInfo: no unionId"); + return buildNotLinked(claimsConsumer, appletLoginRedisParamResponse, token, null); + } + appletLoginRedisParamResponse.setUnionId(weChatAppletLoginResponse.getUnionid()); + WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByUnionId(weChatAppletLoginResponse.getUnionid()); + if (Objects.isNull(weChatCustomerLink)) { + log.info("getLoginInfo: not linked"); + return buildNotLinked(claimsConsumer, appletLoginRedisParamResponse, token, weChatAppletLoginResponse.getUnionid()); + } + log.info("getLoginInfo: linked"); + //如果没有小程序的openId,则更新关联信息 + if (!weChatCustomerLink.hasAppletOpenId()) { + weChatCustomerLink.setAppletOpenId(weChatAppletLoginResponse.getOpenid()); + weChatCustomerLinkService.updateWeChatCustomerLink(weChatCustomerLink); + } + appletLoginRedisParamResponse.setCustomerId(weChatCustomerLink.getUserId()); + claimsConsumer.accept(appletLoginRedisParamResponse); + return AppletLoginInfo.buildLinked(token); + } + + + @Override + public AppletLoginInfo dealUserInfo(WeChatAppletUserInfo weChatAppletUserInfo, String openId, String sessionKey, Consumer claimsConsumer) { + log.debug("dealUserInfo and weChatAppletUserInfo:{} \r\n sessionKey:{} \r\n openId:{}", weChatAppletUserInfo, sessionKey, openId); + String unionId = WeChatAppletUtils.getUnionIdFromUserInfo(sessionKey, weChatAppletUserInfo); + if (StringUtils.isEmpty(unionId)) { + log.error("dealUserInfo fail : getUnionIdFromUserInfo fail"); + claimsConsumer.accept(null); + return AppletLoginInfo.buildNotLinked(); + } + AppletLoginRedisParamResponse appletLoginRedisParamResponse = new AppletLoginRedisParamResponse(); + appletLoginRedisParamResponse.setUnionId(unionId); + WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByUnionId(unionId); + if (Objects.isNull(weChatCustomerLink)) { + log.info("dealUserInfo: not linked"); + claimsConsumer.accept(appletLoginRedisParamResponse); + return AppletLoginInfo.buildNotLinked().addUnionId(unionId); + } + log.info("dealUserInfo: linked"); + //如果没有小程序的openId,则更新关联信息 + if (!weChatCustomerLink.hasAppletOpenId()) { + weChatCustomerLink.setAppletOpenId(openId); + weChatCustomerLinkService.updateWeChatCustomerLink(weChatCustomerLink); + } + appletLoginRedisParamResponse.setCustomerId(weChatCustomerLink.getUserId()); + claimsConsumer.accept(appletLoginRedisParamResponse); + return AppletLoginInfo.buildLinked(); + } + + @Override + public int checkCustomerBind(String userName) { + log.debug("checkCustomerBind and userName:{} ", userName); + WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByUserName(userName); + if (!ObjectUtils.isEmpty(weChatCustomerLink) && !StringUtils.isEmpty(weChatCustomerLink.getAppletOpenId())) { + log.error("checkCustomerBind fail : bind already"); + return -9; + } + return 1; + } + + @Override + public int bindAccount(String openId, String unionId, long customerId) { + log.debug("bindAccount and openId:{} \r\n unionId:{} \r\n customerId:{}", openId, unionId, customerId); + WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByCustomerId(customerId); + if (!ObjectUtils.isEmpty(weChatCustomerLink) && !weChatCustomerLink.getUnionId().equals(unionId)) { + log.error("checkCustomerBind fail : bind already"); + throw new ServiceException("R-00004"); + } + if (Objects.isNull(weChatCustomerLink)) { + weChatCustomerLink = new WeChatCustomerLink(); + } + weChatCustomerLink.setUnionId(unionId); + weChatCustomerLink.setAppletOpenId(openId); + weChatCustomerLink.setUserId(customerId); + //如果数据库中有记录就更新记录 + if (-1 != weChatCustomerLink.getUserId()) { + return weChatCustomerLinkService.updateWeChatCustomerLink(weChatCustomerLink); + } + //否则新增 + return weChatCustomerLinkService.addWeChatCustomerLink(weChatCustomerLink); + } + + @Override + public int unbindAccount(long customerId, String unionId) { + log.debug("unbindAccount and customerId:{} \r\n unionId:{}", customerId, unionId); + return weChatCustomerLinkService.unbindWeChatCustomerLink(customerId, unionId); + } + + /** + * 构建未关联返回 + * + * @param claimsConsumer 回调 + * @param appletLoginRedisParamResponse 小程序redis参数返回实体类 + * @param token token + * @return 小程序登录信息 + */ + private AppletLoginInfo buildNotLinked(Consumer claimsConsumer, AppletLoginRedisParamResponse appletLoginRedisParamResponse, String token, String unionId) { + claimsConsumer.accept(appletLoginRedisParamResponse); + return AppletLoginInfo.buildNotLinked(token).addUnionId(unionId); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatCustomerLinkServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatCustomerLinkServiceImpl.java new file mode 100644 index 0000000..3699eda --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/service/impl/WeChatCustomerLinkServiceImpl.java @@ -0,0 +1,138 @@ +package com.ruoyi.member.service.impl; + + +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.segchk.service.ISegchkUserIndexService; +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import com.ruoyi.member.mapper.WeChatCustomerLinkMapper; +import com.ruoyi.member.service.WeChatCustomerLinkService; +import com.ruoyi.common.utils.RedisCahceKey; +import com.ruoyi.util.Claims; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +/** + * 微信用户关联服务实现类 + */ +@Service +public class WeChatCustomerLinkServiceImpl implements WeChatCustomerLinkService { + + /** + * 日志 + */ + private Logger logger = LoggerFactory.getLogger(WeChatCustomerLinkServiceImpl.class); + /** + * 注入微信用户数据库服务 + */ + @Autowired + private WeChatCustomerLinkMapper weChatCustomerLinkMapper; + /** + * 用户数据库服务 + */ + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + + /** + * 注入用户服务 + */ +// @Autowired +// private IUmsMemberService customerService; + + + @CacheEvict(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#weChatCustomerLink.unionId") + @Override + public int addWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink) { + logger.debug("addWeChatCustomerLink and weChatCustomerLink:{}", weChatCustomerLink); + return weChatCustomerLinkMapper.addWeChatCustomerLink(weChatCustomerLink); + } + + @Override + public WeChatCustomerLink queryWeChatCustomerLinkByOpenId(String openId) { + logger.debug("queryWeChatCustomerLinkByOpenId and openId:{}", openId); + return weChatCustomerLinkMapper.queryWeChatCustomerLinkByOpenId(openId); + } + + @Override + public WeChatCustomerLink queryWeChatCustomerLinkByCustomerId(long customerId) { + logger.debug("queryWeChatCustomerLinkByCustomerId and customerId:{}", customerId); + return weChatCustomerLinkMapper.queryWeChatCustomerLinkByCustomerId(customerId); + } + + @Override + public WeChatCustomerLink queryWeChatCustomerLinkByUserName(String userName) { + logger.debug("queryWeChatCustomerLinkByUserName and userName:{}", userName); +// UmsMember customer = null; +// UmsMember customer = customerService.queryCustomerByNameInWriteDataSource(userName); + /*if (ObjectUtils.isEmpty(customer)) { + logger.error("queryWeChatCustomerLinkByUserName fail: member is null"); + return null; + }*/ + return null; +// return weChatCustomerLinkMapper.queryWeChatCustomerLinkByCustomerId(customer.getCustomerLevelId()); + } + + @Cacheable(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#unionId") + @Override + public WeChatCustomerLink queryWeChatCustomerLinkByUnionId(String unionId) { + logger.debug("queryWeChatCustomerLinkByUnionId and unionId:{}", unionId); + return weChatCustomerLinkMapper.queryWeChatCustomerLinkByUnionId(unionId); + } + + @CacheEvict(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#unionId") + @Override + public int unbindWeChatCustomerLink(long customerId, String unionId) { + logger.debug("unbindWeChatCustomerLink and customerId:{} \r\n unionId:{}", customerId, unionId); + return weChatCustomerLinkMapper.deleteWeChatCustomerLink(customerId); + } + + @CacheEvict(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#weChatCustomerLink.unionId") + @Override + public int updateWeChatCustomerLink(WeChatCustomerLink weChatCustomerLink) { + logger.debug("updateWeChatCustomerLink andweChatCustomerLink:{}", weChatCustomerLink); + return weChatCustomerLinkMapper.updateWeChatCustomerLink(weChatCustomerLink); + } + + /** + * 更新微信用户关联 + * + * @param segchkUserWechat 微信用户关联实体 + * @param userLevel + * @return 1成功 否则失败 + */ + @Override + public int addSegchkUserWechat(SegchkUserWechat segchkUserWechat, String userLevel) { + return segchkUserIndexService.updateWeChatInfoByUserId(segchkUserWechat, userLevel); + } + + /** + * 更新微信用户关联 + * + * @param segchkUserWechat 微信用户关联实体 + * @param userLevel + * @return 1成功 否则失败 + */ + @CacheEvict(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#token") + @Override + public int addSegchkUserWechat(SegchkUserWechat segchkUserWechat, String userLevel, String token) { + return segchkUserIndexService.updateWeChatInfoByUserId(segchkUserWechat, userLevel); + } + + /** + * 获取微信用户关联 + * + * @param claims 微信用户关联实体 + * @param token + * @return 1成功 否则失败 + */ + @Cacheable(value = RedisCahceKey.WE_CHAT_CUSTOMER_LINK, key = "'WE_CHAT_CUSTOMER_LINK'+#token") + @Override + public SegchkUserWechat getSegchkUserWechat(Claims claims, String token) { + return segchkUserIndexService.queryWeChatInfoByUserId(claims); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginInfo.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginInfo.java new file mode 100644 index 0000000..f1d795a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginInfo.java @@ -0,0 +1,129 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * 小程序登录信息 + * + * @author SK + * @since 2018/6/13 + */ +@ApiModel(description = "小程序登录信息") +public class AppletLoginInfo { + + /** + * token + */ + @ApiModelProperty(value = "token") + private String token; + + /** + * 是否关联用户 + */ + @ApiModelProperty(value = "是否关联用户") + private boolean isLink; + + /** + * 是否有unionId + */ + @ApiModelProperty(value = "是否有unionId") + private boolean hasUnionId; + + + /** + * 构建已关联用户实体 + * + * @param token token + * @return 小程序登录信息实体 + */ + public static AppletLoginInfo buildLinked(String token) { + AppletLoginInfo appletLoginInfo = new AppletLoginInfo(); + appletLoginInfo.isLink = true; + appletLoginInfo.token = token; + appletLoginInfo.hasUnionId = true; + return appletLoginInfo; + } + + /** + * 构建为关联用户实体 + * + * @param token token + * @return 小程序登录信息实体 + */ + public static AppletLoginInfo buildNotLinked(String token) { + AppletLoginInfo appletLoginInfo = new AppletLoginInfo(); + appletLoginInfo.isLink = false; + appletLoginInfo.token = token; + return appletLoginInfo; + } + + + /** + * 构建已关联用户实体 + * + * @return 小程序登录信息实体 + */ + public static AppletLoginInfo buildLinked() { + AppletLoginInfo appletLoginInfo = new AppletLoginInfo(); + appletLoginInfo.isLink = true; + appletLoginInfo.hasUnionId = true; + return appletLoginInfo; + } + + /** + * 构建为关联用户实体 + * + * @return 小程序登录信息实体 + */ + public static AppletLoginInfo buildNotLinked() { + AppletLoginInfo appletLoginInfo = new AppletLoginInfo(); + appletLoginInfo.isLink = false; + return appletLoginInfo; + } + + /** + * 添加unionId + * + * @param unionId 联合登录id + * @return 当前实体 + */ + public AppletLoginInfo addUnionId(String unionId) { + hasUnionId = !StringUtils.isEmpty(unionId); + return this; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public boolean isLink() { + return isLink; + } + + public void setLink(boolean link) { + isLink = link; + } + + public boolean isHasUnionId() { + return hasUnionId; + } + + public void setHasUnionId(boolean hasUnionId) { + this.hasUnionId = hasUnionId; + } + + @Override + public String toString() { + return "AppletLoginInfo{" + + "token='" + token + '\'' + + ", isLink=" + isLink + + ", hasUnionId=" + hasUnionId + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginRedisParamResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginRedisParamResponse.java new file mode 100644 index 0000000..98f5ac5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/AppletLoginRedisParamResponse.java @@ -0,0 +1,96 @@ +package com.ruoyi.member.vo; + +import org.springframework.util.StringUtils; + +/** + * 小程序redis参数返回实体类 + * + * @author SK + * @since 2018/6/13 + */ +public class AppletLoginRedisParamResponse { + + /** + * 小程序sessionKey + */ + private String sessionKey; + + /** + * token + */ + private String token; + + /** + * 联合登录id + */ + private String unionId; + + /** + * 用户id + */ + private long customerId = -1; + + /** + * 微信用户标识 + */ + private String openId; + + private String code; + + /** + * 判断是否有unionId + * + * @return 有返回true, 否则返回false + */ + public boolean hasUnionId() { + return !StringUtils.isEmpty(unionId); + } + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUnionId() { + return unionId; + } + + public void setUnionId(String unionId) { + this.unionId = unionId; + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewEmailRequest.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewEmailRequest.java new file mode 100644 index 0000000..430348b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewEmailRequest.java @@ -0,0 +1,133 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * 绑定新邮箱实体 + */ +@ApiModel(description = "绑定新邮箱实体") +public class BindNewEmailRequest { + + /** + * 用户id + */ + @ApiModelProperty(value = "用户id") + private long customerId; + + /** + * 用户手机 + */ + @ApiModelProperty(value = "用户手机") + private String mobile; + + /** + * 新邮箱 + */ + @ApiModelProperty(value = "新邮箱") + private String email; + + /** + * 是否有凭证 + */ + @ApiModelProperty(value = "是否有凭证") + private String hasCert; + + /** + * 校验码 + */ + @ApiModelProperty(value = "校验码") + private String checkCode; + + /** + * 用户输入的图片验证码 + */ + @ApiModelProperty(value = "用户输入的图片验证码") + private String kaptcha; + + /** + * 存在redis中的图片验证码 + */ + @ApiModelProperty(value = "存在redis中的图片验证码") + private String oldKaptcha; + + /** + * 随机数 + */ + @ApiModelProperty(value = "随机数") + private String uuid; + + /** + * 判断是否有凭证 + * + * @return 有返回true + */ + public boolean hasOwnCert() { + return !StringUtils.isEmpty(this.hasCert); + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getHasCert() { + return hasCert; + } + + public void setHasCert(String hasCert) { + this.hasCert = hasCert; + } + + public String getCheckCode() { + return checkCode; + } + + public void setCheckCode(String checkCode) { + this.checkCode = checkCode; + } + + public String getKaptcha() { + return kaptcha; + } + + public void setKaptcha(String kaptcha) { + this.kaptcha = kaptcha; + } + + public String getOldKaptcha() { + return oldKaptcha; + } + + public void setOldKaptcha(String oldKaptcha) { + this.oldKaptcha = oldKaptcha; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewMobileRequest.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewMobileRequest.java new file mode 100644 index 0000000..7d4e57f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindNewMobileRequest.java @@ -0,0 +1,105 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * Created by 魔金商城 on 17/11/21. + * 重新绑定手机号码实体 + */ +@ApiModel(description = "重新绑定手机号码实体") +public class BindNewMobileRequest { + + /** + * 用户id + */ + @ApiModelProperty(value = "用户id") + private long customerId; + + /** + * 重新绑定的手机号码 + */ + @ApiModelProperty(value = "重新绑定的手机号码") + private String mobile; + + /** + * 用户输入的验证码 + */ + @ApiModelProperty(value = "用户输入的验证码") + private String code; + + /** + * 发送给手机的验证码 + */ + @ApiModelProperty(value = "发送给手机的验证码") + private String originCode; + + /** + * 是否有凭证 + */ + @ApiModelProperty(value = "是否有凭证") + private String hasCert; + + /** + * 判断是否有凭证 + * + * @return 有返回true + */ + public boolean hasOwnCert() { + return !StringUtils.isEmpty(this.hasCert); + } + + /** + * 判断验证码是否正确 + * + * @return 正确返回0 + */ + public boolean validateCode() { + if (StringUtils.isEmpty(this.code)) { + return false; + } + + return this.code.equals(this.originCode); + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getOriginCode() { + return originCode; + } + + public void setOriginCode(String originCode) { + this.originCode = originCode; + } + + public String getHasCert() { + return hasCert; + } + + public void setHasCert(String hasCert) { + this.hasCert = hasCert; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindParams.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindParams.java new file mode 100644 index 0000000..a5ec429 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/BindParams.java @@ -0,0 +1,139 @@ +package com.ruoyi.member.vo; + +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.function.Consumer; + + +/** + * 登入参数实体 + */ +@ApiModel(description = "登入参数实体") +public class BindParams extends BaseEntity { + + /** + * 用户id + */ + @ApiModelProperty(value = "用户id") + private String userId; + + /** + * 运营商id + */ + @ApiModelProperty(value = "运营商id") + private String providerId; + + /** + * 用户角色 + */ + @ApiModelProperty(value = "用户角色") + private String userLevel; + + + /** + * 授权code + */ + @ApiModelProperty(value = "授权code") + private String code; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称") + private String nickName; + + /** + * 头像 + */ + @ApiModelProperty(value = "头像") + private String avatar; + + /** + * getUserProfile返回 + */ + @ApiModelProperty(value = "getUserProfile返回") + private String profileRes; + + + /** + * 验证验证码 是否正确 (目前都不需要验证码) + * + * @return 正确返回true 否则返回false + */ + public boolean validateCode() { + + // 目前都不需要验证码 + return true; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getUserLevel() { + return userLevel; + } + + public void setUserLevel(String userLevel) { + this.userLevel = userLevel; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getProfileRes() { + return profileRes; + } + + public void setProfileRes(String profileRes) { + this.profileRes = profileRes; + } + + @Override + public String toString() { + return "BindParams{" + + "userId='" + userId + '\'' + + ", providerId='" + providerId + '\'' + + ", userLevel='" + userLevel + '\'' + + ", code='" + code + '\'' + + ", nickName='" + nickName + '\'' + + ", avatar='" + avatar + '\'' + + ", profileRes='" + profileRes + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/CustomerSearchCondition.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/CustomerSearchCondition.java new file mode 100644 index 0000000..b862df8 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/CustomerSearchCondition.java @@ -0,0 +1,178 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by 魔金商城 on 17/5/19. + * 会员搜索条件 + */ +@ApiModel(description = "会员搜索条件") +public class CustomerSearchCondition { + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名") + private String userName; + + /** + * 用户的真实姓名 + */ + @ApiModelProperty(value = "用户的真实姓名") + private String releName; + + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码") + private String mobile; + + /** + * 邮箱 + */ + @ApiModelProperty(value = "邮箱") + private String email; + + /** + * 手机是否验证 0 否 1 验证 默认0 + */ + @ApiModelProperty(value = "手机是否验证 0 否 1 验证 默认0") + private String isMobileVerification; + + /** + * 邮箱是否验证 0 否 1 验证 默认0 + */ + @ApiModelProperty(value = "邮箱是否验证 0 否 1 验证 默认0") + private String isEmailVerification; + + /** + * 用户状态 1 正常 2 冻结 默认1 + */ + @ApiModelProperty(value = "用户状态 1 正常 2 冻结 默认1") + private String status; + + + /** + * 1 普通用户 2 商家店铺用户 + */ + @ApiModelProperty(value = "1 普通用户 2 商家店铺用户") + private String type; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private String createTime; + + /** + * 归属门店id + */ + @ApiModelProperty(value = "归属门店id") + private long beloneStoreId; + + + /** + * 获得搜索条件 + * + * @return 返回搜索套件 + */ + public Map getSearchParams() { + Map params = new HashMap<>(); + params.put("userName", userName); + params.put("releName", releName); + params.put("mobile", mobile); + params.put("email", email); + params.put("isMobileVerification", isMobileVerification); + params.put("isEmailVerification", isEmailVerification); + params.put("status", status); + params.put("type", type); + params.put("createTime", createTime); + params.put("beloneStoreId", beloneStoreId); + return params; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getReleName() { + return releName; + } + + public void setReleName(String releName) { + this.releName = releName; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getIsMobileVerification() { + return isMobileVerification; + } + + public void setIsMobileVerification(String isMobileVerification) { + this.isMobileVerification = isMobileVerification; + } + + public String getIsEmailVerification() { + return isEmailVerification; + } + + public void setIsEmailVerification(String isEmailVerification) { + this.isEmailVerification = isEmailVerification; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public long getBeloneStoreId() { + return beloneStoreId; + } + + public void setBeloneStoreId(long beloneStoreId) { + this.beloneStoreId = beloneStoreId; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/ForgetPwdRequest.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/ForgetPwdRequest.java new file mode 100644 index 0000000..2be9550 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/ForgetPwdRequest.java @@ -0,0 +1,174 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * Created by 魔金商城 on 17/11/22. + * 忘记密码请求 + */ +@ApiModel(description = "忘记密码请求") +public class ForgetPwdRequest { + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码") + private String mobile; + + /** + * 验证码 + */ + @ApiModelProperty(value = "验证码") + private String code; + + /** + * 发送给手机的验证码 + */ + @ApiModelProperty(value = "发送给手机的验证码") + private String originCode; + + /** + * 凭证 + */ + @ApiModelProperty(value = "凭证") + private String certificate; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 随机数 + */ + @ApiModelProperty(value = "随机数") + private String uuid; + + /** + * 请求来自 1:pc + */ + @ApiModelProperty(value = "请求来自 1:pc") + private String requestFrom; + + /** + * 用户输入的图片验证码 + */ + @ApiModelProperty(value = "用户输入的图片验证码") + private String kaptcha; + + /** + * 存在redis中的图片验证码 + */ + @ApiModelProperty(value = "存在redis中的图片验证码") + private String oldKaptcha; + + /** + * 随机数(pc端图片验证码用) + */ + @ApiModelProperty(value = "随机数(pc端图片验证码用)") + private String uuidForPcKaptcha; + + /** + * 是否有凭证 + * + * @return 有返回true + */ + public boolean hasCertificate() { + return !StringUtils.isEmpty(certificate); + } + + /** + * 判断验证码是否正确 + * + * @return 正确返回true + */ + public boolean validateCode() { + if (StringUtils.isEmpty(this.code)) { + return false; + } + return this.code.equals(this.originCode); + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getOriginCode() { + return originCode; + } + + public void setOriginCode(String originCode) { + this.originCode = originCode; + } + + public String getCertificate() { + return certificate; + } + + public void setCertificate(String certificate) { + this.certificate = certificate; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getRequestFrom() { + return requestFrom; + } + + public void setRequestFrom(String requestFrom) { + this.requestFrom = requestFrom; + } + + public String getKaptcha() { + return kaptcha; + } + + public void setKaptcha(String kaptcha) { + this.kaptcha = kaptcha; + } + + public String getOldKaptcha() { + return oldKaptcha; + } + + public void setOldKaptcha(String oldKaptcha) { + this.oldKaptcha = oldKaptcha; + } + + public String getUuidForPcKaptcha() { + return uuidForPcKaptcha; + } + + public void setUuidForPcKaptcha(String uuidForPcKaptcha) { + this.uuidForPcKaptcha = uuidForPcKaptcha; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/LoginParams.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/LoginParams.java new file mode 100644 index 0000000..48a9065 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/LoginParams.java @@ -0,0 +1,113 @@ +package com.ruoyi.member.vo; + +import com.ruoyi.segchk.domain.SegchkUserBasicInfo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.function.Consumer; + + +/** + * 登入参数实体 + */ +@ApiModel(description = "登入参数实体") +public class LoginParams { + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名") + private String mobile; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 回调函数 + */ + @ApiModelProperty(value = "回调函数") + private Consumer consumer; + + /** + * 用户输入的验证码 + */ + @ApiModelProperty(value = "用户输入的验证码") + private String code; + + /** + * session中的验证码 + */ + @ApiModelProperty(value = "session中的验证码") + private String codeInSession; + + /** + * 登录来源 0 pc 1 app 2 mobile + */ + private int source; + + public void setFromApp() { + this.source = 1; + } + + /** + * 验证验证码 是否正确 (目前都不需要验证码) + * + * @return 正确返回true 否则返回false + */ + public boolean validateCode() { + + // 目前都不需要验证码 + return true; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Consumer getConsumer() { + return consumer; + } + + public void setConsumer(Consumer consumer) { + this.consumer = consumer; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getCodeInSession() { + return codeInSession; + } + + public void setCodeInSession(String codeInSession) { + this.codeInSession = codeInSession; + } + + public int getSource() { + return source; + } + + public void setSource(int source) { + this.source = source; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/QueryCriteria.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/QueryCriteria.java new file mode 100644 index 0000000..370e0d7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/QueryCriteria.java @@ -0,0 +1,125 @@ +package com.ruoyi.member.vo; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.HashMap; +import java.util.Map; + +/** + * 会员预存款查询条件 + */ +@ApiModel(description = "会员预存款查询条件") +public class QueryCriteria { + + /** + * 会员id + */ + @ApiModelProperty(value = "会员id") + private long customerId; + + private int pageNum =0; + /** + * 会员名称 + */ + @ApiModelProperty(value = "会员名称") + private String userName; + + /** + * 交易单号 + */ + @ApiModelProperty(value = "交易单号") + private String transCode; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private String startTime; + + /** + * 结束时间 + */ + @ApiModelProperty(value = "结束时间") + private String endTime; + + /** + * 查询类型 1全部 2 收入 3支出 默认全部 + */ + @ApiModelProperty(value = "查询类型 1全部 2 收入 3支出 默认全部") + private String filterType = "1"; + + /** + * 获得查询条件 + * + * @return 返回查询条件 + */ + public Map getQueryMap() { + Map params = new HashMap<>(); + params.put("customerId", customerId); + params.put("userName", userName); + params.put("transCode", transCode); + params.put("startTime", startTime); + params.put("endTime", endTime); + params.put("filterType", filterType); + params.put("pageNum", pageNum); + return params; + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public int getPageNum() { + return pageNum; + } + + public void setPageNum(int pageNum) { + this.pageNum = pageNum; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getTransCode() { + return transCode; + } + + public void setTransCode(String transCode) { + this.transCode = transCode; + } + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public String getFilterType() { + return filterType; + } + + public void setFilterType(String filterType) { + this.filterType = filterType; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UnAuthLoginParams.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UnAuthLoginParams.java new file mode 100644 index 0000000..3eadbdc --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UnAuthLoginParams.java @@ -0,0 +1,79 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.function.Consumer; + +/** + * 免密登入参数实体 + */ +@ApiModel(description = "免密登入参数实体") +public class UnAuthLoginParams { + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号") + private String phoneNo; + /** + * 时间戳 + */ + @ApiModelProperty(value = "时间戳") + private Long timeStamp; + /** + * 请求签名 + */ + @ApiModelProperty(value = "请求签名") + private String sign; + + /** + * 渠道类型 + */ + @ApiModelProperty(value = "渠道类型") + private String channelType; + /** + * 回调函数 + */ + private Consumer consumer; + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public Long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(Long timeStamp) { + this.timeStamp = timeStamp; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getChannelType() { + return channelType; + } + + public void setChannelType(String channelType) { + this.channelType = channelType; + } + + public Consumer getConsumer() { + return consumer; + } + + public void setConsumer(Consumer consumer) { + this.consumer = consumer; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePayPwdBean.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePayPwdBean.java new file mode 100644 index 0000000..a995915 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePayPwdBean.java @@ -0,0 +1,173 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * Created by 魔金商城 on 17/11/20. + * 修改支付密码实体 + */ +@ApiModel(description = "修改支付密码实体") +public class UpdatePayPwdBean { + + /** + * 会员id + */ + @ApiModelProperty(value = "会员id") + private long customerId; + + /** + * 用户输入的手机验证码 + */ + @ApiModelProperty(value = "用户输入的手机验证码") + private String code; + + /** + * 存起来的手机验证码 + */ + @ApiModelProperty(value = "存起来的手机验证码") + private String originCode; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码") + private String mobile; + + + /** + * 凭证 + */ + @ApiModelProperty(value = "凭证") + private String certificate; + + /** + * 请求来自 1:pc + */ + @ApiModelProperty(value = "请求来自 1:pc") + private String requestFrom; + + /** + * 用户输入的图片验证码 + */ + @ApiModelProperty(value = "用户输入的图片验证码") + private String kaptcha; + + /** + * 存在redis中的图片验证码 + */ + @ApiModelProperty(value = "存在redis中的图片验证码") + private String oldKaptcha; + + /** + * 随机数 + */ + @ApiModelProperty(value = "随机数") + private String uuid; + + + /** + * 是否有凭证 + * + * @return 有返回true + */ + public boolean hasCertificate() { + return !StringUtils.isEmpty(certificate); + } + + /** + * 校验用户输入的验证码是否正确 + * + * @return 正确返回true + */ + public boolean validateCode() { + return StringUtils.isEmpty(this.code) ? false : this.code.equals(this.originCode); + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getOriginCode() { + return originCode; + } + + public void setOriginCode(String originCode) { + this.originCode = originCode; + } + + 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; + } + + public String getCertificate() { + return certificate; + } + + public void setCertificate(String certificate) { + this.certificate = certificate; + } + + public String getRequestFrom() { + return requestFrom; + } + + public void setRequestFrom(String requestFrom) { + this.requestFrom = requestFrom; + } + + public String getKaptcha() { + return kaptcha; + } + + public void setKaptcha(String kaptcha) { + this.kaptcha = kaptcha; + } + + public String getOldKaptcha() { + return oldKaptcha; + } + + public void setOldKaptcha(String oldKaptcha) { + this.oldKaptcha = oldKaptcha; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePwdBean.java b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePwdBean.java new file mode 100644 index 0000000..1d71b98 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/member/vo/UpdatePwdBean.java @@ -0,0 +1,172 @@ +package com.ruoyi.member.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.StringUtils; + +/** + * Created by 魔金商城 on 17/11/20. + * 修改密码实体 + */ +@ApiModel(description = "修改密码实体") +public class UpdatePwdBean { + + /** + * 会员id + */ + @ApiModelProperty(value = "会员id") + private long customerId; + + /** + * 用户输入的手机验证码 + */ + @ApiModelProperty(value = "用户输入的手机验证码") + private String code; + + /** + * 存起来的手机验证码 + */ + @ApiModelProperty(value = "存起来的手机验证码") + private String originCode; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码") + private String mobile; + + /** + * 凭证 + */ + @ApiModelProperty(value = "凭证") + private String certificate; + + /** + * 请求来自 1:pc + */ + @ApiModelProperty(value = "请求来自 1:pc") + private String requestFrom; + + /** + * 用户输入的图片验证码 + */ + @ApiModelProperty(value = "用户输入的图片验证码") + private String kaptcha; + + /** + * 存在redis中的图片验证码 + */ + @ApiModelProperty(value = "存在redis中的图片验证码") + private String oldKaptcha; + + /** + * 随机数 + */ + @ApiModelProperty(value = "随机数") + private String uuid; + + + /** + * 是否有凭证 + * + * @return 有返回true + */ + public boolean hasCertificate() { + return !StringUtils.isEmpty(certificate); + } + + /** + * 校验用户输入的验证码是否正确 + * + * @return 正确返回true + */ + public boolean validateCode() { + return StringUtils.isEmpty(this.code) ? false : this.code.equals(this.originCode); + } + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getOriginCode() { + return originCode; + } + + public void setOriginCode(String originCode) { + this.originCode = originCode; + } + + 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; + } + + public String getCertificate() { + return certificate; + } + + public void setCertificate(String certificate) { + this.certificate = certificate; + } + + public String getRequestFrom() { + return requestFrom; + } + + public void setRequestFrom(String requestFrom) { + this.requestFrom = requestFrom; + } + + public String getKaptcha() { + return kaptcha; + } + + public void setKaptcha(String kaptcha) { + this.kaptcha = kaptcha; + } + + public String getOldKaptcha() { + return oldKaptcha; + } + + public void setOldKaptcha(String oldKaptcha) { + this.oldKaptcha = oldKaptcha; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/order/service/impl/PaySupplier.java b/ruoyi-segchk/src/main/java/com/ruoyi/order/service/impl/PaySupplier.java new file mode 100644 index 0000000..f29d612 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/order/service/impl/PaySupplier.java @@ -0,0 +1,16 @@ +package com.ruoyi.order.service.impl; + +/** + * Created by 魔金商城 on 17/12/22. + * 支付接口 + */ +@FunctionalInterface +public interface PaySupplier { + + /** + * 获得支付返回的参数结果 + * + * @return 返回支付参数结果 + */ + D getPayParams(T t, U u); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/order/vo/OrderItem.java b/ruoyi-segchk/src/main/java/com/ruoyi/order/vo/OrderItem.java new file mode 100644 index 0000000..4ea62d4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/order/vo/OrderItem.java @@ -0,0 +1,9 @@ +package com.ruoyi.order.vo; + +/** + * Created by 魔金商城 on 17/11/13. + * 订单枚举 + */ +public enum OrderItem { + LOG, ATTR, SKUS, CANREFUND, CANRETRUN, EXPRESSURL, STORE_INFO, BACK_PROGRESS, CUSTOMER, COMMUNITYHEAD +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeRet.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeRet.java new file mode 100644 index 0000000..0b221a0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeRet.java @@ -0,0 +1,47 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg充值卡管理对象 segchk_charge_card + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkChargeRet extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 充值id */ + @Excel(name = "充值id") + private Long chargeId; + + /** 卡id */ + @Excel(name = "卡id") + private Long cardId; + + public Long getChargeId() { + return chargeId; + } + + public void setChargeId(Long chargeId) { + this.chargeId = chargeId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + @Override + public String toString() { + return "SegchkChargeRet{" + + "chargeId=" + chargeId + + ", cardId=" + cardId + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeReward.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeReward.java new file mode 100644 index 0000000..fbc5a50 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkChargeReward.java @@ -0,0 +1,207 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.core.domain.BaseEntity; +import org.springframework.util.ObjectUtils; + +import java.math.BigDecimal; + +public class SegchkChargeReward extends BaseEntity { +// 会员卡类型id + private Integer cardTypeId; +// 会员卡id + private Long cardId; +// 对应用户id + private Long userId; +// 运营商id + private Long providerId; +// 充值id + private Long chargeId; +// 奖励id + private Long rewardId; +// 使用次数 + private Long useCount; +// 在目标商家核消次数 + private Long chkCount; +// 充值金额 + private BigDecimal charge; +// 余额使用额度 + private BigDecimal accountUsed; +// 推荐人id + private Long userRecommenders; +// 推荐人角色 + private Integer recommendersLevel; +// 持卡用户充值成功次数 + private Integer totalChargeCount; +// 奖励金额 + private BigDecimal reward; + + public Integer getCardTypeId() { + return cardTypeId; + } + + public void setCardTypeId(Integer cardTypeId) { + this.cardTypeId = cardTypeId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public BigDecimal getCharge() { + return charge; + } + + public void setCharge(BigDecimal charge) { + this.charge = charge; + } + + public BigDecimal getAccountUsed() { + return accountUsed; + } + + public void setAccountUsed(BigDecimal accountUsed) { + this.accountUsed = accountUsed; + } + + public Long getUserRecommenders() { + return userRecommenders; + } + + public void setUserRecommenders(Long userRecommenders) { + this.userRecommenders = userRecommenders; + } + + public Integer getRecommendersLevel() { + return recommendersLevel; + } + + public void setRecommendersLevel(Integer recommendersLevel) { + this.recommendersLevel = recommendersLevel; + } + + public Integer getTotalChargeCount() { + return totalChargeCount; + } + + public void setTotalChargeCount(Integer totalChargeCount) { + this.totalChargeCount = totalChargeCount; + } + + public BigDecimal getReward() { + return reward; + } + + public void setReward(BigDecimal reward) { + this.reward = reward; + } + + public Long getChargeId() { + return chargeId; + } + + public void setChargeId(Long chargeId) { + this.chargeId = chargeId; + } + + public Long getRewardId() { + return rewardId; + } + + public void setRewardId(Long rewardId) { + this.rewardId = rewardId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public Long getUseCount() { + return useCount; + } + + public void setUseCount(Long useCount) { + this.useCount = useCount; + } + + public Long getChkCount() { + return chkCount; + } + + public void setChkCount(Long chkCount) { + this.chkCount = chkCount; + } + + @Override + public String toString() { + return "SegchkChargeReward{" + + "cardTypeId=" + cardTypeId + + ", cardId=" + cardId + + ", userId=" + userId + + ", providerId=" + providerId + + ", chargeId=" + chargeId + + ", rewardId=" + rewardId + + ", useCount=" + useCount + + ", chkCount=" + chkCount + + ", charge=" + charge + + ", accountUsed=" + accountUsed + + ", userRecommenders=" + userRecommenders + + ", recommendersLevel=" + recommendersLevel + + ", totalChargeCount=" + totalChargeCount + + ", reward=" + reward + + '}'; + } + + public int validateForCheck(Long storeId){ +// 根据核消商家,判断是否可以返利 + if(ObjectUtils.isEmpty(this.getRecommendersLevel()) || this.getRecommendersLevel() == 2 || this.getRecommendersLevel() == 1){ +// 只要持卡用户推荐人不是平台。就不可以返利 + return -1; + } + else if(this.getUseCount() > 1 || this.getChkCount() > 1){ +// 该卡已发生过核消 + return -2; + } + else if(ObjectUtils.isEmpty(this.getReward())){ +// 该商家不支持该卡的核消,也不可以返利 + return -3; + } + else if(this.getReward().compareTo(new BigDecimal(0.0)) == 0){ +// 该商家不需要返利 + return -4; + } + return 0; + } + + public void mkReward() { + switch (this.getTotalChargeCount()){ + case 0: break; + case 1: { + this.setReward(this.getReward().divide(new BigDecimal("2"), 2, BigDecimal.ROUND_HALF_UP));break; + } + case 2: { + this.setReward(this.getReward().divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_UP));break; + } + default: { + this.setReward(new BigDecimal("0.0")); + break; + } + + } + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkMsgWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkMsgWebResp.java new file mode 100644 index 0000000..d477638 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkMsgWebResp.java @@ -0,0 +1,91 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +/** + * seg用户奖励对象 segchk_user_reward + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkMsgWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 消息类型,0系统消息,1交易消息,2提醒消息,3评价消息,4核消消息 */ + @Excel(name = "消息类型,0系统消息,1交易消息,2提醒消息,3评价消息,4核消消息") + private String msgType; + + /** 消息内容 */ + @Excel(name = "消息内容") + private String msgContent; + + /** 消息标题 */ + @Excel(name = "消息标题") + private String msgTitle; + + + /** 消息状态,0未发送,1,未读,2已读,3删除 */ + @Excel(name = "消息状态,0未发送,1,未读,2已读,3删除") + private String msgFlag; + + /** 接收时间 */ + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + @Excel(name = "接收时间", width = 30, dateFormat = "yyyy-MM-dd hh:mm:ss") + private Date fromTime; + + public String getMsgType() { + return msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String getMsgContent() { + return msgContent; + } + + public void setMsgContent(String msgContent) { + this.msgContent = msgContent; + } + + public String getMsgTitle() { + return msgTitle; + } + + public void setMsgTitle(String msgTitle) { + this.msgTitle = msgTitle; + } + + public String getMsgFlag() { + return msgFlag; + } + + public void setMsgFlag(String msgFlag) { + this.msgFlag = msgFlag; + } + + public Date getFromTime() { + return fromTime; + } + + public void setFromTime(Date fromTime) { + this.fromTime = fromTime; + } + + @Override + public String toString() { + return "SegchkMsgWebResp{" + + "msgType='" + msgType + '\'' + + ", msgContent='" + msgContent + '\'' + + ", msgTitle='" + msgTitle + '\'' + + ", msgFlag='" + msgFlag + '\'' + + ", fromTime=" + fromTime + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebResp.java new file mode 100644 index 0000000..85d54ab --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkRecommenderStoreWebResp.java @@ -0,0 +1,182 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.List; + +/** + * seg返回首页推荐商户对象 segchk_recommender_storeweb + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkRecommenderStoreWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家id,全局唯一 */ + @Excel(name = "商家id,全局唯一") + private Long storeId; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 商户显示序号 */ + @Excel(name = "商户显示序号") + private Integer storeSort; + + /** 商户列表模式时的图标 */ + @Excel(name = "商户列表模式时的图标") + private String storeIcon; + + /** 商户的大图标 */ + @Excel(name = "商户的大图标") + private String storeGificon; + + /** 商户经度 */ + @Excel(name = "商户经度") + private BigDecimal storeLon; + + /** 商户纬度 */ + @Excel(name = "商户纬度") + private BigDecimal storeLat; + + /** 商户累积核消次数 */ + @Excel(name = "商户累积核消次数") + private Integer chkCount; + + /** 商户平均星评 */ + @Excel(name = "商户平均星评") + private BigDecimal starAvg; + + /** 用户距离 */ + @Excel(name = "用户距离") + private BigDecimal userDist; + + + /** 商户标签列表 */ + @Valid + private List lables; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Integer getStoreSort() { + return storeSort; + } + + public void setStoreSort(Integer storeSort) { + this.storeSort = storeSort; + } + + public String getStoreIcon() { + return storeIcon; + } + + public void setStoreIcon(String storeIcon) { + this.storeIcon = storeIcon; + } + + public String getStoreGificon() { + return storeGificon; + } + + public void setStoreGificon(String storeGificon) { + this.storeGificon = storeGificon; + } + + public BigDecimal getStoreLon() { + return storeLon; + } + + public void setStoreLon(BigDecimal storeLon) { + this.storeLon = storeLon; + } + + public BigDecimal getStoreLat() { + return storeLat; + } + + public void setStoreLat(BigDecimal storeLat) { + this.storeLat = storeLat; + } + + public Integer getChkCount() { + return chkCount; + } + + public void setChkCount(Integer chkCount) { + this.chkCount = chkCount; + } + + public BigDecimal getStarAvg() { + return starAvg; + } + + public void setStarAvg(BigDecimal starAvg) { + this.starAvg = starAvg; + } + + public List getLables() { + return lables; + } + + public void setLables(List lables) { + this.lables = lables; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + @Override + public String toString() { + return "SegchkRecommenderStoreWebResp{" + + "providerId=" + providerId + + ", storeId=" + storeId + + ", storeName=" + storeName + + ", storeSort=" + storeSort + + ", storeIcon='" + storeIcon + '\'' + + ", storeGificon='" + storeGificon + '\'' + + ", storeLon=" + storeLon + + ", storeLat=" + storeLat + + ", chkCount=" + chkCount + + ", starAvg=" + starAvg + + ", lables=" + lables + + ", userDist=" + userDist + + '}'; + } + + public BigDecimal getUserDist() { + return userDist; + } + + public void setUserDist(BigDecimal userDist) { + this.userDist = userDist; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleDetailWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleDetailWebResp.java new file mode 100644 index 0000000..4cfe77a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleDetailWebResp.java @@ -0,0 +1,90 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceAndSaleDetailWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modTime; + + /** 会员卡号 */ + @Excel(name = "会员卡号") + private Long cardId; + + /** 卡类型名称 */ + @Excel(name = "卡类型名称") + private String cardName; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 统计结果 */ + @Excel(name = "统计结果") + private Long staticCount; + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public Long getStaticCount() { + return staticCount; + } + + public void setStaticCount(Long staticCount) { + this.staticCount = staticCount; + } + + @Override + public String toString() { + return "SegchkServiceAndSaleDetailWebResp{" + + "modTime=" + modTime + + ", cardId=" + cardId + + ", cardName='" + cardName + '\'' + + ", storeName='" + storeName + '\'' + + ", staticCount=" + staticCount + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebReq.java new file mode 100644 index 0000000..a1ebce6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebReq.java @@ -0,0 +1,98 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceAndSaleWebReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商户id */ + @Excel(name = "商户id") + private Long storeId; + + /** 统计等级,0按月统计,1按月查询统计 */ + @Excel(name = "统计等级") + private Integer staticLevel; + + /** 统计月份,只在staticLevel为1时有效,0时为统计的月数 */ + @Excel(name = "统计月份") + private String staticMonth; + + /** 用户身份,0运营商,1商家 */ + @Excel(name = "用户身份") + private Integer userLevel; + + /** 数据源选择,0核消,1售卡 */ + @Excel(name = "数据源选择") + private Integer srcFlag; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Integer getStaticLevel() { + return staticLevel; + } + + public void setStaticLevel(Integer staticLevel) { + this.staticLevel = staticLevel; + } + + public String getStaticMonth() { + return staticMonth; + } + + public void setStaticMonth(String staticMonth) { + this.staticMonth = staticMonth; + } + + public Integer getUserLevel() { + return userLevel; + } + + public void setUserLevel(Integer userLevel) { + this.userLevel = userLevel; + } + + @Override + public String toString() { + return "SegchkServiceAndSaleWebReq{" + + "providerId=" + providerId + + ", storeId=" + storeId + + ", staticLevel='" + staticLevel + '\'' + + ", staticMonth='" + staticMonth + '\'' + + ", userLevel=" + userLevel + + '}'; + } + + public Integer getSrcFlag() { + return srcFlag; + } + + public void setSrcFlag(Integer srcFlag) { + this.srcFlag = srcFlag; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebResp.java new file mode 100644 index 0000000..245db7b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceAndSaleWebResp.java @@ -0,0 +1,61 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceAndSaleWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + /** 统计月份,只在staticLevel为1时有效 */ + @Excel(name = "统计月份") + private String staticMonth; + + /** staticMonth与staticMonth同义,只是为yyyy-mm-01使用查询具备详单时使用 */ + @Excel(name = "统计月份") + private String queryMon; + + /** 统计结果 */ + @Excel(name = "统计结果") + private Long staticCount; + + public String getStaticMonth() { + return staticMonth; + } + + public void setStaticMonth(String staticMonth) { + this.staticMonth = staticMonth; + } + + public Long getStaticCount() { + return staticCount; + } + + public void setStaticCount(Long staticCount) { + this.staticCount = staticCount; + } + + public String getQueryMon() { + return queryMon; + } + + public void setQueryMon(String queryMon) { + this.queryMon = queryMon; + } + + @Override + public String toString() { + return "SegchkServiceAndSaleWebResp{" + + "staticMonth='" + staticMonth + '\'' + + ", queryMon='" + queryMon + '\'' + + ", staticCount=" + staticCount + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentUserReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentUserReq.java new file mode 100644 index 0000000..e3b70a2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentUserReq.java @@ -0,0 +1,89 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +/** + * seg评价记录对象 SegchkServiceCommentUserReq + * + * @author yinzhiying + * @date 2021-07-30 + */ +public class SegchkServiceCommentUserReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 评价id */ + private Long commentId; + + /** 星级评价 */ + @Excel(name = "星级评价") + private Integer starLevel; + + /** 评价内容 */ + @Excel(name = "评价内容") + private String contentText; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modTime; + + /** 核消id,全表唯一 */ + @Excel(name = "核消id,全表唯一") + private Long chkServiceId; + + public Long getCommentId() { + return commentId; + } + + public void setCommentId(Long commentId) { + this.commentId = commentId; + } + + public Integer getStarLevel() { + return starLevel; + } + + public void setStarLevel(Integer starLevel) { + this.starLevel = starLevel; + } + + public String getContentText() { + return contentText; + } + + public void setContentText(String contentText) { + this.contentText = contentText; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + public Long getChkServiceId() { + return chkServiceId; + } + + public void setChkServiceId(Long chkServiceId) { + this.chkServiceId = chkServiceId; + } + + @Override + public String toString() { + return "SegchkServiceCommentUserReq{" + + "commentId=" + commentId + + ", starLevel=" + starLevel + + ", contentText='" + contentText + '\'' + + ", modTime=" + modTime + + ", chkServiceId=" + chkServiceId + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentWebResp.java new file mode 100644 index 0000000..6efaa49 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceCommentWebResp.java @@ -0,0 +1,116 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +/** + * seg评价记录对象 segchk_service_comment + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceCommentWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 商家id,全局唯一 */ + @Excel(name = "商家id,全局唯一") + private Long storeId; + + /** 星级评价 */ + @Excel(name = "星级评价") + private Integer starLevel; + + /** 评价内容 */ + @Excel(name = "评价内容") + private String contentText; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modTime; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 充值卡id */ + @Excel(name = "充值卡名称") + private String cardName; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private String userName; + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Integer getStarLevel() { + return starLevel; + } + + public void setStarLevel(Integer starLevel) { + this.starLevel = starLevel; + } + + public String getContentText() { + return contentText; + } + + public void setContentText(String contentText) { + this.contentText = contentText; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Override + public String toString() { + return "SegchkServiceCommentWebResp{" + + "storeId=" + storeId + + ", starLevel=" + starLevel + + ", contentText='" + contentText + '\'' + + ", modTime=" + modTime + + ", providerId=" + providerId + + ", cardName='" + cardName + '\'' + + ", userName='" + userName + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkResp.java new file mode 100644 index 0000000..a33f110 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderChkResp.java @@ -0,0 +1,138 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceOrderChkResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id */ + @Excel(name = "运营商id") + private Long providerId; + + /** 商户id */ + @Excel(name = "商户id") + private Long storeId; + + /** 用户id */ + @Excel(name = "用户id") + private Long userId; + + /** 卡id */ + @Excel(name = "卡id") + private Long cardId; + + /** 会员卡或优惠券下的标签id */ + @Excel(name = "会员卡或优惠券下的标签id") + private Integer lableId; + + /** 卡类型 0 会员卡,1赠卡,2优惠券 */ + @Excel(name = "卡类型") + private Integer typeId; + + /** 卡名称 */ + @Excel(name = "卡名称") + private String cardName; + + /** 剩余次数 */ + @Excel(name = "卡名称") + private Integer leftCount; + + /** 是否支持 */ + @Excel(name = "是否支持") + private Integer isSupported; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public Integer getLableId() { + return lableId; + } + + public void setLableId(Integer lableId) { + this.lableId = lableId; + } + + public Integer getTypeId() { + return typeId; + } + + public void setTypeId(Integer typeId) { + this.typeId = typeId; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public Integer getLeftCount() { + return leftCount; + } + + public void setLeftCount(Integer leftCount) { + this.leftCount = leftCount; + } + + public Integer getIsSupported() { + return isSupported; + } + + public void setIsSupported(Integer isSupported) { + this.isSupported = isSupported; + } + + @Override + public String toString() { + return "SegchkServiceOrderChkResp{" + + "providerId=" + providerId + + ", storeId=" + storeId + + ", userId=" + userId + + ", cardId=" + cardId + + ", lableId=" + lableId + + ", typeId=" + typeId + + ", cardName='" + cardName + '\'' + + ", leftCount=" + leftCount + + ", isSupported=" + isSupported + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderWebReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderWebReq.java new file mode 100644 index 0000000..2f4b25f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkServiceOrderWebReq.java @@ -0,0 +1,136 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkServiceOrderWebReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id */ + @Excel(name = "运营商id") + private Long providerId; + + /** 商户id */ + @Excel(name = "商户id") + private Long storeId; + + /** 用户id */ + @Excel(name = "用户id") + private Long userId; + + /** 卡id */ + @Excel(name = "卡id") + private Long cardId; + + /** 会员卡或优惠券下的标签id */ + @Excel(name = "会员卡或优惠券下的标签id") + private Integer lableId; + + /** 卡类型 0 会员卡,1赠卡,2优惠券 */ + @Excel(name = "卡类型") + private Integer typeId; + + /** 卡名称 */ + @Excel(name = "卡名称") + private String cardName; + + /** 用户卡片的剩余使用次数 */ + @Excel(name = "卡剩余次数") + private Integer leftCount; + + /** 该商家支持的核销次数 */ + @Excel(name = "商家支持次数") + private Integer stoerChkCount; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public Integer getLableId() { + return lableId; + } + + public void setLableId(Integer lableId) { + this.lableId = lableId; + } + + public Integer getTypeId() { + return typeId; + } + + public void setTypeId(Integer typeId) { + this.typeId = typeId; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + @Override + public String toString() { + return "SegchkServiceOrderWebReq{" + + "providerId=" + providerId + + ", storeId=" + storeId + + ", userId=" + userId + + ", cardId=" + cardId + + ", lableId=" + lableId + + ", typeId=" + typeId + + ", cardName='" + cardName + '\'' + + '}'; + } + + public Integer getLeftCount() { + return leftCount; + } + + public void setLeftCount(Integer leftCount) { + this.leftCount = leftCount; + } + + public Integer getStoerChkCount() { + return stoerChkCount; + } + + public void setStoerChkCount(Integer stoerChkCount) { + this.stoerChkCount = stoerChkCount; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreBasicInfoWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreBasicInfoWebResp.java new file mode 100644 index 0000000..5bc83ea --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreBasicInfoWebResp.java @@ -0,0 +1,325 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.List; + +/** + * seg商家详情页对象 SegchkStoreBasicInfoWebResp + * + * @author yinzhiying + * @date 2021-07-12 + */ +public class SegchkStoreBasicInfoWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家id,全局唯一 */ + @Excel(name = "商家id,全局唯一") + private Long storeId; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 商家电话 */ + @Excel(name = "商家电话") + private String storePhone; + + /** 服务状态,0在线,1下线 */ + @Excel(name = "服务状态,0在线,1下线") + private String serviceState; + + /** 销售id */ + @Excel(name = "销售id") + private Integer salerId; + + /** 商家地址 */ + @Excel(name = "商家地址") + private String storeAddr; + + /** 商家经度 */ + @Excel(name = "商家经度") + private BigDecimal storeLon; + + /** 商家纬度 */ + @Excel(name = "商家纬度") + private BigDecimal storeLat; + + /** 商家运营时间 */ + @Excel(name = "商家运营时间") + private String onService; + + /** 商家描述详情 */ + @Excel(name = "商家描述详情") + private String detail; + + @Excel(name = "商家vr路径") + private String storeVR; + + /** 商家轮播图1路径,默认用于首页推荐轮播图 */ + @Excel(name = "商家轮播图1路径,默认用于首页推荐轮播图") + private String storeCarousel1; + + /** 商家轮播图2路径 */ + @Excel(name = "商家轮播图2路径") + private String storeCarousel2; + + /** 商家轮播图3路径 */ + @Excel(name = "商家轮播图3路径") + private String storeCarousel3; + + /** 商家轮播图4路径 */ + @Excel(name = "商家轮播图4路径") + private String storeCarousel4; + + /** 商家轮播图5路径 */ + @Excel(name = "商家轮播图5路径") + private String storeCarousel5; + + /** 商家轮播图6路径 */ + @Excel(name = "商家轮播图6路径") + private String storeCarousel6; + + /** 商户累积核消次数 */ + @Excel(name = "商户累积核消次数") + private Integer chkCount; + + /** 商户平均星评 */ + @Excel(name = "商户平均星评") + private BigDecimal starAvg; + + + /** 是否被收藏 */ + @Excel(name = "是否被收藏") + private Integer isCollect = 0; + + /** 商户标签列表 */ + @Valid + private List segchkRecommenderStoreLableWebList; + + public void setProviderId(Long providerId) + { + this.providerId = providerId; + } + + public Long getProviderId() + { + return providerId; + } + public void setStoreId(Long storeId) + { + this.storeId = storeId; + } + + public Long getStoreId() + { + return storeId; + } + public void setStoreName(String storeName) + { + this.storeName = storeName; + } + + public String getStoreName() + { + return storeName; + } + public void setStorePhone(String storePhone) + { + this.storePhone = storePhone; + } + + public void setServiceState(String serviceState) + { + this.serviceState = serviceState; + } + + public String getServiceState() + { + return serviceState; + } + public void setSalerId(Integer salerId) + { + this.salerId = salerId; + } + + public Integer getSalerId() + { + return salerId; + } + + public void setStoreAddr(String storeAddr) + { + this.storeAddr = storeAddr; + } + + public String getStoreAddr() + { + return storeAddr; + } + public void setStoreLon(BigDecimal storeLon) + { + this.storeLon = storeLon; + } + + public BigDecimal getStoreLon() + { + return storeLon; + } + public void setStoreLat(BigDecimal storeLat) + { + this.storeLat = storeLat; + } + + public BigDecimal getStoreLat() + { + return storeLat; + } + public void setOnService(String onService) + { + this.onService = onService; + } + + public String getOnService() + { + return onService; + } + public void setDetail(String detail) + { + this.detail = detail; + } + + public String getDetail() + { + return detail; + } + + public String getStorePhone() { + return storePhone; + } + + public String getStoreCarousel1() { + return storeCarousel1; + } + + public void setStoreCarousel1(String storeCarousel1) { + this.storeCarousel1 = storeCarousel1; + } + + public String getStoreCarousel2() { + return storeCarousel2; + } + + public void setStoreCarousel2(String storeCarousel2) { + this.storeCarousel2 = storeCarousel2; + } + + public String getStoreCarousel3() { + return storeCarousel3; + } + + public void setStoreCarousel3(String storeCarousel3) { + this.storeCarousel3 = storeCarousel3; + } + + public String getStoreCarousel4() { + return storeCarousel4; + } + + public void setStoreCarousel4(String storeCarousel4) { + this.storeCarousel4 = storeCarousel4; + } + + public String getStoreCarousel5() { + return storeCarousel5; + } + + public void setStoreCarousel5(String storeCarousel5) { + this.storeCarousel5 = storeCarousel5; + } + + public String getStoreCarousel6() { + return storeCarousel6; + } + + public void setStoreCarousel6(String storeCarousel6) { + this.storeCarousel6 = storeCarousel6; + } + + public List getSegchkRecommenderStoreLableWebList() { + return segchkRecommenderStoreLableWebList; + } + + public void setSegchkRecommenderStoreLableWebList(List segchkRecommenderStoreLableWebList) { + this.segchkRecommenderStoreLableWebList = segchkRecommenderStoreLableWebList; + } + + public Integer getChkCount() { + return chkCount; + } + + public void setChkCount(Integer chkCount) { + this.chkCount = chkCount; + } + + public BigDecimal getStarAvg() { + return starAvg; + } + + public void setStarAvg(BigDecimal starAvg) { + this.starAvg = starAvg; + } + + public Integer getIsCollect() { + return isCollect; + } + + public void setIsCollect(Integer isCollect) { + this.isCollect = isCollect; + } + + public String getStoreVR() { + return storeVR; + } + + public void setStoreVR(String storeVR) { + this.storeVR = storeVR; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("SegchkStoreBasicInfoWebResp{"); + sb.append("providerId=").append(providerId); + sb.append(", storeId=").append(storeId); + sb.append(", storeName='").append(storeName).append('\''); + sb.append(", storePhone='").append(storePhone).append('\''); + sb.append(", serviceState='").append(serviceState).append('\''); + sb.append(", salerId=").append(salerId); + sb.append(", storeAddr='").append(storeAddr).append('\''); + sb.append(", storeLon=").append(storeLon); + sb.append(", storeLat=").append(storeLat); + sb.append(", onService='").append(onService).append('\''); + sb.append(", detail='").append(detail).append('\''); + sb.append(", storeVR='").append(storeVR).append('\''); + sb.append(", storeCarousel1='").append(storeCarousel1).append('\''); + sb.append(", storeCarousel2='").append(storeCarousel2).append('\''); + sb.append(", storeCarousel3='").append(storeCarousel3).append('\''); + sb.append(", storeCarousel4='").append(storeCarousel4).append('\''); + sb.append(", storeCarousel5='").append(storeCarousel5).append('\''); + sb.append(", storeCarousel6='").append(storeCarousel6).append('\''); + sb.append(", chkCount=").append(chkCount); + sb.append(", starAvg=").append(starAvg); + sb.append(", isCollect=").append(isCollect); + sb.append(", segchkRecommenderStoreLableWebList=").append(segchkRecommenderStoreLableWebList); + sb.append('}'); + return sb.toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreIndexWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreIndexWebResp.java new file mode 100644 index 0000000..8dd6873 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreIndexWebResp.java @@ -0,0 +1,209 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.List; + +/** + * seg返回首页推荐商户对象 segchk_recommender_storeweb + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkStoreIndexWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家id,全局唯一 */ + @Excel(name = "商家id,全局唯一") + private Long storeId; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 商家状态 */ + @Excel(name = "商家状态") + private String serviceState; + + /** 商户显示序号 */ + @Excel(name = "商户显示序号") + private Integer storeSort; + + /** 商户列表模式时的图标 */ + @Excel(name = "商户列表模式时的图标") + private String storeIcon; + + /** 商户的大图标 */ + @Excel(name = "商户的大图标") + private String storeGificon; + + /** 商户经度 */ + @Excel(name = "商户经度") + private BigDecimal storeLon; + + /** 商户纬度 */ + @Excel(name = "商户纬度") + private BigDecimal storeLat; + + /** 用户距离 */ + @Excel(name = "用户距离") + private BigDecimal userDist; + + /** 商户累积核消次数 */ + @Excel(name = "商户累积核消次数") + private Integer chkCount; + + /** 商户平均星评 */ + @Excel(name = "商户平均星评") + private BigDecimal starAvg; + + /** 在线状态 */ + @Excel(name = "对应的销售id") + private Integer salerId; + + + /** 商户标签列表 */ + @Valid + private List lables; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Integer getStoreSort() { + return storeSort; + } + + public void setStoreSort(Integer storeSort) { + this.storeSort = storeSort; + } + + public String getStoreIcon() { + return storeIcon; + } + + public void setStoreIcon(String storeIcon) { + this.storeIcon = storeIcon; + } + + public String getStoreGificon() { + return storeGificon; + } + + public void setStoreGificon(String storeGificon) { + this.storeGificon = storeGificon; + } + + public BigDecimal getStoreLon() { + return storeLon; + } + + public void setStoreLon(BigDecimal storeLon) { + this.storeLon = storeLon; + } + + public BigDecimal getStoreLat() { + return storeLat; + } + + public void setStoreLat(BigDecimal storeLat) { + this.storeLat = storeLat; + } + + public Integer getChkCount() { + return chkCount; + } + + public void setChkCount(Integer chkCount) { + this.chkCount = chkCount; + } + + public BigDecimal getStarAvg() { + return starAvg; + } + + public void setStarAvg(BigDecimal starAvg) { + this.starAvg = starAvg; + } + + public List getLables() { + return lables; + } + + public void setLables(List lables) { + this.lables = lables; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + + public String getServiceState() { + return serviceState; + } + + public void setServiceState(String serviceState) { + this.serviceState = serviceState; + } + + public Integer getSalerId() { + return salerId; + } + + public void setSalerId(Integer salerId) { + this.salerId = salerId; + } + + @Override + public String toString() { + return "SegchkStoreIndexWebResp{" + + "providerId=" + providerId + + ", storeId=" + storeId + + ", storeName='" + storeName + '\'' + + ", serviceState='" + serviceState + '\'' + + ", storeSort=" + storeSort + + ", storeIcon='" + storeIcon + '\'' + + ", storeGificon='" + storeGificon + '\'' + + ", storeLon=" + storeLon + + ", storeLat=" + storeLat + + ", chkCount=" + chkCount + + ", starAvg=" + starAvg + + ", salerId=" + salerId + + ", lables=" + lables + + ", userDist=" + userDist + + '}'; + } + + public BigDecimal getUserDist() { + return userDist; + } + + public void setUserDist(BigDecimal userDist) { + this.userDist = userDist; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreVrReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreVrReq.java new file mode 100644 index 0000000..013c95d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreVrReq.java @@ -0,0 +1,118 @@ +package com.ruoyi.segchk.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg 商家vr请求体 + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkStoreVrReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** vr标识,全局唯一 */ + private Long vrId; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家ID,全局唯一 */ + @Excel(name = "商家ID,全局唯一") + private Long storeId; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String vrUrl; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String thumbPath; + + /** 服务状态,0在线,1下线 */ + @Excel(name = "服务状态,0在线,1下线") + private String serviceState; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modTime; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("vrId", getVrId()) + .append("providerId", getProviderId()) + .append("storeId", getStoreId()) + .append("vrUrl", getVrUrl()) + .append("thumbPath", getThumbPath()) + .append("serviceState", getServiceState()) + .append("modTime", getModTime()) + .toString(); + } + + public Long getVrId() { + return vrId; + } + + public void setVrId(Long vrId) { + this.vrId = vrId; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public String getVrUrl() { + return vrUrl; + } + + public void setVrUrl(String vrUrl) { + this.vrUrl = vrUrl; + } + + public String getThumbPath() { + return thumbPath; + } + + public void setThumbPath(String thumbPath) { + this.thumbPath = thumbPath; + } + + public String getServiceState() { + return serviceState; + } + + public void setServiceState(String serviceState) { + this.serviceState = serviceState; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreWebReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreWebReq.java new file mode 100644 index 0000000..5156fb3 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkStoreWebReq.java @@ -0,0 +1,179 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg返回首页推荐商户对象 segchk_recommender_storeweb + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkStoreWebReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 排序类型 */ + @Excel(name = "排序类型") + private Integer sortType; + + /** 商户id */ + @Excel(name = "商户id") + private Integer storeId; + + /** 商户名称 */ + @Excel(name = "商户名称") + private String storeName; + + /** 标签id */ + @Excel(name = "标签id") + private Integer lableId; + + /** 标签名称 */ + @Excel(name = "标签名称") + private String lableName; + + /** 标签类型id */ + @Excel(name = "标签类型id") + private Integer typeId; + + /** 充值卡id */ + @Excel(name = "充值卡id") + private Integer cardId; + + /** 充值卡名称 */ + @Excel(name = "充值卡名称") + private String cardName; + + /** 用户经度 */ + @Excel(name = "用户经度") + private BigDecimal userLon; + + /** 用户纬度 */ + @Excel(name = "用户纬度") + private BigDecimal userLat; + + /** 用户距离 */ + @Excel(name = "用户距离") + private BigDecimal userDist; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Integer getSortType() { + return sortType; + } + + public void setSortType(Integer sortType) { + this.sortType = sortType; + } + + public Integer getStoreId() { + return storeId; + } + + public void setStoreId(Integer storeId) { + this.storeId = storeId; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public Integer getLableId() { + return lableId; + } + + public void setLableId(Integer lableId) { + this.lableId = lableId; + } + + public String getLableName() { + return lableName; + } + + public void setLableName(String lableName) { + this.lableName = lableName; + } + + public Integer getTypeId() { + return typeId; + } + + public void setTypeId(Integer typeId) { + this.typeId = typeId; + } + + public Integer getCardId() { + return cardId; + } + + public void setCardId(Integer cardId) { + this.cardId = cardId; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public BigDecimal getUserLon() { + return userLon; + } + + public void setUserLon(BigDecimal userLon) { + this.userLon = userLon; + } + + public BigDecimal getUserLat() { + return userLat; + } + + public void setUserLat(BigDecimal userLat) { + this.userLat = userLat; + } + + public BigDecimal getUserDist() { + return userDist; + } + + public void setUserDist(BigDecimal userDist) { + this.userDist = userDist; + } + + @Override + public String toString() { + return "SegchkStoreWebReq{" + + "providerId=" + providerId + + ", sortType=" + sortType + + ", storeId=" + storeId + + ", storeName='" + storeName + '\'' + + ", lableId=" + lableId + + ", lableName='" + lableName + '\'' + + ", typeId=" + typeId + + ", cardId=" + cardId + + ", cardName='" + cardName + '\'' + + ", userLon=" + userLon + + ", userLat=" + userLat + + ", userDist=" + userDist + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccountCheck.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccountCheck.java new file mode 100644 index 0000000..b2c4024 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserAccountCheck.java @@ -0,0 +1,76 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg用户余额信息对象 segchk_user_account + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserAccountCheck extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long userId; + + /** 余额 */ + @Excel(name = "余额") + private BigDecimal account; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 余额id */ + @Excel(name = "余额id") + private Long accountId; + + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public BigDecimal getAccount() { + return account; + } + + public void setAccount(BigDecimal account) { + this.account = account; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + @Override + public String toString() { + return "SegchkUserAccountCheck{" + + "userId=" + userId + + ", account=" + account + + ", providerId=" + providerId + + ", accountId=" + accountId + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsResp.java new file mode 100644 index 0000000..76f541d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashOpsResp.java @@ -0,0 +1,49 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg用户提现记录对象 segchk_user_cash + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserCashOpsResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 提现额 */ + @Excel(name = "提现额") + private BigDecimal account; + + /** 提现id,全表唯一 */ + @Excel(name = "提现id,全表唯一") + private Long cashId; + + public BigDecimal getAccount() { + return account; + } + + public void setAccount(BigDecimal account) { + this.account = account; + } + + public Long getCashId() { + return cashId; + } + + public void setCashId(Long cashId) { + this.cashId = cashId; + } + + @Override + public String toString() { + return "SegchkUserCashOpsResp{" + + "account=" + account + + ", cashId=" + cashId + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashWebResp.java new file mode 100644 index 0000000..2390fee --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCashWebResp.java @@ -0,0 +1,66 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * seg用户奖励对象 segchk_user_reward + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserCashWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal cash; + + /** 奖励卡号 */ + @Excel(name = "奖励卡号") + private String retFlag; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd hh:mm:ss") + private Date modTime; + + + public BigDecimal getCash() { + return cash; + } + + public void setCash(BigDecimal cash) { + this.cash = cash; + } + + public String getRetFlag() { + return retFlag; + } + + public void setRetFlag(String retFlag) { + this.retFlag = retFlag; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + @Override + public String toString() { + return "SegchkUserCashWebResp{" + + "cash=" + cash + + ", retFlag='" + retFlag + '\'' + + ", modTime=" + modTime + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeCard.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeCard.java new file mode 100644 index 0000000..b27b0eb --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeCard.java @@ -0,0 +1,153 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg用户充值可选卡对象 SegchkUserChargeCard + * + * @author yinzhiying + * @date 2021-07-30 + */ +public class SegchkUserChargeCard extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运营商id */ + @Excel(name = "运营商id") + private Long providerId; + + /** 卡类型id */ + @Excel(name = "卡类型id") + private Long cardTypeId; + + /** 会员卡id */ + @Excel(name = "会员卡id") + private Long cardId; + + /** 会员卡名称 */ + @Excel(name = "会员卡名称") + private String cardTypeName; + + /** 已购买次数 */ + @Excel(name = "已购买次数") + private Integer hadBuy; + + /** 可购买次数 */ + @Excel(name = "可购买次数") + private Integer buyCount; + + /** 会员卡面值 */ + @Excel(name = "会员卡面值") + private BigDecimal cardTypeValue; + + /** 是否可以购买,0可,1有卡正在使用,2购买次数超限 */ + @Excel(name = "是否可以购买") + private Integer canBuy; + + /** 会员卡权益次数 */ + @Excel(name = "会员卡权益次数") + private Integer cardTypeChkcount; + + /** 会员卡有效天数 */ + @Excel(name = "会员卡有效天数") + private Integer effectiveTime; + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getCardTypeId() { + return cardTypeId; + } + + public void setCardTypeId(Long cardTypeId) { + this.cardTypeId = cardTypeId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public String getCardTypeName() { + return cardTypeName; + } + + public void setCardTypeName(String cardTypeName) { + this.cardTypeName = cardTypeName; + } + + public Integer getHadBuy() { + return hadBuy; + } + + public void setHadBuy(Integer hadBuy) { + this.hadBuy = hadBuy; + } + + public Integer getBuyCount() { + return buyCount; + } + + public void setBuyCount(Integer buyCount) { + this.buyCount = buyCount; + } + + public BigDecimal getCardTypeValue() { + return cardTypeValue; + } + + public void setCardTypeValue(BigDecimal cardTypeValue) { + this.cardTypeValue = cardTypeValue; + } + + public Integer getCanBuy() { + return canBuy; + } + + public void setCanBuy(Integer canBuy) { + this.canBuy = canBuy; + } + + public Integer getCardTypeChkcount() { + return cardTypeChkcount; + } + + public void setCardTypeChkcount(Integer cardTypeChkcount) { + this.cardTypeChkcount = cardTypeChkcount; + } + + public Integer getEffectiveTime() { + return effectiveTime; + } + + public void setEffectiveTime(Integer effectiveTime) { + this.effectiveTime = effectiveTime; + } + + @Override + public String toString() { + return "SegchkUserChargeCard{" + + "providerId=" + providerId + + ", cardTypeId=" + cardTypeId + + ", cardId=" + cardId + + ", cardTypeName='" + cardTypeName + '\'' + + ", hadBuy=" + hadBuy + + ", buyCount=" + buyCount + + ", cardTypeValue=" + cardTypeValue + + ", canBuy=" + canBuy + + ", cardTypeChkcount=" + cardTypeChkcount + + ", effectiveTime=" + effectiveTime + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeWebResp.java new file mode 100644 index 0000000..201c238 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserChargeWebResp.java @@ -0,0 +1,78 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * seg用户奖励对象 segchk_user_reward + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserChargeWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal charge; + + /** 奖励类型 */ + @Excel(name = "奖励类型") + private String cardName; + + /** 奖励卡号 */ + @Excel(name = "奖励卡号") + private String retFlag; + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd hh:mm:ss") + private Date modTime; + + public BigDecimal getCharge() { + return charge; + } + + public void setCharge(BigDecimal charge) { + this.charge = charge; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getRetFlag() { + return retFlag; + } + + public void setRetFlag(String retFlag) { + this.retFlag = retFlag; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + @Override + public String toString() { + return "SegchkUserChargeWebResp{" + + "charge=" + charge + + ", cardName='" + cardName + '\'' + + ", retFlag=" + retFlag + + ", modTime=" + modTime + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollectWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollectWebResp.java new file mode 100644 index 0000000..259ca96 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserCollectWebResp.java @@ -0,0 +1,185 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * seg会员卡对象 segchk_user_vip + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserCollectWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 收藏id */ + @Excel(name = "收藏id") + private Long collectId; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家id */ + @Excel(name = "商家id,全局惟一") + private Long storeId; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 商家图标 */ + @Excel(name = "会员卡类型,0--9块9,1---99") + private String storeIcon; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long serviceState; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal storeLon; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal storeLat; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long chkCount; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal starAvg; + + + /** 创建或修改时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "创建或修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modTime; + + /** 商户标签列表 */ + @Valid + private List segchkRecommenderStoreLableWebList; + + public Long getCollectId() { + return collectId; + } + + public void setCollectId(Long collectId) { + this.collectId = collectId; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getStoreIcon() { + return storeIcon; + } + + public void setStoreIcon(String storeIcon) { + this.storeIcon = storeIcon; + } + + public Long getServiceState() { + return serviceState; + } + + public void setServiceState(Long serviceState) { + this.serviceState = serviceState; + } + + public BigDecimal getStoreLon() { + return storeLon; + } + + public void setStoreLon(BigDecimal storeLon) { + this.storeLon = storeLon; + } + + public BigDecimal getStoreLat() { + return storeLat; + } + + public void setStoreLat(BigDecimal storeLat) { + this.storeLat = storeLat; + } + + public Long getChkCount() { + return chkCount; + } + + public void setChkCount(Long chkCount) { + this.chkCount = chkCount; + } + + public BigDecimal getStarAvg() { + return starAvg; + } + + public void setStarAvg(BigDecimal starAvg) { + this.starAvg = starAvg; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + public List getSegchkRecommenderStoreLableWebList() { + return segchkRecommenderStoreLableWebList; + } + + public void setSegchkRecommenderStoreLableWebList(List segchkRecommenderStoreLableWebList) { + this.segchkRecommenderStoreLableWebList = segchkRecommenderStoreLableWebList; + } + + @Override + public String toString() { + return "SegchkUserCollectWebResp{" + + "collectId=" + collectId + + ", providerId=" + providerId + + ", storeId=" + storeId + + ", storeName='" + storeName + '\'' + + ", storeIcon='" + storeIcon + '\'' + + ", serviceState=" + serviceState + + ", storeLon=" + storeLon + + ", storeLat=" + storeLat + + ", chkCount=" + chkCount + + ", starAvg=" + starAvg + + ", modTime=" + modTime + + ", segchkRecommenderStoreLableWebList=" + segchkRecommenderStoreLableWebList + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikeGoWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikeGoWebResp.java new file mode 100644 index 0000000..593df8a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserLikeGoWebResp.java @@ -0,0 +1,263 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * seg会员卡对象 segchk_user_vip + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserLikeGoWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 想去id */ + @Excel(name = "想去id") + private Long likegoId; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 商家id */ + @Excel(name = "商家id,全局惟一") + private Long storeId; + + /** 会员卡id */ + @Excel(name = "会员卡id,充值卡或自定义卡") + private Long cardId; + + /** 用户id */ + @Excel(name = "用户id,全局惟一") + private Long userId; + + /** 用户手机尾号 */ + @Excel(name = "用户手机尾号") + private String phoneNo; + + /** 用户昵称 */ + @Excel(name = "用户昵称") + private String nickName; + + /** 商家名称 */ + @Excel(name = "商家名称") + private String storeName; + + /** 卡名称 */ + @Excel(name = "卡名称") + private String cardName; + + /** 二维码 */ + @Excel(name = "二维码") + private String qrCode; + + /** 商家小图标 */ + @Excel(name = "商家小图标") + private String storeIcon; + + /** 商家服务状态,是否在线 */ + @Excel(name = "商家服务状态") + private Long serviceState; + + /** 商家经度 */ + @Excel(name = "商家经度") + private BigDecimal storeLon; + + /** 商家纬度 */ + @Excel(name = "商家纬度") + private BigDecimal storeLat; + + /** 商家累积核次数 */ + @Excel(name = "商家累积核次数") + private Long chkCount; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private BigDecimal starAvg; + + + /** 预约时间 */ + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + @Excel(name = "预约时间", width = 30, dateFormat = "yyyy-MM-dd hh:mm:ss") + private Date modTime; + + /** 商户标签列表 */ + @Valid + private List segchkRecommenderStoreLableWebList; + + public Long getLikegoId() { + return likegoId; + } + + public void setLikegoId(Long likegoId) { + this.likegoId = likegoId; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getQrCode() { + return qrCode; + } + + public void setQrCode(String qrCode) { + this.qrCode = qrCode; + } + + public String getStoreIcon() { + return storeIcon; + } + + public void setStoreIcon(String storeIcon) { + this.storeIcon = storeIcon; + } + + public Long getServiceState() { + return serviceState; + } + + public void setServiceState(Long serviceState) { + this.serviceState = serviceState; + } + + public BigDecimal getStoreLon() { + return storeLon; + } + + public void setStoreLon(BigDecimal storeLon) { + this.storeLon = storeLon; + } + + public BigDecimal getStoreLat() { + return storeLat; + } + + public void setStoreLat(BigDecimal storeLat) { + this.storeLat = storeLat; + } + + public Long getChkCount() { + return chkCount; + } + + public void setChkCount(Long chkCount) { + this.chkCount = chkCount; + } + + public BigDecimal getStarAvg() { + return starAvg; + } + + public void setStarAvg(BigDecimal starAvg) { + this.starAvg = starAvg; + } + + public Date getModTime() { + return modTime; + } + + public void setModTime(Date modTime) { + this.modTime = modTime; + } + + public List getSegchkRecommenderStoreLableWebList() { + return segchkRecommenderStoreLableWebList; + } + + public void setSegchkRecommenderStoreLableWebList(List segchkRecommenderStoreLableWebList) { + this.segchkRecommenderStoreLableWebList = segchkRecommenderStoreLableWebList; + } + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + return "SegchkUserLikeGoWebResp{" + + "likegoId=" + likegoId + + ", providerId=" + providerId + + ", storeId=" + storeId + + ", cardId=" + cardId + + ", userId=" + userId + + ", phoneNo='" + phoneNo + '\'' + + ", nickName='" + nickName + '\'' + + ", storeName='" + storeName + '\'' + + ", cardName='" + cardName + '\'' + + ", qrCode='" + qrCode + '\'' + + ", storeIcon='" + storeIcon + '\'' + + ", serviceState=" + serviceState + + ", storeLon=" + storeLon + + ", storeLat=" + storeLat + + ", chkCount=" + chkCount + + ", starAvg=" + starAvg + + ", modTime=" + modTime + + ", segchkRecommenderStoreLableWebList=" + segchkRecommenderStoreLableWebList + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserSetInfoReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserSetInfoReq.java new file mode 100644 index 0000000..60658e6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserSetInfoReq.java @@ -0,0 +1,104 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户修改信息对象 SegchkUserSetInfoReq + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserSetInfoReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long userId; + + /** 密码 */ + @Excel(name = "密码") + private String passwd; + + /** 密码id,全表唯一 */ + @Excel(name = "密码id,全表唯一") + private Long pwdId; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 用户手机号 */ + @Excel(name = "用户手机号") + private String phoneNo; + + /** 用户等级 */ + @Excel(name = "用户等级") + private Integer userLevel; + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setPasswd(String passwd) + { + this.passwd = passwd; + } + + public void setPwdId(Long pwdId) + { + this.pwdId = pwdId; + } + + public Long getPwdId() + { + return pwdId; + } + public void setProviderId(Long providerId) + { + this.providerId = providerId; + } + + public Long getProviderId() + { + return providerId; + } + + public String getPasswd() { + return passwd; + } + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public Integer getUserLevel() { + return userLevel; + } + + public void setUserLevel(Integer userLevel) { + this.userLevel = userLevel; + } + + @Override + public String toString() { + return "SegchkUserSetInfoReq{" + + "userId=" + userId + + ", passwd='" + passwd + '\'' + + ", pwdId=" + pwdId + + ", providerId=" + providerId + + ", phoneNo='" + phoneNo + '\'' + + ", userLevel=" + userLevel + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebCardResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebCardResp.java new file mode 100644 index 0000000..5c77742 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebCardResp.java @@ -0,0 +1,185 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.Date; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserWebCardResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + /** 运营商id */ + @Excel(name = "运营商id") + private String providerId; + + /** 卡名称 */ + @Excel(name = "卡名称") + private String cardName; + + /** 卡提供商(商家名称) */ + @Excel(name = "卡提供商") + private String storeName; + + /** 商家id */ + @Excel(name = "商家id") + private String storeId; + + + /** 使用次数 */ + @Excel(name = "使用次数") + private Integer useCount; + + /** 剩余次数 */ + @Excel(name = "剩余次数") + private Integer leftCount; + + /** 有效期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "有效期", width = 30, dateFormat = "yyyy-MM-dd") + private Date effectiveTime; + + /** 卡券标识,0会员卡,1券(或赠卡) */ + @Excel(name = "卡券标识") + private Integer typeFlag; + + /** 卡券状态 */ + @Excel(name = "卡券状态") + private String cardStatus; + + /** 卡券说明 */ + @Excel(name = "卡券说明") + private String cardContent; + + /** 卡券说明 */ + @Excel(name = "卡券说明") + private String bgUrl; + + /** 卡券字体颜色 */ + @Excel(name = "卡券字体颜色") + private String contentColor; + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public Integer getUseCount() { + return useCount; + } + + public void setUseCount(Integer useCount) { + this.useCount = useCount; + } + + public Integer getLeftCount() { + return leftCount; + } + + public void setLeftCount(Integer leftCount) { + this.leftCount = leftCount; + } + + public Date getEffectiveTime() { + return effectiveTime; + } + + public void setEffectiveTime(Date effectiveTime) { + this.effectiveTime = effectiveTime; + } + + public Integer getTypeFlag() { + return typeFlag; + } + + public void setTypeFlag(Integer typeFlag) { + this.typeFlag = typeFlag; + } + + public String getCardStatus() { + return cardStatus; + } + + public void setCardStatus(String cardStatus) { + this.cardStatus = cardStatus; + } + + public String getCardContent() { + return cardContent; + } + + public void setCardContent(String cardContent) { + this.cardContent = cardContent; + } + + + + public String getBgUrl() { + return bgUrl; + } + + public void setBgUrl(String bgUrl) { + this.bgUrl = bgUrl; + } + + public String getContentColor() { + return contentColor; + } + + public void setContentColor(String contentColor) { + this.contentColor = contentColor; + } + + public String getStoreId() { + return storeId; + } + + public void setStoreId(String storeId) { + this.storeId = storeId; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + @Override + public String toString() { + return "SegchkUserWebCardResp{" + + "providerId='" + providerId + '\'' + + ", cardName='" + cardName + '\'' + + ", storeName='" + storeName + '\'' + + ", storeId='" + storeId + '\'' + + ", useCount=" + useCount + + ", leftCount=" + leftCount + + ", effectiveTime=" + effectiveTime + + ", typeFlag=" + typeFlag + + ", cardStatus='" + cardStatus + '\'' + + ", cardContent='" + cardContent + '\'' + + ", bgUrl='" + bgUrl + '\'' + + ", contentColor='" + contentColor + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebReq.java new file mode 100644 index 0000000..0c5c3b2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebReq.java @@ -0,0 +1,112 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserWebReq extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long userId; + + /** 用户手机号 */ + @Excel(name = "用户手机号") + private String phoneNo; + + /** 微信唯一识别号 */ + @Excel(name = "微信唯一识别号") + private String openid; + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + /** 用户身份,0运营商,1商家,2用户 */ + @Excel(name = "用户身份") + private Integer userLevel; + + /** 身份证号码 */ + @Excel(name = "身份证号码") + private String cardID; + + /** 查询用户卡类型,0会员卡,1优惠券 */ + @Excel(name = "查询用户卡类型") + private Integer cardFlag; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public String getCardID() { + return cardID; + } + + public void setCardID(String cardID) { + this.cardID = cardID; + } + + public Integer getUserLevel() { + return userLevel; + } + + public void setUserLevel(Integer userLevel) { + this.userLevel = userLevel; + } + + public Integer getCardFlag() { + return cardFlag; + } + + public void setCardFlag(Integer cardFlag) { + this.cardFlag = cardFlag; + } + + @Override + public String toString() { + return "SegchkUserWebReq{" + + "userId=" + userId + + ", phoneNo='" + phoneNo + '\'' + + ", openid='" + openid + '\'' + + ", providerId=" + providerId + + ", userLevel=" + userLevel + + ", cardID='" + cardID + '\'' + + ", cardFlag=" + cardFlag + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebResp.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebResp.java new file mode 100644 index 0000000..1840d66 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/SegchkUserWebResp.java @@ -0,0 +1,307 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.math.BigDecimal; + +/** + * seg用户基本信息对象 segchk_user_basic_info + * + * @author yinzhiying + * @date 2021-07-01 + */ +public class SegchkUserWebResp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + /** 运营商id,全局唯一 */ + @Excel(name = "运营商id,全局唯一") + private Long providerId; + + + /** 用户id,全局唯一 */ + @Excel(name = "用户id,全局唯一") + private Long userId; + + /** 用户角色 */ + @Excel(name = "用户角色") + private Integer userLevel; + + /** 用户手机号 */ + @Excel(name = "用户手机号") + private String phoneNo; + + /** 用户名称 */ + @Excel(name = "用户名称") + private String userName; + + /** 微信唯一识别号 */ + @Excel(name = "微信唯一识别号") + private String openid; + + /** 注册地区 */ + @Excel(name = "注册地区") + private String districtName; + + /** 推荐人id */ + @Excel(name = "推荐人id") + private String recommenderId; + + /** 推荐人角色 */ + @Excel(name = "推荐人角色") + private String recommenderLevel; + + /** 推荐人名称 */ + @Excel(name = "推荐人名称") + private String recommenderName; + + /** 用户头像 */ + @Excel(name = "用户头像") + private String userIcon; + + /** 是否实名认证 */ + @Excel(name = "是否实名认证") + private Integer iscertified; + + /** 账号余额 */ + @Excel(name = "账号余额") + private BigDecimal account = BigDecimal.valueOf(0.0); + + /** 核消次数 */ + @Excel(name = "核消次数") + private Long chkCount; + + /** 充值次数 */ + @Excel(name = "充值次数") + private Long chargeCount; + + /** 提现次数 */ + @Excel(name = "提现次数") + private Long cashCount; + + /** 未读消息数量 */ + @Excel(name = "未读消息数量") + private Long msgCount; + + /** 可用卡数量 */ + @Excel(name = "可用卡数量") + private Long cardCount; + + /** 优惠券数量 */ + @Excel(name = "优惠券数量") + private Long storeCardCount; + + /** 商家数量 */ + @Excel(name = "商家数量") + private Long storeCount; + + /** 有效预约单数量 */ + @Excel(name = "预约单数量") + private Long likegoCount; + + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getPhoneNo() { + return phoneNo; + } + + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getUserIcon() { + return userIcon; + } + + public void setUserIcon(String userIcon) { + this.userIcon = userIcon; + } + + public Integer getIscertified() { + return iscertified; + } + + public void setIscertified(Integer iscertified) { + this.iscertified = iscertified; + } + + public BigDecimal getAccount() { + return account; + } + + public void setAccount(BigDecimal account) { + this.account = account; + } + + public Long getChkCount() { + return chkCount; + } + + public void setChkCount(Long chkCount) { + this.chkCount = chkCount; + } + + public Long getChargeCount() { + return chargeCount; + } + + public void setChargeCount(Long chargeCount) { + this.chargeCount = chargeCount; + } + + public Long getCashCount() { + return cashCount; + } + + public void setCashCount(Long cashCount) { + this.cashCount = cashCount; + } + + public Long getMsgCount() { + return msgCount; + } + + public void setMsgCount(Long msgCount) { + this.msgCount = msgCount; + } + + public Long getCardCount() { + return cardCount; + } + + public void setCardCount(Long cardCount) { + this.cardCount = cardCount; + } + + public Long getStorecardCount() { + return storeCardCount; + } + + public void setStorecardCount(Long storecardCount) { + this.storeCardCount = storecardCount; + } + + public Long getProviderId() { + return providerId; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + public Long getStoreCardCount() { + return storeCardCount; + } + + public void setStoreCardCount(Long storeCardCount) { + this.storeCardCount = storeCardCount; + } + + public Long getStoreCount() { + return storeCount; + } + + public void setStoreCount(Long storeCount) { + this.storeCount = storeCount; + } + + public Long getLikegoCount() { + return likegoCount; + } + + public void setLikegoCount(Long likegoCount) { + this.likegoCount = likegoCount; + } + + public Integer getUserLevel() { + return userLevel; + } + + public void setUserLevel(Integer userLevel) { + this.userLevel = userLevel; + } + + public String getDistrictName() { + return districtName; + } + + public void setDistrictName(String districtName) { + this.districtName = districtName; + } + + public String getRecommenderId() { + return recommenderId; + } + + public void setRecommenderId(String recommenderId) { + this.recommenderId = recommenderId; + } + + public String getRecommenderLevel() { + return recommenderLevel; + } + + public void setRecommenderLevel(String recommenderLevel) { + this.recommenderLevel = recommenderLevel; + } + + public String getRecommenderName() { + return recommenderName; + } + + public void setRecommenderName(String recommenderName) { + this.recommenderName = recommenderName; + } + + @Override + public String toString() { + return "SegchkUserWebResp{" + + "providerId=" + providerId + + ", userId=" + userId + + ", userLevel=" + userLevel + + ", phoneNo='" + phoneNo + '\'' + + ", userName='" + userName + '\'' + + ", openid='" + openid + '\'' + + ", districtName='" + districtName + '\'' + + ", recommenderId='" + recommenderId + '\'' + + ", recommenderLevel='" + recommenderLevel + '\'' + + ", recommenderName='" + recommenderName + '\'' + + ", userIcon='" + userIcon + '\'' + + ", iscertified=" + iscertified + + ", account=" + account + + ", chkCount=" + chkCount + + ", chargeCount=" + chargeCount + + ", cashCount=" + cashCount + + ", msgCount=" + msgCount + + ", cardCount=" + cardCount + + ", storeCardCount=" + storeCardCount + + ", storeCount=" + storeCount + + ", likegoCount=" + likegoCount + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/StoreSelfCard.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/StoreSelfCard.java new file mode 100644 index 0000000..2c7c288 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/StoreSelfCard.java @@ -0,0 +1,94 @@ +package com.ruoyi.segchk.domain; + +import com.ruoyi.common.core.domain.BaseEntity; + +public class StoreSelfCard extends BaseEntity { + + private Long likegoId; + private Long userId; + private Long cardId; + private Long lableId; + private Long storeId; + private Integer typeId; + private Integer totalCount; + private String freeContent; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getCardId() { + return cardId; + } + + public void setCardId(Long cardId) { + this.cardId = cardId; + } + + public Integer getTypeId() { + return typeId; + } + + public void setTypeId(Integer typeId) { + this.typeId = typeId; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + public String getFreeContent() { + return freeContent; + } + + public void setFreeContent(String freeContent) { + this.freeContent = freeContent; + } + + public Long getLableId() { + return lableId; + } + + public void setLableId(Long lableId) { + this.lableId = lableId; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + + public Long getLikegoId() { + return likegoId; + } + + public void setLikegoId(Long likegoId) { + this.likegoId = likegoId; + } + @Override + public String + toString() { + return "StoreSelfCard{" + + "likegoId=" + likegoId + + "userId=" + userId + + ", cardId=" + cardId + + ", lableId=" + lableId + + ", storeId=" + storeId + + ", typeId=" + typeId + + ", totalCount=" + totalCount + + ", freeContent='" + freeContent + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/WeChatCustomerLink.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/WeChatCustomerLink.java new file mode 100644 index 0000000..8530871 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/domain/WeChatCustomerLink.java @@ -0,0 +1,128 @@ +package com.ruoyi.segchk.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ruoyi.util.CommonConstant; +import org.springframework.util.StringUtils; + +import java.io.Serializable; + +/** + * 微信用户关联实体类 + */ +public class WeChatCustomerLink implements Serializable { + /** + * 主键 + */ + private long id = -1; + /** + * 联合登录id + */ + private String unionId; + /** + * 微信用户唯一标识 + */ + private String openId; + /** + * 小程序openId + */ + private String appletOpenId; + /** + * providerId + */ + private String providerId; + /** + * 用户id + */ + private Long userId = CommonConstant.NO_CUSTOMER_ID; + + public WeChatCustomerLink() { + } + + public WeChatCustomerLink(String openId, String unionId) { + this.openId = openId; + this.unionId = unionId; + } + + /** + * 是否绑定 绑定返回true + */ + @JsonIgnore + public boolean isBind() { + return this.userId != CommonConstant.NO_CUSTOMER_ID; + } + + /** + * 判断是否有openId + * + * @return 有返回true, 否则返回false + */ + public boolean hasOpenId() { + return !StringUtils.isEmpty(openId); + } + + /** + * 判断是否有小程序openId + * + * @return 有返回true, 否则返回false + */ + public boolean hasAppletOpenId() { + return !StringUtils.isEmpty(appletOpenId); + } + + public String getUnionId() { + return unionId; + } + + public void setUnionId(String unionId) { + this.unionId = unionId; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getAppletOpenId() { + return appletOpenId; + } + + public void setAppletOpenId(String appletOpenId) { + this.appletOpenId = appletOpenId; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + @Override + public String toString() { + return "WeChatCustomerLink{" + + "id=" + id + + ", unionId='" + unionId + '\'' + + ", openId='" + openId + '\'' + + ", appletOpenId='" + appletOpenId + '\'' + + ", providerId='" + providerId + '\'' + + ", userId=" + userId + + '}'; + } +} + diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkProviderIndexMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkProviderIndexMapper.java new file mode 100644 index 0000000..72183f5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkProviderIndexMapper.java @@ -0,0 +1,66 @@ +package com.ruoyi.segchk.mapper; + +import com.ruoyi.segchk.domain.*; + +import java.util.List; + +/** + * seg运营商管理Mapper接口 + * + * @author yinzhiying + * @date 2021-08-23 + */ +public interface SegchkProviderIndexMapper +{ + + /** + * 查询运营商个人中心信息 + * + * @param segchkUserWebReq 查询实体对象 + * @return 结果 + */ + public SegchkUserWebResp selectSegchkProviderWebInfo(SegchkUserWebReq segchkUserWebReq); + + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreServiceList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreServiceDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 返回运营商openid + * + * @param providerId 运营商id + * @return 结果 + */ + public String selectProviderOpenIdById(Long providerId); + + public String selectSegchkProviderName(String providerId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreIndexMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreIndexMapper.java new file mode 100644 index 0000000..44dcfdc --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkStoreIndexMapper.java @@ -0,0 +1,154 @@ +package com.ruoyi.segchk.mapper; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.domain.WeChatCustomerLink; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public interface SegchkStoreIndexMapper { + /** + * 以会员卡为主标签,结合其他如关键字标签,优惠券标签显示商家列表 + * @param segchkStoreWebReq 根据运营商,商户,标签等查询相应的商户列表 + * @return + */ + public List selectSegchkStoreList(SegchkStoreWebReq segchkStoreWebReq); + + /** + * 以会员卡为主标签,结合其他如关键字标签,优惠券标签显示商家列表 + * @param segchkStoreWebReq 根据运营商,商户,标签等查询相应的商户列表 + * @return + */ + public List selectSegchkStoreListByOneLable(SegchkStoreWebReq segchkStoreWebReq); + + + /** + * 以会员卡为主标签,结合其他如关键字标签,优惠券标签显示商家列表 + * @param segchkStoreWebReq 根据运营商,商户,标签等查询相应的商户列表 + * @return + */ + public List selectSegchkStoreListByAll(SegchkStoreWebReq segchkStoreWebReq); + + /** + * 标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreRecommendLableList(Long providerId); + + /** + * 标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreLableList(Long providerId); + + /** + * 商户查找 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreSearch(SegchkStoreWebReq segchkStoreWebReq); + + public SegchkStoreBasicInfoWebResp selectSegchkStoreDetails(SegchkStoreWebReq segchkStoreWebReq); + + public List selectSegchkStoreComments(SegchkStoreWebReq segchkStoreWebReq); + + + /** + * 根据商户id,查询商户个人中心信息 + * + * @param segchkUserWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public SegchkUserWebResp selectSegchkStoreWebInfo(SegchkUserWebReq segchkUserWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreServiceList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreServiceDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户提现记录 + * + * @param segchkUserWebReq@return seg首页轮播图管理 + */ + public List selectStoreCashList(SegchkUserWebReq segchkUserWebReq); + + /** + * 根据商户id,查询商户的预约列表 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectStoreUserLikeGoList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据行政区域id,查询对应运营商id,如果没有,则返回默认运营商id + * + * @param params 行政区代码,以及默认展示行政地区代码 + * @return seg首页轮播图管理 + */ + public HashMap selectSegchkProviderBycode(Map params); + + public List selectSegchkCarouseStoreList(SegchkCarouseMgt segchkCarouseMgt); + + + /** + * 根据运营商返回seg首页推荐商户实体列表 + * + * @param segchkRecommenderStoreWebReq seg首页推荐商户运营商id + * @return 结果 + */ + public List selectSegchkRecommenderStoreListWeb(SegchkRecommenderStoreWebReq segchkRecommenderStoreWebReq); + + + /** + * 返回商户openid + * + * @param storeId 商户id + * @return 结果 + */ + public WeChatCustomerLink selectStoreOpenIdById(Long storeId); + + public Integer isCollectByUser(Map params); + + public String selectSegchkStoreName(String storeId); + + public int addAccountByReward(SegchkChargeReward segchkChargeReward); + + Long getVipCardFromLikego(Long likegoId); + + public int addCommentAccByComment(Long commentId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkUserIndexMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkUserIndexMapper.java new file mode 100644 index 0000000..90f09fd --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/mapper/SegchkUserIndexMapper.java @@ -0,0 +1,136 @@ +package com.ruoyi.segchk.mapper; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.domain.WeChatCustomerLink; + +import java.util.List; +import java.util.Map; + +public interface SegchkUserIndexMapper { + /** + * 查询seg用户基本信息 + * + * @param segchkUserWebReq 前端查询用户中心对象实体 + * @return seg用户基本信息 + */ + public SegchkUserWebResp selectSegchkUserWebInfo(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户核消列表 + * + * @param segchkUserWebReq 前端查询用户中心对象实体 + * @return seg用户基本信息 + */ + public List selectUserServiceCHKList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户会员卡列表 + * + * @param segchkUserWebReq 前端查询用户中心对象实体 + * @return seg用户基本信息 + */ + public List selectUserCardList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户赠卡及优惠券列表 + * + * @param segchkUserWebReq 前端查询用户中心对象实体 + * @return seg用户基本信息 + */ + public List selectUserPerformanceList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户收藏列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + public List selectUserCollectList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户预约列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + public List selectUserLikGoList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户充值列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + public List selectUserChargeList(SegchkUserWebReq segchkUserWebReq); + + + /** + * 查询seg用户提现列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + public List selectUserCashList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户消息列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + public List selectUserMsgList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户预约时可用卡列表 + * + * @param segchkServiceOrderWebReq + * @return seg用户扩展信息 + */ + public List selectUserOrderPredCardListWebInfo(SegchkServiceOrderWebReq segchkServiceOrderWebReq); + + /** + * 查询seg用户预约时可用卡列表 + * + * @param segchkServiceOrderWebReq + * @return seg用户扩展信息 + */ + public List selecttest(SegchkServiceOrderWebReq segchkServiceOrderWebReq); + + /** + * 查询seg用户我想去订单的有效信息 + * + * @param likegoId + * @return seg用户扩展信息 + */ + public SegchkServiceOrderChkTestResp selectUserOrderPredInfo(Long likegoId); + + /** + * 查询seg用户可以充值的卡信息 + * + * @param segchkUserWebReq + * @return seg用户扩展信息 + */ + public List selectSegchkUserChargePre(SegchkUserWebReq segchkUserWebReq); + + public SegchkUserLevelInfo selectUserLevelByMobile(String phoneno); + + public int userIsExit(Map parmMap); + + public int providerIsExit(Map parmMap); + public int storeIsExit(Map parmMap); + + public int recommenderIsExit(Map parmMap); + + int updateSegchkProviderWechat(SegchkUserWechat segchkUserWechat); + + public int updateSegchkStoreWechat(SegchkUserWechat segchkUserWechat); + + public int updateSegchkUserWechat(SegchkUserWechat segchkUserWechat); + + public WeChatCustomerLink getUserWechatOpenId(Long userId); + + public String selectSegchkUserName(String userId); + + public SegchkChargeReward selectSegchkRewardInfoForCharge(Map paramsMap); + + int addAccountByReward(SegchkChargeReward segchkChargeReward); + + Map getCardInfo(Map paramsMap); + + SegchkChargeReward selectSegchkRewardInfoForCheck(Map params); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkProviderIndexService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkProviderIndexService.java new file mode 100644 index 0000000..eda3586 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkProviderIndexService.java @@ -0,0 +1,49 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.*; + +import java.util.List; + +/** + * seg用户基本信息Service接口 + * + * @author yinzhiying + * @date 2021-07-01 + */ +public interface ISegchkProviderIndexService +{ + + /** + * 查询运营商个人中心信息 + * + * @param segchkUserWebReq 查询实体对象 + * @return 结果 + */ + public SegchkUserWebResp selectSegchkProviderWebInfo(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询运营商下核消,售卡统计 + * + * @param segchkServiceAndSaleWebReq 查询实体对象 + * @return 结果 + */ + public List selectProviderServiceAndSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 查询运营商下核消,售卡统计详情 + * + * @param segchkServiceAndSaleWebReq 查询实体对象 + * @return 结果 + */ + public List selectProviderServiceAndSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 返回运营商openid + * + * @param userId 运营商id + * @return 结果 + */ + public String selectWeChatInfoByProviderId(Long userId); + + public String selectSegchkProviderName(String recommenderId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkStoreIndexService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkStoreIndexService.java new file mode 100644 index 0000000..a4b7f5e --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkStoreIndexService.java @@ -0,0 +1,191 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.domain.WeChatCustomerLink; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * seg首页轮播图管理Service接口 + * + * @author yinzhiying + * @date 2021-07-01 + */ +public interface ISegchkStoreIndexService +{ + /** + * 商户列表 + * + * @param segchkStoreWebReq seg首页轮播图管理ID + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreList(SegchkStoreWebReq segchkStoreWebReq); + + /** + * 标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + public List selectSegchkRecommendLableList(Long providerId); + + /** + * 全量标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + public List selectSegchkLableList(Long providerId); + + /** + * 商户查找 + * + * @param segchkStoreWebReq 搜索对象 + * @return 商户查找 + */ + public List selectSegchkStoreSearch(SegchkStoreWebReq segchkStoreWebReq); + + + /** + * 商户详情页展示 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public SegchkStoreBasicInfoWebResp selectSegchkStoreDetails(SegchkStoreWebReq segchkStoreWebReq); + + /** + * 根据商户id,查询商户相关评价列表 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectSegchkStoreComments(SegchkStoreWebReq segchkStoreWebReq); + + /** + * 根据商户id,查询商户个人中心信息 + * + * @param segchkUserWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public SegchkUserWebResp selectSegchkStoreWebInfo(SegchkUserWebReq segchkUserWebReq); + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectStoreServiceAndSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户核消详情,或售卡详情 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectStoreServiceAndSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + /** + * 根据商户id,查询商户提现记录 + * + * @param segchkUserWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectStoreCashList(SegchkUserWebReq segchkUserWebReq); + + + /** + * 根据商户id,查询商户的预约列表 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + public List selectStoreUserLikeGoList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq); + + + /** + * 根据行政区域id,查询对应运营商id,如果没有,则返回默认运营商id + * + * @param adcode 行政区代码 + * @return seg首页轮播图管理 + */ + public HashMap getProvider(Map adcode); + + /** + * 根据提现id,进行提现结果保存,及余额更新 + * + * @param chargeId 行政区代码 + * @param ret 行政区代码 + * @return seg首页轮播图管理 + */ + public void cashRet(String chargeId, int ret); + + /** + * 根据运营商id,获取相应的轮播图列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + public List getBanners(Long providerId); + + /** + * 根据用户提交信息进行修改 + * + * @param segchkUserSetInfoReq 用户评价提交实体 + * @return 更新结果 + */ + public int updateUserInfo(SegchkUserSetInfoReq segchkUserSetInfoReq); + + + /** + * 返回seg首页推荐商户信息 + * + * @param segchkRecommenderStoreWebReq seg首页推荐商户ID + * @return 结果 + */ + public List selectSegchkRecommenderStoreListByProvider(SegchkRecommenderStoreWebReq segchkRecommenderStoreWebReq); + + /** + * 返回商户openid + * + * @param userId 商户id + * @return 结果 + */ + public WeChatCustomerLink selectWeChatInfoByStoreId(Long userId); + + + /** + * 验证推荐人是否存在 + * + * @param recommenderId 推荐人id + * @param recommenderLevel 推荐人角色 + * @return 结果 + */ + int recommenderIsExit(String recommenderId, String recommenderLevel, String providerId); + + + /** + * 检查该商户是否已被当前用户收藏 + * + * @param providerId 推荐人id + * @param storeId 推荐人角色 + * @param userId 推荐人角色 + * @return 是否收藏,1已收藏,0未收藏 + */ + Integer isCollectByUser(Long providerId, Long storeId, Long userId); + + public String selectSegchkStoreName(String storeId); + + Integer addStoreSelfCard(SegchkStoreSelfMgt segchkStoreSelfMgt); + + public int addAccountByReward(SegchkChargeReward segchkChargeReward); + + Long getVipCardFromLikego(Long likegoId); + + HashMap getCustomService(Long providerId); + + public int addCommentAccByComment(Long commentId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCashService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCashService.java new file mode 100644 index 0000000..f5667d6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCashService.java @@ -0,0 +1,63 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.SegchkUserCash; + +import java.util.List; + +/** + * seg用户提现记录Service接口 + * + * @author yinzhiying + * @date 2021-08-23 + */ +public interface ISegchkUserCashService +{ + /** + * 查询seg用户提现记录 + * + * @param cashId seg用户提现记录主键 + * @return seg用户提现记录 + */ + public SegchkUserCash selectSegchkUserCashByCashId(Long cashId); + + /** + * 查询seg用户提现记录列表 + * + * @param segchkUserCash seg用户提现记录 + * @return seg用户提现记录集合 + */ + public List selectSegchkUserCashList(SegchkUserCash segchkUserCash); + + /** + * 新增seg用户提现记录 + * + * @param segchkUserCash seg用户提现记录 + * @return 结果 + */ + public int insertSegchkUserCash(SegchkUserCash segchkUserCash); + + /** + * 修改seg用户提现记录 + * + * @param segchkUserCash seg用户提现记录 + * @return 结果 + */ + public int updateSegchkUserCash(SegchkUserCash segchkUserCash); + + /** + * 批量删除seg用户提现记录 + * + * @param cashIds 需要删除的seg用户提现记录主键集合 + * @return 结果 + */ + public int deleteSegchkUserCashByCashIds(Long[] cashIds); + + /** + * 删除seg用户提现记录信息 + * + * @param cashId seg用户提现记录主键 + * @return 结果 + */ + public int deleteSegchkUserCashByCashId(Long cashId); + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCollectService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCollectService.java new file mode 100644 index 0000000..d3ddda2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserCollectService.java @@ -0,0 +1,70 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.SegchkUserCollect; + +import java.util.List; + +/** + * seg用户收藏记录Service接口 + * + * @author yinzhiying + * @date 2021-08-23 + */ +public interface ISegchkUserCollectService +{ + /** + * 查询seg用户收藏记录 + * + * @param collectId seg用户收藏记录主键 + * @return seg用户收藏记录 + */ + public SegchkUserCollect selectSegchkUserCollectByCollectId(Long collectId); + + /** + * 查询seg用户收藏记录列表 + * + * @param segchkUserCollect seg用户收藏记录 + * @return seg用户收藏记录集合 + */ + public List selectSegchkUserCollectList(SegchkUserCollect segchkUserCollect); + + /** + * 新增seg用户收藏记录 + * + * @param segchkUserCollect seg用户收藏记录 + * @return 结果 + */ + public int insertSegchkUserCollect(SegchkUserCollect segchkUserCollect); + + /** + * 修改seg用户收藏记录 + * + * @param segchkUserCollect seg用户收藏记录 + * @return 结果 + */ + public int updateSegchkUserCollect(SegchkUserCollect segchkUserCollect); + + /** + * 批量删除seg用户收藏记录 + * + * @param collectIds 需要删除的seg用户收藏记录主键集合 + * @return 结果 + */ + public int deleteSegchkUserCollectByCollectIds(Long[] collectIds); + + /** + * 删除seg用户收藏记录信息 + * + * @param collectId seg用户收藏记录主键 + * @return 结果 + */ + public int deleteSegchkUserCollectByCollectId(Long collectId); + + /** + * 批量删除seg用户收藏记录 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteSegchkUserCollectByIds(String ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserIndexService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserIndexService.java new file mode 100644 index 0000000..b7d487a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserIndexService.java @@ -0,0 +1,295 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.util.Claims; +import com.ruoyi.util.CommonResponse; +import com.ruoyi.util.bean.PrepayResult; +import com.ruoyi.util.bean.WxTransferResult; + +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * seg用户基本信息Service接口 + * + * @author yinzhiying + * @date 2021-07-01 + */ +public interface ISegchkUserIndexService +{ + /** + * 查询seg用户中心信息 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public SegchkUserWebResp selectSegchkUserWebInfo(SegchkUserWebReq segchkUserWebReq); + + + /** + * 查询seg用户核消列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserServiceCHKList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户可用会员卡列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserCardList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户收藏列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserCollectList(SegchkUserWebReq segchkUserWebReq); + + + /** + * 查询seg用户预约列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserLikGoList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户充值列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserChargeList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户提现列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserCashList(SegchkUserWebReq segchkUserWebReq); + + /** + * 查询seg用户消息列表 + * + * @param segchkUserWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserMsgList(SegchkUserWebReq segchkUserWebReq); + + + /** + * 查询seg用户预约可用卡券列表 + * + * @param segchkServiceOrderWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + public List selectUserOrderPredCardListWebInfo(SegchkServiceOrderWebReq segchkServiceOrderWebReq); + + /** + * 根据用户核消二维码提取出来相应的信息进行核消,1、检查核卡是否可以核消(防止该卡已经在该商家不能再次核消),2、检查该预约id,是否已经使用(防止多次预约核消使用) + * + * @param segchkUserLikego seg用户想去记录实体 + * @return 结果 + */ + public void CheckUserServiceChk(SegchkUserLikego segchkUserLikego); + + public SegchkServiceOrderChkTestResp selectUserOrderPredInfo(Long likeGoId); + + /** + * 根据核查结果进行核消。说明已经满足核消条件 + * + * @param segchkServiceOrderChkTestResp 核消检查信息 + * @param likegoId 预约单id + * @param stoRewardWithChk + * @return 结果 + */ + public int OrderCheckTransaction(SegchkServiceOrderChkTestResp segchkServiceOrderChkTestResp, Long likegoId, Boolean stoRewardWithChk); + + /** + * 根据支付回调结果,进行相应的更新 + * + * @param chargeId 核消检查信息 + * @param ret 预约单id + * @return 结果 + */ + public void chargeRet(String chargeId, int ret); + + + /** + * 根据用户充值等信息获取相关的返利信息 + * + * @param params 充值信息 + * @return 结果 + */ + int makeChargeReward(Map params); + + /** + * 根据支用户id,运营商id,查询该用户可购买的卡 + * + * @param segchkUserWebReq 用户请示信息体 + * @return 结果 + */ + public List SegchkUserChargePre(SegchkUserWebReq segchkUserWebReq); + + + /** + * 根据支用户id,运营商id,用户充值时可用余额 + * + * @param segchkUserCharge 用户请示信息体 + * @return 结果 + */ + public BigDecimal getAccount(SegchkUserCharge segchkUserCharge); + + /** + * 根据用户id(或者商户id),运营商id,用户身份查询用户余额 + * + * @param segchkUserCashOpsReq 用户请示信息体 + * @param ip + * @return 结果 + */ + public int getAccountForCash(SegchkUserCashOpsReq segchkUserCashOpsReq, String ip); + + /** + * 根据提现id,进行提现结果保存,及余额更新 + * + * @param chargeId 行政区代码 + * @param ret 行政区代码 + * @return seg首页轮播图管理 + */ + public void cashRet(String chargeId, int ret); + + /** + * 新增用户评价 + * + * @param segchkServiceComment 用户评价提交实体 + * @return seg首页轮播图管理 + */ + public int insertSegchkServiceComment(SegchkServiceCommentUserReq segchkServiceComment); + + /** + * 根据评价id,查询用户评价 + * + * @param segchkServiceCommentUserReq 用户评价提交实体 + * @return seg首页轮播图管理 + */ + public SegchkServiceComment selectSegchkServiceComment(SegchkServiceCommentUserReq segchkServiceCommentUserReq); + + /** + * 根据用户提交信息进行修改 + * + * @param segchkUserSetInfoReq 用户评价提交实体 + * @return 更新结果 + */ + public int updateUserInfo(SegchkUserSetInfoReq segchkUserSetInfoReq); + + /** + * 根据用户提交信息实名设置 + * + * @param segchkUserCertificationInfo 用户提交实体 + * @return 更新结果 + */ + public int userCerticify(SegchkUserCertificationInfo segchkUserCertificationInfo); + + /** + * 根据用户信息返回用户身份 + * + * @param phoneno 用户信息 + * @return 更新结果 + */ + public SegchkUserLevelInfo selectUserLevelByMobile(String phoneno); + + /** + * 根据用户信息注册用户基本信息表 + * + * @param segchkUserBasicInfo 用户信息 + * @return 插入结果 + */ + public int addUserBasicInfo(SegchkUserBasicInfo segchkUserBasicInfo); + + /** + * 根据推荐人信息,检查推荐人是否存在 + * + * @param parmMap 推荐人信息 + * @return 查询记录数 + */ + public int recommenderIsExit(Map parmMap); + + /** + * 根据推荐人信息,更新用户扩展信息表 + * + * @param segchkUserExtInfo 推荐人信息 + * @return 查询记录数 + */ + public int insertUserExtInfo(SegchkUserExtInfo segchkUserExtInfo); + + + /** + * 根据用户基本信息查找用户微信信息 + * + * @param segchkUserLevelInfo 用户基本信息 + * @return 查询记录数 + */ + public String getWeChatInfoByUserId(SegchkUserLevelInfo segchkUserLevelInfo); + + /** + * 根据用户信息,更新用户微信信息表 + * + * @param segchkUserWechat 用户基本信息 + * @param userLevel + * @return 查询记录数 + */ + public int updateWeChatInfoByUserId(SegchkUserWechat segchkUserWechat, String userLevel); + + /** + * 微信小程序支付 + * + * @param orderCode 订单code + * @param userId 用户id + * @param ip 请求真实ip + * @param type 支付类型 1:订单支付 2:预存款充值 ---> 1用户支付,2商户支付 + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -3:没有待支付的订单 -5:微信生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + CommonResponse wechatAppletPay(String orderCode, Long userId, Long providerId, String ip, int type); + + /** + * 微信小程序提现 + * + * @param orderCode 订单code + * @param userId 用户id + * @param providerId 用户id + * @param ip 请求真实ip + * @param type 支付类型 1:订单支付 2:预存款充值 ---> 1用户支付,2商户支付 + * @param openId + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -3:没有待支付的订单 -5:微信生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + CommonResponse wechatAppletTransfers(String orderCode, Long userId, Long providerId, String ip, int type, String openId); + + /** + * 微信回调(小程序) 回调 + * + * @param inputStream 微信回调参数 + * @return 返回码 1:成功 -1:没有订单 + */ + int weChatAppletNotify(InputStream inputStream); + + /** + * 根据预约单,查询相关信息 + * + * @param segchkUserLikego 包含预约单id + * @return SegchkUserLikego + */ + public SegchkUserLikego selectUserLikeGo(SegchkUserLikego segchkUserLikego); + + int insertSegchkUserCharge(SegchkUserCharge segchkUserCharge); + + SegchkUserWechat queryWeChatInfoByUserId(Claims claims); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserLikegoService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserLikegoService.java new file mode 100644 index 0000000..087870e --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserLikegoService.java @@ -0,0 +1,62 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.SegchkUserLikego; + +import java.util.List; + +/** + * seg用户想去记录Service接口 + * + * @author yinzhiying + * @date 2021-08-23 + */ +public interface ISegchkUserLikegoService +{ + /** + * 查询seg用户想去记录 + * + * @param likegoId seg用户想去记录主键 + * @return seg用户想去记录 + */ + public SegchkUserLikego selectSegchkUserLikegoByLikegoId(Long likegoId); + + /** + * 查询seg用户想去记录列表 + * + * @param segchkUserLikego seg用户想去记录 + * @return seg用户想去记录集合 + */ + public List selectSegchkUserLikegoList(SegchkUserLikego segchkUserLikego); + + /** + * 新增seg用户想去记录 + * + * @param segchkUserLikego seg用户想去记录 + * @return 结果 + */ + public int insertSegchkUserLikego(SegchkUserLikego segchkUserLikego); + + /** + * 修改seg用户想去记录 + * + * @param segchkUserLikego seg用户想去记录 + * @return 结果 + */ + public int updateSegchkUserLikego(SegchkUserLikego segchkUserLikego); + + /** + * 批量删除seg用户想去记录 + * + * @param likegoIds 需要删除的seg用户想去记录主键集合 + * @return 结果 + */ + public int deleteSegchkUserLikegoByLikegoIds(Long[] likegoIds); + + /** + * 删除seg用户想去记录信息 + * + * @param likegoId seg用户想去记录主键 + * @return 结果 + */ + public int deleteSegchkUserLikegoByLikegoId(Long likegoId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserWechatService.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserWechatService.java new file mode 100644 index 0000000..b1ec5f0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/ISegchkUserWechatService.java @@ -0,0 +1,62 @@ +package com.ruoyi.segchk.service; + +import com.ruoyi.segchk.domain.SegchkUserWechat; + +import java.util.List; + +/** + * seg用户微信信息Service接口 + * + * @author yinzhiying + * @date 2021-08-23 + */ +public interface ISegchkUserWechatService +{ + /** + * 查询seg用户微信信息 + * + * @param userId seg用户微信信息主键 + * @return seg用户微信信息 + */ + public SegchkUserWechat selectSegchkUserWechatByUserId(Long userId); + + /** + * 查询seg用户微信信息列表 + * + * @param segchkUserWechat seg用户微信信息 + * @return seg用户微信信息集合 + */ + public List selectSegchkUserWechatList(SegchkUserWechat segchkUserWechat); + + /** + * 新增seg用户微信信息 + * + * @param segchkUserWechat seg用户微信信息 + * @return 结果 + */ + public int insertSegchkUserWechat(SegchkUserWechat segchkUserWechat); + + /** + * 修改seg用户微信信息 + * + * @param segchkUserWechat seg用户微信信息 + * @return 结果 + */ + public int updateSegchkUserWechat(SegchkUserWechat segchkUserWechat); + + /** + * 批量删除seg用户微信信息 + * + * @param userIds 需要删除的seg用户微信信息主键集合 + * @return 结果 + */ + public int deleteSegchkUserWechatByUserIds(Long[] userIds); + + /** + * 删除seg用户微信信息信息 + * + * @param userId seg用户微信信息主键 + * @return 结果 + */ + public int deleteSegchkUserWechatByUserId(Long userId); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/ISegchkStoreIndexServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/ISegchkStoreIndexServiceImpl.java new file mode 100644 index 0000000..6ba3dcf --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/ISegchkStoreIndexServiceImpl.java @@ -0,0 +1,393 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.mapper.SegchkIndexStoreAccountMapper; +import com.ruoyi.segchk.mapper.SegchkStoreCashMapper; +import com.ruoyi.segchk.mapper.SegchkStoreIndexMapper; +import com.ruoyi.segchk.mapper.SegchkStoreSecurityMapper; +import com.ruoyi.segchk.service.*; +import com.ruoyi.segchk.domain.WeChatCustomerLink; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class ISegchkStoreIndexServiceImpl implements ISegchkStoreIndexService { + + private static final Logger logger = LoggerFactory.getLogger(ISegchkStoreIndexServiceImpl.class); + + @Autowired + private SegchkStoreIndexMapper segchkStoreIndexMapper; + + @Autowired + private SegchkStoreCashMapper segchkStoreCashMapper; + + @Autowired + private SegchkIndexStoreAccountMapper segchkIndexStoreAccountMapper; + + @Autowired + private SegchkStoreSecurityMapper segchkStoreSecurityMapper; + + @Autowired + private ISegchkUserIndexService segchkUserIndexService; + + @Autowired + private ISegchkProviderMgtService segchkProviderMgtService; + + @Autowired + private ISegchkPreferenceLableService segchkPreferenceLableService; + + @Autowired + private ISegchkStoreSelfMgtService segchkStoreSelfMgtService; + /** + * 根据标签id,商户列表 + * + * @param segchkStoreWebReq seg首页轮播图管理ID + * @return seg首页轮播图管理 + */ + @Override + public List selectSegchkStoreList(SegchkStoreWebReq segchkStoreWebReq) { + + if(segchkStoreWebReq.getSortType() == null){ + segchkStoreWebReq.setSortType(0); + } + boolean cardempty = ObjectUtils.isEmpty(segchkStoreWebReq.getCardId()); + boolean lableempty = ObjectUtils.isEmpty(segchkStoreWebReq.getTypeId()); + if(cardempty && lableempty) { +// 全空,说明查询所有商家列表 + logger.debug("selectSegchkStoreList all with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreListByAll(segchkStoreWebReq); + } + else if(!lableempty && cardempty){ +// 标签不为空,全部会员卡 + logger.debug("selectSegchkStoreList one non-card lable with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreListByOneLable(segchkStoreWebReq); + } + + else if(lableempty && !cardempty){ +// 查询指定会员卡,全部标签 + segchkStoreWebReq.setLableId(segchkStoreWebReq.getCardId()); + segchkStoreWebReq.setTypeId(0); + segchkStoreWebReq.setCardId(null); + logger.debug("selectSegchkStoreList one card lable with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreListByOneLable(segchkStoreWebReq); + } + logger.debug("selectSegchkStoreList some lable with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreList(segchkStoreWebReq); + } + + /** + * 标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + @Override + public List selectSegchkRecommendLableList(Long providerId) { + logger.debug("selectSegchkRecommendLableList with: {}", providerId); + return segchkStoreIndexMapper.selectSegchkStoreRecommendLableList(providerId); + } + + /** + * 全量标签列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + @Override + public List selectSegchkLableList(Long providerId) { + logger.debug("selectSegchkLableList with {}", providerId); + return segchkStoreIndexMapper.selectSegchkStoreLableList(providerId); + } + + /** + * 商户查找 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public List selectSegchkStoreSearch(SegchkStoreWebReq segchkStoreWebReq) { + logger.debug("selectSegchkStoreSearch with: {}", segchkStoreWebReq.toString()); + segchkStoreWebReq.setSortType(0); + List segchkStoreIndexWebResps = segchkStoreIndexMapper.selectSegchkStoreSearch(segchkStoreWebReq); + boolean card_empty = ObjectUtils.isEmpty(segchkStoreWebReq.getCardId()); + boolean lable_empty = ObjectUtils.isEmpty(segchkStoreWebReq.getTypeId()); + List resps = segchkStoreIndexWebResps.parallelStream().filter(store -> { + List lables = store.getLables(); + boolean cardflag = card_empty ? true : lables.parallelStream().anyMatch(lable -> lable.getLableTypeId() == 0 && lable.getLableId() == segchkStoreWebReq.getCardId()); + boolean lableflag = lable_empty ? true : lables.parallelStream().anyMatch(lable -> lable.getLableTypeId() == segchkStoreWebReq.getTypeId() && lable.getLableId() == segchkStoreWebReq.getLableId()); + return cardflag && lableflag; + }).collect(Collectors.toList()); + return resps; + } + + /** + * 商户详情页展示 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public SegchkStoreBasicInfoWebResp selectSegchkStoreDetails(SegchkStoreWebReq segchkStoreWebReq) { + logger.debug("selectSegchkStoreDetails with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreDetails(segchkStoreWebReq); + } + + /** + * 根据商户id,查询商户相关评价列表 + * + * @param segchkStoreWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public List selectSegchkStoreComments(SegchkStoreWebReq segchkStoreWebReq) { + logger.debug("selectSegchkStoreComments with: {}", segchkStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkStoreComments(segchkStoreWebReq); + } + + /** + * 根据商户id,查询商户个人中心信息 + * + * @param segchkUserWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public SegchkUserWebResp selectSegchkStoreWebInfo(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectSegchkStoreWebInfo with: {}", segchkUserWebReq.toString()); + SegchkUserWebResp segchkUserWebResp = segchkStoreIndexMapper.selectSegchkStoreWebInfo(segchkUserWebReq); + segchkUserWebResp.setProviderId(segchkUserWebReq.getProviderId()); + segchkUserWebResp.setUserId(segchkUserWebReq.getUserId()); + return segchkUserWebResp; + } + + /** + * 根据商户id,查询商户核消统计,或售卡统计 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + * + * { + * "providerId": 4, + * "storeId": 123, + * "staticLevel": 0, + * "staticMonth": "6", + * "userLevel": 1, + * "srcFlag": 0 + * } + */ + @Override + public List selectStoreServiceAndSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq) { + logger.debug("selectStoreServiceAndSaleList with: {}", segchkServiceAndSaleWebReq.toString()); + if(segchkServiceAndSaleWebReq.getSrcFlag() == 0) + return segchkStoreIndexMapper.selectSegchkStoreServiceList(segchkServiceAndSaleWebReq); + else + return segchkStoreIndexMapper.selectSegchkStoreSaleList(segchkServiceAndSaleWebReq); + } + + /** + * 根据商户id,查询商户核消详情,或售卡详情 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public List selectStoreServiceAndSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq) { + logger.debug("selectStoreServiceAndSaleDetails with: {}", segchkServiceAndSaleWebReq.toString()); + if(segchkServiceAndSaleWebReq.getSrcFlag() == 0) + return segchkStoreIndexMapper.selectSegchkStoreServiceDetails(segchkServiceAndSaleWebReq); + else + return segchkStoreIndexMapper.selectSegchkStoreSaleDetails(segchkServiceAndSaleWebReq); + } + + /** + * 根据商户id,查询商户提现记录 + * + * @param segchkUserWebReq@return seg首页轮播图管理 + */ + @Override + public List selectStoreCashList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectStoreCashList with: {}", segchkUserWebReq.toString()); + return segchkStoreIndexMapper.selectStoreCashList(segchkUserWebReq); + } + + /** + * 根据商户id,查询商户的预约列表 + * + * @param segchkServiceAndSaleWebReq 搜索对象 + * @return seg首页轮播图管理 + */ + @Override + public List selectStoreUserLikeGoList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq) { + logger.debug("selectStoreUserLikeGoList with: {}", segchkServiceAndSaleWebReq.toString()); + return segchkStoreIndexMapper.selectStoreUserLikeGoList(segchkServiceAndSaleWebReq); + } + + /** + * 根据行政区域id,查询对应运营商id,如果没有,则返回默认运营商id + * + * @param adcode 行政区代码 + * @return seg首页轮播图管理 + */ + @Override + public HashMap getProvider(Map adcode) { + logger.debug("getProvider with: {}", adcode); + return segchkStoreIndexMapper.selectSegchkProviderBycode(adcode); + } + + /** + * 根据提现id,进行提现结果保存,及余额更新 + * + * @param chargeId 行政区代码 + * @param ret 行政区代码 + * @return seg首页轮播图管理 + */ + @Override + public void cashRet(String chargeId, int ret) { + logger.debug("cashRet with: {}---{}", chargeId, ret); + int opsRet = 0; + SegchkStoreCash segchkStoreCash = new SegchkStoreCash(); + segchkStoreCash.setCashId(Long.valueOf(chargeId)); + segchkStoreCash.setRetFlag(ret == 0 ? "1" : "2"); + opsRet = segchkStoreCashMapper.updateSegchkStoreCash(segchkStoreCash); + if(ret != 0){ + opsRet += segchkIndexStoreAccountMapper.deleteSegchkStoreAccountByCash(segchkStoreCash); + } + } + + /** + * 根据运营商id,获取相应的轮播图列表 + * + * @param providerId 运营商id + * @return seg首页轮播图管理 + */ + @Override + public List getBanners(Long providerId) { + logger.debug("getBanners with: {}", providerId); + SegchkCarouseMgt segchkCarouseMgt = new SegchkCarouseMgt(); + segchkCarouseMgt.setProviderId(providerId); + segchkCarouseMgt.setMgtState(0); + List segchkCarouseMgtList = segchkStoreIndexMapper.selectSegchkCarouseStoreList(segchkCarouseMgt); + return segchkCarouseMgtList; + } + + /** + * 根据用户提交信息进行修改 + * + * @param segchkUserSetInfoReq 用户评价提交实体 + * @return 更新结果 + */ + @Override + public int updateUserInfo(SegchkUserSetInfoReq segchkUserSetInfoReq) { + logger.debug("updateUserInfo with: {}", segchkUserSetInfoReq.toString()); + SegchkStoreSecurity segchkStoreSecurity = new SegchkStoreSecurity(); + segchkStoreSecurity.setPasswd(segchkUserSetInfoReq.getPasswd()); + segchkStoreSecurity.setProviderId(segchkUserSetInfoReq.getProviderId()); + segchkStoreSecurity.setStoreId(segchkUserSetInfoReq.getUserId()); + return segchkStoreSecurityMapper.insertSegchkStoreSecurity(segchkStoreSecurity); + } + + + /** + * 返回seg首页推荐商户信息 + * + * @param segchkRecommenderStoreWebReq seg首页推荐商户ID + * @return 结果 + */ + @Override + public List selectSegchkRecommenderStoreListByProvider(SegchkRecommenderStoreWebReq segchkRecommenderStoreWebReq) { + logger.debug("selectSegchkRecommenderStoreListByProvider with: {}", segchkRecommenderStoreWebReq.toString()); + return segchkStoreIndexMapper.selectSegchkRecommenderStoreListWeb(segchkRecommenderStoreWebReq); + } + + /** + * 返回商户openid + * + * @param storeId 商户id + * @return 结果 + */ + @Override + public WeChatCustomerLink selectWeChatInfoByStoreId(Long storeId) { + logger.debug("selectWeChatInfoByStoreId with: {}", storeId); + return segchkStoreIndexMapper.selectStoreOpenIdById(storeId); + } + + /** + * 验证推荐人是否存在 + * + * @param recommenderId 推荐人id + * @param recommenderLevel 推荐人角色 + * @return 结果 + */ + @Override + public int recommenderIsExit(String recommenderId, String recommenderLevel, String providerId) { + logger.debug("recommenderIsExit with: {}---{}---{}", recommenderId, recommenderLevel, providerId); + Map parmMap = new HashMap<>(); + parmMap.put("recommondId", recommenderId); + parmMap.put("recommondLevel", recommenderLevel); + parmMap.put("providerId", providerId); + return segchkUserIndexService.recommenderIsExit(parmMap); + } + + /** + * 检查该商户是否已被当前用户收藏 + * + * @param providerId 推荐人id + * @param storeId 推荐人角色 + * @param userId 推荐人角色 + * @return 是否收藏,1已收藏,0未收藏 + */ + @Override + public Integer isCollectByUser(Long providerId, Long storeId, Long userId) { + logger.debug("isCollectByUser with: {}---{}---{}", providerId, storeId, userId); + Map params = new HashMap<>(); + params.put("providerId", providerId); + params.put("storeId", storeId); + params.put("userId", userId); + return segchkStoreIndexMapper.isCollectByUser(params); + } + + @Override + public String selectSegchkStoreName(String storeId) { + return segchkStoreIndexMapper.selectSegchkStoreName(storeId); + } + + @Override + public Integer addStoreSelfCard(SegchkStoreSelfMgt segchkStoreSelfMgt) { + if(segchkStoreSelfMgt.getTypeId() == 2){ +// 说明是优惠券 + SegchkPreferenceLable segchkPreferenceLable = segchkPreferenceLableService.selectSegchkPreferenceLableByPreferenceId(segchkStoreSelfMgt.getLableId()); + segchkStoreSelfMgt.setFreeName(segchkPreferenceLable.getPreferenceName()); + } + return segchkStoreSelfMgtService.insertSegchkStoreSelfMgt(segchkStoreSelfMgt); + } + + @Override + public int addAccountByReward(SegchkChargeReward segchkChargeReward) { + return segchkStoreIndexMapper.addAccountByReward(segchkChargeReward); + } + + @Override + public Long getVipCardFromLikego(Long likegoId) { + return segchkStoreIndexMapper.getVipCardFromLikego(likegoId); + } + + @Override + public HashMap getCustomService(Long providerId) { + return segchkProviderMgtService.getCustomService(providerId); + } + + @Override + public int addCommentAccByComment(Long commentId) { + int ret = segchkStoreIndexMapper.addCommentAccByComment(commentId); + logger.debug("addCommentAccByComment with ({}) {}", commentId, (ret > 0 ? "successed" : "failed")); + return ret; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkProviderIndexServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkProviderIndexServiceImpl.java new file mode 100644 index 0000000..fa00c62 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkProviderIndexServiceImpl.java @@ -0,0 +1,78 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.mapper.SegchkProviderIndexMapper; +import com.ruoyi.segchk.service.ISegchkProviderIndexService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * seg运营商管理Service业务层处理 + * + * @author yinzhiying + * @date 2021-07-01 + */ +@Service +public class SegchkProviderIndexServiceImpl implements ISegchkProviderIndexService +{ + @Autowired + private SegchkProviderIndexMapper segchkProviderIndexMapper; + + + /** + * 查询运营商个人中心信息 + * + * @param segchkUserWebReq 查询实体对象 + * @return 结果 + */ + @Override + public SegchkUserWebResp selectSegchkProviderWebInfo(SegchkUserWebReq segchkUserWebReq) { + return segchkProviderIndexMapper.selectSegchkProviderWebInfo(segchkUserWebReq); + } + + /** + * 查询运营商下核消,售卡统计 + * + * @param segchkServiceAndSaleWebReq 查询实体对象 + * @return 结果 + */ + @Override + public List selectProviderServiceAndSaleList(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq) { + if(segchkServiceAndSaleWebReq.getSrcFlag() == 0) + return segchkProviderIndexMapper.selectSegchkStoreServiceList(segchkServiceAndSaleWebReq); + else + return segchkProviderIndexMapper.selectSegchkStoreSaleList(segchkServiceAndSaleWebReq); + } + + /** + * 查询运营商下核消,售卡统计详情 + * + * @param segchkServiceAndSaleWebReq 查询实体对象 + * @return 结果 + */ + @Override + public List selectProviderServiceAndSaleDetails(SegchkServiceAndSaleWebReq segchkServiceAndSaleWebReq) { + if(segchkServiceAndSaleWebReq.getSrcFlag() == 0) + return segchkProviderIndexMapper.selectSegchkStoreServiceDetails(segchkServiceAndSaleWebReq); + else + return segchkProviderIndexMapper.selectSegchkStoreSaleDetails(segchkServiceAndSaleWebReq); + } + + /** + * 返回运营商openid + * + * @param providerId 运营商id + * @return 结果 + */ + @Override + public String selectWeChatInfoByProviderId(Long providerId) { + return segchkProviderIndexMapper.selectProviderOpenIdById(providerId); + } + + @Override + public String selectSegchkProviderName(String providerId) { + return segchkProviderIndexMapper.selectSegchkProviderName(providerId); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCashServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCashServiceImpl.java new file mode 100644 index 0000000..376359b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCashServiceImpl.java @@ -0,0 +1,100 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.segchk.domain.SegchkUserCash; +import com.ruoyi.segchk.mapper.SegchkUserCashMapper; +import com.ruoyi.segchk.service.ISegchkUserCashService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * seg用户提现记录Service业务层处理 + * + * @author yinzhiying + * @date 2021-08-23 + */ +@Service +public class SegchkUserCashServiceImpl implements ISegchkUserCashService +{ + + private static final Logger logger = LoggerFactory.getLogger(SegchkUserCashServiceImpl.class); + + @Autowired + private SegchkUserCashMapper segchkUserCashMapper; + + /** + * 查询seg用户提现记录 + * + * @param cashId seg用户提现记录主键 + * @return seg用户提现记录 + */ + @Override + public SegchkUserCash selectSegchkUserCashByCashId(Long cashId) + { + return segchkUserCashMapper.selectSegchkUserCashByCashId(cashId); + } + + /** + * 查询seg用户提现记录列表 + * + * @param segchkUserCash seg用户提现记录 + * @return seg用户提现记录 + */ + @Override + public List selectSegchkUserCashList(SegchkUserCash segchkUserCash) + { + return segchkUserCashMapper.selectSegchkUserCashList(segchkUserCash); + } + + /** + * 新增seg用户提现记录 + * + * @param segchkUserCash seg用户提现记录 + * @return 结果 + */ + @Override + public int insertSegchkUserCash(SegchkUserCash segchkUserCash) + { + return segchkUserCashMapper.insertSegchkUserCash(segchkUserCash); + } + + /** + * 修改seg用户提现记录 + * + * @param segchkUserCash seg用户提现记录 + * @return 结果 + */ + @Override + public int updateSegchkUserCash(SegchkUserCash segchkUserCash) + { + return segchkUserCashMapper.updateSegchkUserCash(segchkUserCash); + } + + /** + * 批量删除seg用户提现记录 + * + * @param cashIds 需要删除的seg用户提现记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserCashByCashIds(Long[] cashIds) + { + return segchkUserCashMapper.deleteSegchkUserCashByCashIds(cashIds); + } + + /** + * 删除seg用户提现记录信息 + * + * @param cashId seg用户提现记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserCashByCashId(Long cashId) + { + return segchkUserCashMapper.deleteSegchkUserCashByCashId(cashId); + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCollectServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCollectServiceImpl.java new file mode 100644 index 0000000..ea6e280 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserCollectServiceImpl.java @@ -0,0 +1,107 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.segchk.domain.SegchkUserCollect; +import com.ruoyi.segchk.mapper.SegchkUserCollectMapper; +import com.ruoyi.segchk.service.ISegchkUserCollectService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * seg用户收藏记录Service业务层处理 + * + * @author yinzhiying + * @date 2021-08-23 + */ +@Service +public class SegchkUserCollectServiceImpl implements ISegchkUserCollectService +{ + @Autowired + private SegchkUserCollectMapper segchkUserCollectMapper; + + /** + * 查询seg用户收藏记录 + * + * @param collectId seg用户收藏记录主键 + * @return seg用户收藏记录 + */ + @Override + public SegchkUserCollect selectSegchkUserCollectByCollectId(Long collectId) + { + return segchkUserCollectMapper.selectSegchkUserCollectByCollectId(collectId); + } + + /** + * 查询seg用户收藏记录列表 + * + * @param segchkUserCollect seg用户收藏记录 + * @return seg用户收藏记录 + */ + @Override + public List selectSegchkUserCollectList(SegchkUserCollect segchkUserCollect) + { + return segchkUserCollectMapper.selectSegchkUserCollectList(segchkUserCollect); + } + + /** + * 新增seg用户收藏记录 + * + * @param segchkUserCollect seg用户收藏记录 + * @return 结果 + */ + @Override + public int insertSegchkUserCollect(SegchkUserCollect segchkUserCollect) + { + return segchkUserCollectMapper.insertSegchkUserCollect(segchkUserCollect); + } + + /** + * 修改seg用户收藏记录 + * + * @param segchkUserCollect seg用户收藏记录 + * @return 结果 + */ + @Override + public int updateSegchkUserCollect(SegchkUserCollect segchkUserCollect) + { + return segchkUserCollectMapper.updateSegchkUserCollect(segchkUserCollect); + } + + /** + * 批量删除seg用户收藏记录 + * + * @param collectIds 需要删除的seg用户收藏记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserCollectByCollectIds(Long[] collectIds) + { + return segchkUserCollectMapper.deleteSegchkUserCollectByCollectIds(collectIds); + } + + /** + * 删除seg用户收藏记录信息 + * + * @param collectId seg用户收藏记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserCollectByCollectId(Long collectId) + { + return segchkUserCollectMapper.deleteSegchkUserCollectByCollectId(collectId); + } + + /** + * 删除seg用户收藏记录对象 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + @Override + public int deleteSegchkUserCollectByIds(String ids) + { + return segchkUserCollectMapper.deleteSegchkUserCollectByCollectIds(Convert.toLongArray(ids)); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserIndexServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserIndexServiceImpl.java new file mode 100644 index 0000000..4600d24 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserIndexServiceImpl.java @@ -0,0 +1,1380 @@ +package com.ruoyi.segchk.service.impl; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.order.service.impl.PaySupplier; +//import com.ruoyi.order.service.impl.WechatWithdrawSupplier; +import com.ruoyi.segchk.domain.*; +import com.ruoyi.segchk.mapper.*; +import com.ruoyi.segchk.service.*; +import com.ruoyi.segchk.domain.BaseInfoSet; +import com.ruoyi.setting.bean.WechatPaySet; +import com.ruoyi.setting.service.ILsPaySettingService; +import com.ruoyi.util.*; +import com.ruoyi.util.bean.*; +import com.weixin.pay.WXPay; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +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.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.net.URLEncoder; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * seg用户基本信息Service业务层处理 + * + * @author yinzhiying + * @date 2021-07-01 + */ +@Service +public class SegchkUserIndexServiceImpl implements ISegchkUserIndexService +{ + private static final Logger logger = LoggerFactory.getLogger(SegchkUserIndexServiceImpl.class); + + @Autowired + private SegchkUserIndexMapper segchkUserIndexMapper; + + @Autowired + private SegchkIndexUserVipMapper segchkIndexUserVipMapper; + + @Autowired + private SegchkServiceChkMapper segchkServiceChkMapper; + + @Autowired + private SegchkStoreSelfMgtMapper segchkStoreSelfMgtMapper; + + @Autowired + private SegchkSelfServiceChkMapper segchkSelfServiceChkMapper; + + @Autowired + private SegchkUserLikegoMapper segchkUserLikegoMapper; + + @Autowired + private SegchkUserChargeMapper segchkUserChargeMapper; + + @Autowired + private SegchkIndexUserAccountMapper segchkIndexUserAccountMapper; + + @Autowired + private SegchkIndexStoreAccountMapper segchkIndexStoreAccountMapper; + + @Autowired + private SegchkUserSecurityMapper segchkUserSecurityMapper; + + @Autowired + private SegchkUserCertificationInfoMapper segchkUserCertificationInfoMapper; + + @Autowired + private SegchkStoreCashMapper segchkStoreCashMapper; + + @Autowired + private SegchkUserCashMapper segchkUserCashMapper; + + + @Autowired + private SegchkServiceCommentMapper segchkServiceCommentMapper; + + @Autowired + private SegchkUserBasicInfoMapper segchkUserBasicInfoMapper; + + @Autowired + private SegchkUserExtInfoMapper segchkUserExtInfoMapper; + + @Autowired + private SegchkUserWechatMapper segchkUserWechatMapper; + + @Autowired + private ISegchkUserRewardService segchkUserRewardService; + + @Autowired + private ISegchkStoreIndexService segchkStoreIndexService; + + @Autowired + private ISegchkProviderIndexService segchkProviderIndexService; + + @Autowired + private ISegchkSystemSettingService segchkSystemSettingService; + + @Autowired + private ISegchkStoreRewardService segchkStoreRewardService; + + + @Autowired + private ISegchkUserAccountService segchkUserAccountService; + + /** + * 注入支付设置服务 + */ + @Autowired + private ILsPaySettingService paySetService; + + @Value("${segchk.cash.store_threshold:#{0.0}}") + private BigDecimal storeThreshold; + + @Value("${segchk.cash.user_threshold:#{0.0}}") + private BigDecimal userThreshold; + + @Value("${segchk.cash.store_threshold_first:#{0.0}}") + private BigDecimal storeThresholdFirst; + + @Value("${segchk.cash.user_threshold_first:#{0.0}}") + private BigDecimal userThresholdFirst; + + @Value("${segchk.cash.sandbox:#{null}}") + private Integer sandbox; + + /** + * 查询seg用户中心信息 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + @Override + public SegchkUserWebResp selectSegchkUserWebInfo(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectSegchkUserWebInfo with: {}", segchkUserWebReq.toString()); + SegchkUserWebResp segchkUserWebResp = segchkUserIndexMapper.selectSegchkUserWebInfo(segchkUserWebReq); + segchkUserWebResp.setProviderId(segchkUserWebReq.getProviderId()); + if(ObjectUtils.isEmpty(segchkUserWebResp.getRecommenderId()) || ObjectUtils.isEmpty(segchkUserWebResp.getRecommenderLevel())){ +// 说明是平台用户,无推荐人 + segchkUserWebResp.setRecommenderLevel(null); + segchkUserWebResp.setRecommenderId(null); + segchkUserWebResp.setRecommenderName("无"); + logger.debug("selectSegchkUserWebInfo res: ({})", segchkUserWebResp.toString()); + return segchkUserWebResp; + } + switch (segchkUserWebResp.getRecommenderLevel()){ + case "0": segchkUserWebResp.setRecommenderName(segchkProviderIndexService.selectSegchkProviderName(segchkUserWebResp.getRecommenderId()));break; + case "1": segchkUserWebResp.setRecommenderName(segchkStoreIndexService.selectSegchkStoreName(segchkUserWebResp.getRecommenderId()));break; + case "2": segchkUserWebResp.setRecommenderName(segchkUserIndexMapper.selectSegchkUserName(segchkUserWebResp.getRecommenderId()));break; + } + logger.debug("selectSegchkUserWebInfo res: ({})", segchkUserWebResp.toString()); + return segchkUserWebResp; + } + + /** + * 查询seg用户核消列表 + * + * @param segchkUserWebReq + * @return seg用户扩展信息 + */ + @Override + public List selectUserServiceCHKList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserServiceCHKList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserServiceCHKList(segchkUserWebReq); + } + + /** + * 查询seg用户会员卡列表或赠卡优惠券列表 + * + * @param segchkUserWebReq + * @return seg用户扩展信息 + */ + @Override + public List selectUserCardList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserCardList with: {}", segchkUserWebReq.toString()); + if(segchkUserWebReq.getCardFlag() == 0) { + return segchkUserIndexMapper.selectUserCardList(segchkUserWebReq); + } + else if(segchkUserWebReq.getCardFlag() == 1){ + return segchkUserIndexMapper.selectUserPerformanceList(segchkUserWebReq); + } + return null; + } + + /** + * 查询seg用户收藏列表 + * + * @param segchkUserWebReq + * @return seg用户扩展信息 + */ + @Override + public List selectUserCollectList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserCollectList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserCollectList(segchkUserWebReq); + } + + /** + * 查询seg用户预约列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + @Override + public List selectUserLikGoList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserLikGoList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserLikGoList(segchkUserWebReq); + } + + /** + * 查询seg用户充值列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + @Override + public List selectUserChargeList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserChargeList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserChargeList(segchkUserWebReq); + } + + /** + * 查询seg用户提现列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + @Override + public List selectUserCashList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserCashList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserCashList(segchkUserWebReq); + } + + /** + * 查询seg用户消息列表 + * + * @param segchkUserWebReq@return seg用户扩展信息 + */ + @Override + public List selectUserMsgList(SegchkUserWebReq segchkUserWebReq) { + logger.debug("selectUserMsgList with: {}", segchkUserWebReq.toString()); + return segchkUserIndexMapper.selectUserMsgList(segchkUserWebReq); + } + + /** + * 查询seg用户预约可用卡券列表 + * + * @param segchkServiceOrderWebReq seg用户中心请求实体 + * @return seg用户扩展信息 + */ + @Override + public List selectUserOrderPredCardListWebInfo(SegchkServiceOrderWebReq segchkServiceOrderWebReq) { + List segchkServiceOrderWebReqs = segchkUserIndexMapper.selectUserOrderPredCardListWebInfo(segchkServiceOrderWebReq); +// 如果返回结果是空,则说明无会员卡或赠卡或用,如果返回的结果中没有会员卡,说明无可用卡;如果返回的结果中,存在会员卡的store_id为空的情况:说明该赠卡可用,但是该会员卡在该商家不可用;如果是会员卡的时候并且card_id也是空的情况:说明该赠卡可用,但是该会员卡在该商家已经超过了商家的核销次数 + AtomicInteger a = new AtomicInteger(-1); + if(CollectionUtils.isEmpty(segchkServiceOrderWebReqs) + || segchkServiceOrderWebReqs.stream().noneMatch(v -> v.getTypeId() == 0)){ + logger.debug("selectUserOrderPredCardListWebInfo with: {} --- {}", segchkServiceOrderWebReq.toString(), "this user no card can use in this store"); + return new ArrayList(); + } + List segchkServiceOrderWebReqs1 = segchkServiceOrderWebReqs.stream().filter(v -> { + if (v.getTypeId() == 0) { + a.set(0); + if (Objects.isNull(v.getStoreId())) { + a.set(1); + return false; + } else if (Objects.isNull(v.getCardId())) { + a.set(2); + return false; + } else + return true; + } + return true; + }).collect(Collectors.toList()); + StringBuffer sb = new StringBuffer(); + switch (a.get()){ + case 1 : sb.append("this store not support this vip card");break; + case 2 : sb.append("this vip card check over in this store");break; + default : sb.append("this vip card can use in this store");break; + } + logger.debug("selectUserOrderPredCardListWebInfo with: {} --- {}{}", segchkServiceOrderWebReq.toString(), sb.toString(), segchkServiceOrderWebReqs1.size()); + + return segchkServiceOrderWebReqs1; + } + + /** + * 根据用户核消二维码提取出来相应的信息进行核消,1、检查核卡是否可以核消(防止该卡已经在该商家不能再次核消),2、检查该预约id,是否已经使用(防止多次预约核消使用) + * + * @param segchkUserLikego seg用户想去记录实体 + * @return 结果 + */ + @Override + public void CheckUserServiceChk(SegchkUserLikego segchkUserLikego) { + logger.debug("CheckUserServiceChk with: {}", segchkUserLikego.toString()); + SegchkServiceOrderWebReq segchkServiceOrderWebReq = new SegchkServiceOrderWebReq(); + segchkServiceOrderWebReq.setProviderId(segchkUserLikego.getProviderId()); + segchkServiceOrderWebReq.setUserId(segchkUserLikego.getUserId()); + segchkServiceOrderWebReq.setStoreId(segchkUserLikego.getStoreId()); + List segchkServiceOrderWebReqList = segchkUserIndexMapper.selectUserOrderPredCardListWebInfo(segchkServiceOrderWebReq); + if(segchkServiceOrderWebReqList == null || segchkServiceOrderWebReqList.isEmpty()){ + logger.warn("CheckUserServiceChk user has no card can use {}", segchkUserLikego.toString()); +// 说明该用户已经没有可使用的卡了 + } + else { + final List collect = segchkServiceOrderWebReqList.stream().filter(v -> v.getProviderId() == segchkUserLikego.getProviderId() && v.getUserId() == segchkUserLikego.getUserId() && v.getStoreId() == segchkUserLikego.getStoreId() && v.getCardId() == segchkUserLikego.getCardId() && v.getTypeId() == segchkUserLikego.getCardType()).collect(Collectors.toList()); + } + + } + + @Override + public SegchkServiceOrderChkTestResp selectUserOrderPredInfo(Long likegoId) { + logger.debug("selectUserOrderPredInfo with: {}", likegoId.toString()); + return segchkUserIndexMapper.selectUserOrderPredInfo(likegoId); + } + + /** + * 根据核查结果进行核消。说明已经满足核消条件 + * + * @param segchkServiceOrderChkTestResp + * @param likegoId + * @param stoRewardWithChk + * @return 结果 + */ + @Override + @Transactional + public int OrderCheckTransaction(SegchkServiceOrderChkTestResp segchkServiceOrderChkTestResp, Long likegoId, Boolean stoRewardWithChk) { + logger.debug("OrderCheckTransaction with: {}---{}", segchkServiceOrderChkTestResp.toString(), likegoId); + int ret = 0; + Long tmpStoreId = segchkServiceOrderChkTestResp.getStoreId(); + if(segchkServiceOrderChkTestResp.getCardType() == 0){ +// 说明是会员卡,则先更新会员卡次数。然后插入核消记录,最后更新预约订单状态 +// SegchkUserVip segchkUserVip = new SegchkUserVip(); + logger.debug("OrderCheckTransaction will check with vip card"); + ret += segchkIndexUserVipMapper.updateSegchkUserVipCheck(segchkServiceOrderChkTestResp.getCardId()); + logger.debug("OrderCheckTransaction checked({}) with vip card({})" + , (ret == 1 ? "successed" : "failed") + , segchkServiceOrderChkTestResp.getCardId()); + SegchkServiceChk segchkServiceChk = new SegchkServiceChk(); + segchkServiceChk.setCardId(segchkServiceOrderChkTestResp.getCardId()); +// segchkServiceChk.setCardTypeId(0L); + segchkServiceChk.setProviderId(segchkServiceOrderChkTestResp.getProviderId()); + segchkServiceChk.setStoreId(tmpStoreId); + segchkServiceChk.setUserId(segchkServiceOrderChkTestResp.getUserId()); + + ret += segchkServiceChkMapper.insertSegchkServiceChk(segchkServiceChk); + logger.debug("OrderCheckTransaction save({}) service-check with ({})" + , (ret == 2 ? "successed" : "failed") + , segchkServiceChk.toString()); + + if(stoRewardWithChk){ +// 如果允许,会员卡第一次核消,将给该商家返利 + Map params = new HashMap<>(); + params.put("cardId", segchkServiceChk.getCardId()); + params.put("storeId", tmpStoreId); + params.put("userId", segchkServiceChk.getUserId()); +// 根据卡号id,获取会员卡相关信息 + SegchkChargeReward segchkChargeReward = segchkUserIndexMapper.selectSegchkRewardInfoForCheck(params); + + int validateForCheck = segchkChargeReward.validateForCheck(tmpStoreId); + if(validateForCheck < 0){ + logger.warn("validateForCheselectUserOrderPredCardListWebInfock can not make reword for store({}), because {}", tmpStoreId, (validateForCheck == -1 ? "持卡用户推荐人不是平台" : validateForCheck == -2 ? "已使用过" : validateForCheck == -3 ? "该商家不支持该卡的核消" : "该商家不需要返利")); + } + else{ + segchkChargeReward.mkReward(); + segchkChargeReward.setRecommendersLevel(1); + segchkChargeReward.setUserRecommenders(tmpStoreId); + makeStoreReward(segchkChargeReward); + } + } + } + else { +// 说明是优惠券或赠卡则先更新赠卡次数。然后插入核消记录,最后更新预约订单状态 + logger.debug("OrderCheckTransaction will check with store card"); + ret += segchkStoreSelfMgtMapper.updateSegchkUserVipCheck(segchkServiceOrderChkTestResp.getCardId()); + logger.debug("OrderCheckTransaction checked({}) with vip card({})" + , (ret == 1 ? "successed" : "failed") + , segchkServiceOrderChkTestResp.getCardId()); + SegchkSelfServiceChk segchkSelfServiceChk = new SegchkSelfServiceChk(); + segchkSelfServiceChk.setCardId(segchkServiceOrderChkTestResp.getCardId()); + segchkSelfServiceChk.setProviderId(segchkServiceOrderChkTestResp.getProviderId()); + segchkSelfServiceChk.setStoreId(tmpStoreId); + segchkSelfServiceChk.setUserId(segchkServiceOrderChkTestResp.getUserId()); + ret += segchkSelfServiceChkMapper.insertSegchkSelfServiceChk(segchkSelfServiceChk); + logger.debug("OrderCheckTransaction save({}) service-check with ({})" + , (ret == 2 ? "successed" : "failed") + , segchkSelfServiceChk.toString()); + } + SegchkUserLikego segchkUserLikego = new SegchkUserLikego(); + segchkUserLikego.setLikegoId(likegoId); + segchkUserLikego.setMgtState(2); + + ret += segchkUserLikegoMapper.updateSegchkUserLikego(segchkUserLikego); + logger.debug("OrderCheckTransaction update({}) likego({})" + , (ret == 3 ? "successed" : "failed") + , likegoId); + return ret; + } + + /** + * 根据支付回调结果,进行相应的更新 + * + * @param chargeId 核消检查信息 + * @param ret 预约单id + * @return 结果 + */ + @Override + @Transactional + public void chargeRet(String chargeId, int ret) { +// 根据回调结果。如果成功,则插入生成会员卡,并获取会员卡号,否则不产生新的会员卡号 + logger.debug("chargeRet with: {}---{}", chargeId, ret); + SegchkUserCharge segchkUserCharge1 = segchkUserChargeMapper.selectSegchkUserChargeByChargeId(Long.valueOf(chargeId)); + if(ObjectUtils.isEmpty(segchkUserCharge1) || ObjectUtils.isEmpty(segchkUserCharge1.getRetFlag())) { + logger.debug("chargeRet with: {} is not exit", chargeId); + return; + } + if(segchkUserCharge1.getRetFlag() != 0){ + logger.debug("chargeRet charge:{}{} had been updated with: {} on {}", chargeId, ret, segchkUserCharge1.getRetFlag(), segchkUserCharge1.getModTime()); + return; + } + else if(ret == 0){ +// 支付成功,生成新的会员卡信息 + SegchkChargeRet segchkChargeRet = new SegchkChargeRet(); + segchkChargeRet.setChargeId(Long.valueOf(chargeId)); + int insert_ret = segchkIndexUserVipMapper.insertSegchkUserVipByCharge(segchkChargeRet); + if(insert_ret == 0){ + logger.error("chargeRet生成新的会员卡失败--->{0}\n", segchkChargeRet.getChargeId()); + } + else{ + logger.info("chargeRet生成新的会员卡成功--->{0}:{1}\n", chargeId, segchkChargeRet.getCardId()); + SegchkUserBasicInfo segchkUserBasicInfo = new SegchkUserBasicInfo(); + segchkUserBasicInfo.setUserId(segchkUserCharge1.getUserId()); + segchkUserBasicInfo.setCardTypeId(segchkUserCharge1.getCardTypeId()); + segchkUserBasicInfoMapper.updateSegchkUserBasicInfo(segchkUserBasicInfo); + } +// 根据新生成的会员卡号,充值id,更新相应的充值记录表,商家赠卡表等 + SegchkUserCharge segchkUserCharge = new SegchkUserCharge(); + segchkUserCharge.setChargeId(segchkChargeRet.getChargeId()); + if(segchkChargeRet.getCardId() != null && segchkChargeRet.getCardId() != 0L) { + logger.debug("chargeRet chargeId: {}---cardId: {}", segchkChargeRet.getChargeId(), segchkChargeRet.getCardId()); + segchkUserCharge.setCardId(segchkChargeRet.getCardId()); + } + else{ + logger.warn("chargeRet chargeId: {} without cardId", segchkChargeRet.getChargeId()); + } + segchkUserCharge.setRetFlag(1); + int updaterest = segchkUserChargeMapper.updateSegchkUserChargeByRet(segchkUserCharge); + logger.warn("chargeRet update with {} result: {}", "success", updaterest == 1 ? "successed" : "failed"); + + Map params = new HashMap<>(); + params.put("chargeId", segchkUserCharge1.getChargeId()); + params.put("userId", segchkUserCharge1.getUserId()); + params.put("providerId", segchkUserCharge1.getProviderId()); + params.put("cardTypeId", segchkUserCharge1.getCardTypeId()); + params.put("cardId", segchkChargeRet.getCardId()); + updaterest = makeChargeReward(params); + } + else{ + logger.warn("chargeRet with: {}---{}, 充值失败!!!", chargeId.toString(), ret); + SegchkUserCharge segchkUserCharge = new SegchkUserCharge(); + segchkUserCharge.setChargeId(Long.parseLong(chargeId)); + segchkUserCharge.setRetFlag(-1); + int updaterest = segchkUserChargeMapper.updateSegchkUserCharge(segchkUserCharge); + int deleterest = segchkIndexUserAccountMapper.deleteSegchkUserAccountByCharge(segchkUserCharge); + logger.warn("chargeRet update with {} result: {}", "failed", deleterest == 1 ? "successed" : "failed"); + } + } + + @Override + public int makeChargeReward(Map params) { + logger.debug("makeChargeReward with --- ({})", JSON.toJSONString(params)); + int ret = 0; +// 计算返利.给用户或商户,运营商加余额 + SegchkChargeReward segchkChargeReward = segchkUserIndexMapper.selectSegchkRewardInfoForCharge(params); + segchkChargeReward.setCardId((Long) params.get("cardId")); + segchkChargeReward.setChargeId((Long) params.get("chargeId")); + if(ObjectUtils.isEmpty(segchkChargeReward.getUserRecommenders()) || ObjectUtils.isEmpty(segchkChargeReward.getRecommendersLevel())){ +// 推荐人是平台 + logger.warn("chargeRet charge({}) reward is will belong to platform", params.get("chargeId")); + } + /*else if(segchkChargeReward.getRecommendersLevel() == 0){ + + }*/ + else{ + switch (segchkChargeReward.getRecommendersLevel()){ + case 0: { +// return makeProviderReward(segchkChargeReward, params); + return 0; + } + case 1: { + return makeStoreReward(segchkChargeReward); + } + case 2: { + return makeUserReward(segchkChargeReward); + } + default: return 0; + } + } + return ret; + } + + private int makeUserReward(SegchkChargeReward segchkChargeReward) { + logger.debug("makeUserReward with ({})", segchkChargeReward.toString()); + int ret = 0; + if(ObjectUtils.isEmpty(segchkChargeReward.getReward()) || segchkChargeReward.getReward().compareTo(new BigDecimal(0.0)) <= 0){ + logger.debug("makeUserReward reword is null or 0.0"); + return 1; + } +// 如果推荐是用户。则给用户累加奖励 + SegchkUserReward segchkUserReward = new SegchkUserReward(); + segchkUserReward.setProviderId(segchkChargeReward.getProviderId()); + segchkUserReward.setReward(segchkChargeReward.getReward()); + segchkUserReward.setRewardCardId(segchkChargeReward.getCardId()); + segchkUserReward.setRewardCardTypeId(Long.valueOf(segchkChargeReward.getCardTypeId())); + segchkUserReward.setUserId(segchkChargeReward.getUserRecommenders()); + ret = segchkUserRewardService.insertSegchkUserReward(segchkUserReward); + if(ret > 0 ){ + logger.debug("makeUserReward save reward success with chargeId({})--- {}", segchkChargeReward.getChargeId(), segchkUserReward.toString()); + } + else{ + logger.warn("makeUserReward save reward failed with chargeId({}) --- {}", segchkChargeReward.getChargeId(), segchkUserReward.toString()); + } + + segchkChargeReward.setChargeId(segchkChargeReward.getChargeId()); + segchkChargeReward.setRewardId(segchkUserReward.getRewardId()); +// 形成商户余额 + ret = segchkUserIndexMapper.addAccountByReward(segchkChargeReward); + if(ret > 0){ + logger.debug("makeUserReward add account successed for --- {}", segchkChargeReward.toString()); + } + else { + logger.warn("makeUserReward add account failed for --- {}", segchkChargeReward.toString()); + } + return ret; + } + + private int makeStoreReward(SegchkChargeReward segchkChargeReward) { + logger.debug("makeStoreReward with ({})", segchkChargeReward.toString()); + int ret = 0; + if(ObjectUtils.isEmpty(segchkChargeReward.getReward()) || segchkChargeReward.getReward().compareTo(new BigDecimal(0.0)) <= 0){ + logger.debug("makeStoreReward reword is null or 0.0"); + return 1; + } +// 如果推荐是商户。则给商户累加奖励 + SegchkStoreReward segchkStoreReward = new SegchkStoreReward(); + segchkStoreReward.setProviderId(segchkChargeReward.getProviderId()); + segchkStoreReward.setReward(segchkChargeReward.getReward()); + segchkStoreReward.setRewardCardId(segchkChargeReward.getCardId()); + segchkStoreReward.setRewardCardTypeId(Long.valueOf(segchkChargeReward.getCardTypeId())); + segchkStoreReward.setStoreId(segchkChargeReward.getUserRecommenders()); + ret = segchkStoreRewardService.insertSegchkStoreReward(segchkStoreReward); + if(ret > 0 ){ + logger.debug("makeStoreReward save reward success with chargeId({})--- {}", segchkChargeReward.getChargeId(), segchkStoreReward.toString()); + } + else{ + logger.warn("makeStoreReward save reward failed with chargeId({}) --- {}", segchkChargeReward.getChargeId(), segchkStoreReward.toString()); + } + + segchkChargeReward.setChargeId(segchkChargeReward.getChargeId()); + segchkChargeReward.setRewardId(segchkStoreReward.getRewardId()); +// 形成商户余额 + ret = segchkStoreIndexService.addAccountByReward(segchkChargeReward); + if(ret > 0){ + logger.debug("chargeRet add account successed for --- {}", segchkChargeReward.toString()); + } + else { + logger.warn("chargeRet add account failed for --- {}", segchkChargeReward.toString()); + } + return ret; + } + + private int makeProviderReward(SegchkChargeReward segchkChargeReward, Map params) { + return 0; + } + + /** + * 根据支用户id,运营商id,查询该用户可购买的卡 + * + * @param segchkUserWebReq 用户请示信息体 + * @return 结果 + */ + @Override + public List SegchkUserChargePre(SegchkUserWebReq segchkUserWebReq) { + logger.debug("SegchkUserChargePre with: {}", segchkUserWebReq.toString()); + List segchkUserChargeCards = segchkUserIndexMapper.selectSegchkUserChargePre(segchkUserWebReq); + +// 说明该用户购买过正式会员卡 +// boolean b = segchkUserChargeCards.parallelStream().anyMatch(v -> v.getHadBuy() != 0 && v.getCardTypeValue().compareTo(new BigDecimal(20.0)) = -1); + if(segchkUserChargeCards.parallelStream().anyMatch(v -> v.getCanBuy() == 1 || v.getCanBuy() == 3)){ +// 如果有一张卡,为正在使用中1,则不可以再充值购买 + logger.debug("SegchkUserChargePre user had one using card"); + return null; + } + else{ + List segchkUserChargeCards1 = segchkUserChargeCards.parallelStream().filter(v -> { +// 通过过滤出可购买的卡(间接过滤到为超限不能再买的卡) + return v.getCanBuy() == 0; + }).collect(Collectors.toList()); + return segchkUserChargeCards1.size() == 0 || segchkUserChargeCards1.isEmpty() ? null : segchkUserChargeCards1; + } + } + + /** + * 根据支用户id,运营商id,用户充值时可用余额 + * + * @param segchkUserCharge 用户请示信息体 + * @return 结果 + */ + @Override + public BigDecimal getAccount(SegchkUserCharge segchkUserCharge) { + logger.debug("getAccount with: {}", segchkUserCharge.toString()); + SegchkUserAccountCheck segchkUserAccountCheck = new SegchkUserAccountCheck(); + segchkUserAccountCheck.setAccount(segchkUserCharge.getAccountUsed()); + segchkUserAccountCheck.setProviderId(segchkUserCharge.getProviderId()); + segchkUserAccountCheck.setUserId(segchkUserCharge.getUserId()); + BigDecimal ret = segchkIndexUserAccountMapper.checkSegchkUserAccount(segchkUserAccountCheck); + return ret; + } + + /** + * 根据用户id(或者商户id),运营商id,用户身份查询用户余额 + * + * @param segchkUserCashOpsReq 用户请示信息体 + * @param ip + * @return 结果 + */ + @Override + public int getAccountForCash(SegchkUserCashOpsReq segchkUserCashOpsReq, String ip) { + logger.debug("getAccountForCash with: {}---{}", segchkUserCashOpsReq.toString(), ip); + SegchkUserCashOpsResp segchkUserCashOpsResp = segchkIndexUserAccountMapper.selectSegchkUserAccountForCash(segchkUserCashOpsReq); + if(segchkUserCashOpsResp == null){ +// 说明用户没有任何余额信息 + return -1; + } + + if(segchkUserCashOpsReq.getUserLevel() != 1 && segchkUserCashOpsReq.getUserLevel() != 2){ +// 非正常用户 + return -2; + } + BigDecimal firstline = segchkUserCashOpsReq.getUserLevel() == 1 ? storeThresholdFirst : userThresholdFirst; + BigDecimal baseline = segchkUserCashOpsReq.getUserLevel() == 1 ? storeThreshold : userThreshold; + + if(segchkUserCashOpsReq.getCash().compareTo(segchkUserCashOpsReq.getCashId() == null ? firstline : baseline) != 1){ +// 首次提现余额受限 + return -3; + } + if(segchkUserCashOpsReq.getCash().compareTo(segchkUserCashOpsResp.getAccount()) == 1){ +// 提现金额超过余额 + return -4; + } + +// 1、创建提现记录 +// 2 新增余额记录 +// ret = 2 成功 + int ret = makeCashOps(segchkUserCashOpsReq, ip); + + return ret; + } + + /** + * 根据提现id,进行提现结果保存,及余额更新 + * + * @param chargeId 行政区代码 + * @param ret 行政区代码 + * @return seg首页轮播图管理 + */ + @Override + @Transactional + public void cashRet(String chargeId, int ret) { + logger.debug("cashRet with: {}---{}", chargeId.toString(), ret); + int opsRet = 0; + SegchkUserCash segchkUserCash = new SegchkUserCash(); + segchkUserCash.setCashId(Long.valueOf(chargeId)); + segchkUserCash.setRetFlag(ret == 0 ? 1 : 2); + opsRet = segchkUserCashMapper.updateSegchkUserCash(segchkUserCash); + if(ret != 0){ + opsRet = segchkIndexUserAccountMapper.deleteSegchkUserAccountByCash(segchkUserCash); + } + } + + /** + * 新增用户评价 + * + * @param segchkServiceCommentUserReq 用户评价提交实体 + * @return seg首页轮播图管理 + */ + @Override + @Transactional + public int insertSegchkServiceComment(SegchkServiceCommentUserReq segchkServiceCommentUserReq) { + logger.debug("insertSegchkServiceComment with: {}", segchkServiceCommentUserReq.toString()); + int ret = segchkServiceCommentMapper.insertSegchkServiceCommentByChk(segchkServiceCommentUserReq); + SegchkServiceChk segchkServiceChk = new SegchkServiceChk(); + segchkServiceChk.setCommentId(segchkServiceCommentUserReq.getCommentId()); + segchkServiceChk.setChkServiceId(segchkServiceCommentUserReq.getChkServiceId()); + ret += segchkStoreIndexService.addCommentAccByComment(segchkServiceCommentUserReq.getCommentId()); + ret += segchkServiceChkMapper.updateSegchkServiceChk(segchkServiceChk); + return ret; + } + + /** + * 根据评价id,查询用户评价 + * + * @param segchkServiceCommentUserReq 用户评价提交实体 + * @return seg首页轮播图管理 + */ + @Override + public SegchkServiceComment selectSegchkServiceComment(SegchkServiceCommentUserReq segchkServiceCommentUserReq) { + logger.debug("selectSegchkServiceComment with: {}", segchkServiceCommentUserReq.toString()); + return segchkServiceCommentMapper.selectSegchkServiceCommentByCommentId(segchkServiceCommentUserReq.getCommentId()); + } + + /** + * 根据用户提交信息进行修改 + * + * @param segchkUserSetInfoReq 用户评价提交实体 + * @return 更新结果 + */ + @Override + public int updateUserInfo(SegchkUserSetInfoReq segchkUserSetInfoReq) { + logger.debug("updateUserInfo with: {}", segchkUserSetInfoReq.toString()); + SegchkUserSecurity segchkUserSecurity = new SegchkUserSecurity(); + segchkUserSecurity.setPasswd(segchkUserSetInfoReq.getPasswd()); + segchkUserSecurity.setUserId(segchkUserSetInfoReq.getUserId()); + segchkUserSecurity.setProviderId(segchkUserSetInfoReq.getProviderId()); + return segchkUserSecurityMapper.insertSegchkUserSecurity(segchkUserSecurity); + } + + /** + * 根据用户提交信息实名设置 + * + * @param segchkUserCertificationInfo 用户提交实体 + * @return 更新结果 + */ + @Override + public int userCerticify(SegchkUserCertificationInfo segchkUserCertificationInfo) { + logger.debug("userCerticify with: {}", segchkUserCertificationInfo.toString()); + SegchkUserCertificationInfo tmp = new SegchkUserCertificationInfo(); + tmp.setUserId(segchkUserCertificationInfo.getUserId()); + tmp.setProviderId(segchkUserCertificationInfo.getProviderId()); + List infos = segchkUserCertificationInfoMapper.selectSegchkUserCertificationInfoList(tmp); + if(infos == null || infos.isEmpty()){ + return segchkUserCertificationInfoMapper.insertSegchkUserCertificationInfo(segchkUserCertificationInfo); + } + else{ + segchkUserCertificationInfo.setUsercardId(infos.get(0).getUsercardId()); + return segchkUserCertificationInfoMapper.updateSegchkUserCertificationInfo(segchkUserCertificationInfo); + } + } + + /** + * 根据用户信息返回用户身份 + * + * @param phoneno 用户信息 + * @return 更新结果 + */ + @Override + public SegchkUserLevelInfo selectUserLevelByMobile(String phoneno) { + logger.debug("selectUserLevelByMobile with: {}", phoneno.toString()); + return segchkUserIndexMapper.selectUserLevelByMobile(phoneno); + } + + /** + * 根据用户信息注册用户基本信息表 + * + * @param segchkUserBasicInfo 用户信息 + * @return 插入结果 + */ + @Override + public int addUserBasicInfo(SegchkUserBasicInfo segchkUserBasicInfo) { + logger.debug("addUserBasicInfo with: {}", segchkUserBasicInfo.toString()); + return segchkUserBasicInfoMapper.insertSegchkUserBasicInfo(segchkUserBasicInfo); + } + + /** + * 根据推荐人信息,检查推荐人是否存在 + * + * @param parmMap 推荐人信息 + * @return 查询记录数 + */ + @Override + public int recommenderIsExit(Map parmMap) { + logger.debug("recommenderIsExit with: {}", parmMap.toString()); + return segchkUserIndexMapper.recommenderIsExit(parmMap); + } + + /** + * 根据推荐人信息,更新用户扩展信息表 + * + * @param segchkUserExtInfo 推荐人信息 + * @return 查询记录数 + */ + @Override + public int insertUserExtInfo(SegchkUserExtInfo segchkUserExtInfo) { + logger.debug("insertUserExtInfo with: {}", segchkUserExtInfo.toString()); + return segchkUserExtInfoMapper.insertSegchkUserExtInfo(segchkUserExtInfo); + } + + /** + * 根据用户基本信息查找用户微信信息 + * + * @param segchkUserLevelInfo 用户基本信息 + * @return 查询记录数 + */ + @Override + public String getWeChatInfoByUserId(SegchkUserLevelInfo segchkUserLevelInfo) { + logger.debug("getWeChatInfoByUserId with: {}", segchkUserLevelInfo.toString()); + if(segchkUserLevelInfo.getUserLevel() == 2) { + SegchkUserWechat segchkUserWechat = segchkUserWechatMapper.selectSegchkUserWechatByUserId(segchkUserLevelInfo.getUserId()); + if(ObjectUtils.isEmpty(segchkUserWechat) + || StringUtils.isEmpty(segchkUserWechat.getOpenid())){ + return null; + } + return segchkUserWechat.getOpenid(); + } + else if(segchkUserLevelInfo.getUserLevel() == 1){ + WeChatCustomerLink weChatCustomerLink = segchkStoreIndexService.selectWeChatInfoByStoreId(segchkUserLevelInfo.getUserId()); + return ObjectUtils.isEmpty(weChatCustomerLink) ? null : weChatCustomerLink.getOpenId(); + } + else if(segchkUserLevelInfo.getUserLevel() == 0){ + return segchkProviderIndexService.selectWeChatInfoByProviderId(segchkUserLevelInfo.getUserId()); + } + else return null; + } + + /** + * 根据用户信息,更新用户微信信息表 + * + * @param segchkUserWechat 用户基本信息 + * @param userLevel + * @return 查询记录数 + */ + @Override + public int updateWeChatInfoByUserId(SegchkUserWechat segchkUserWechat, String userLevel) { + logger.debug("updateWeChatInfoByUserId with: {}---{}", segchkUserWechat.toString(), userLevel); + if(!ObjectUtils.isEmpty(segchkUserWechat.getNickName())) { +// 如果用户昵称不空,则对昵称进行utf转换,避免用户昵称特殊字符无法存入 + try { + segchkUserWechat.setNickName(URLEncoder.encode(segchkUserWechat.getNickName(), "utf-8")); + } catch (UnsupportedEncodingException e) { + logger.error("updateWeChatInfoByUserId get nickName error: {}", e.getMessage()); + e.printStackTrace(); + } + } + switch (userLevel){ + case "0": return segchkUserIndexMapper.updateSegchkProviderWechat(segchkUserWechat); + case "1": return segchkUserIndexMapper.updateSegchkStoreWechat(segchkUserWechat); + case "2": return segchkUserIndexMapper.updateSegchkUserWechat(segchkUserWechat); + default: return -1; + } + } + + + @Transactional + public int makeCashOps(SegchkUserCashOpsReq segchkUserCashOpsReq, String ip) { + logger.debug("makeCashOps with: {}", segchkUserCashOpsReq.toString()); + int ret = 0; + int type = segchkUserCashOpsReq.getUserLevel(); + String cashId = null; + if(type == 1){ +// 说明是商户提现 + SegchkStoreCash segchkStoreCash = new SegchkStoreCash(); + segchkStoreCash.setCash(segchkUserCashOpsReq.getCash()); + segchkStoreCash.setCashType("0"); + segchkStoreCash.setProviderId(segchkUserCashOpsReq.getProviderId()); + segchkStoreCash.setStoreId(segchkUserCashOpsReq.getUserId()); + segchkStoreCash.setRetFlag("0"); +// 增加提现记录 + ret = segchkStoreCashMapper.insertSegchkStoreCash(segchkStoreCash); +// 根据提现计算商户全额 + ret += segchkIndexStoreAccountMapper.insertSegchkStoreAccountByCash(segchkStoreCash); + cashId = segchkStoreCash.getCashId().toString(); + } + else if(type == 2){ + SegchkUserCash segchkUserCash = new SegchkUserCash(); + segchkUserCash.setCash(segchkUserCashOpsReq.getCash()); + segchkUserCash.setCashType("0"); + segchkUserCash.setProviderId(segchkUserCashOpsReq.getProviderId()); + segchkUserCash.setUserId(segchkUserCashOpsReq.getUserId()); + segchkUserCash.setRetFlag(0); +// 增加提现记录 + ret = segchkUserCashMapper.insertSegchkUserCash(segchkUserCash); +// 根据提现计算最新的余额 + ret += segchkIndexUserAccountMapper.insertSegchkStoreAccountByCash(segchkUserCash); + cashId = segchkUserCash.getCashId().toString(); + + } + if(ret != 2 || StringUtils.isEmpty(cashId)){ + logger.error("makeCashOps fail due to create cash order createcnt{}---return{}---cashId{}....", ret, -12, cashId); + return -12; + } + String openId = segchkUserCashOpsReq.getSearchValue(); + Boolean usesandbox = !StringUtils.isEmpty(segchkUserCashOpsReq.getRemark()); + return wechatAppletTransfers(cashId, segchkUserCashOpsReq.getUserId(), segchkUserCashOpsReq.getProviderId(), ip, type, openId).getFlag(); + } + + /** + * 微信小程序支付 + * + * @param orderCode 订单code + * @param userId 用户id + * @param providerId 用户id + * @param ip 请求真实ip + * @param type 支付类型 1:订单支付 2:预存款充值 ---> 1用户支付,2商户支付 + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -3:没有待支付的订单 -5:微信生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + @Override + public CommonResponse wechatAppletPay(String orderCode, Long userId, Long providerId, String ip, int type) { + logger.debug("wechatAppletPay and orderCode:{} \r\n userId:{} \r\n ip:{} \r\n:type:{}", orderCode, userId, ip, type); + + /* WeChatCustomerLink weChatCustomerLink = weChatCustomerLinkService.queryWeChatCustomerLinkByCustomerId(customerId); + if (ObjectUtils.isEmpty(weChatCustomerLink) || StringUtils.isEmpty(weChatCustomerLink.getAppletOpenId())) { + logger.error("wechatAppletPay fail due to no weChatCustomerLink or appletOpenId is null...."); + return CommonResponse.build(null, -10); + }*/ + WeChatCustomerLink weChatCustomerLink = segchkUserIndexMapper.getUserWechatOpenId(userId); + logger.debug("wechatAppletPay get WeChatCustomerLink: {}", weChatCustomerLink.toString()); + if (ObjectUtils.isEmpty(weChatCustomerLink) || ObjectUtils.isEmpty(weChatCustomerLink.getOpenId())){ + logger.error("wechatAppletPay fail due to wechat error not auth...."); + return CommonResponse.build(null, -10); + } + return weChatCommonPay( + orderCode + , providerId + , userId + , type + , WechatSetting.build(ip, WechatUtils.APPLET_PAY, "/default/user/wechatnotify").addOpenId(weChatCustomerLink.getOpenId()), (setting, orderInfo) -> { + //获取预支付信息 + PrepayResult prepayResult = WechatUtils.getPrepay(setting, orderInfo); + //微信生成预支付信息错误 + if (ObjectUtils.isEmpty(prepayResult)) { + logger.error("wechatAppletPay fail due to wechat error...."); + return CommonResponse.build(null, -5); + } + return CommonResponse.build(prepayResult, 1); + }); + } + + + /** + * 微信小程序提现 + * + * @param orderCode 订单code + * @param userId 用户id + * @param providerId 用户id + * @param ip 请求真实ip + * @param type 支付类型 1:订单支付 2:预存款充值 ---> 2用户支付,1商户支付 + * @param openId + * @return 返回码和支付宝支付的html 返回码说明 -1:用户不存在 -3:没有待支付的订单 -5:微信生成订单出错 -7 没有设置网站地址 -8 缺少配置 -9 没有启用 1 成功 + */ + @Override + public CommonResponse wechatAppletTransfers(String orderCode, Long userId, Long providerId, String ip, int type, String openId) { + logger.debug("wechatAppletTransfers and orderCode:{} \r\n userId:{} \r\n ip:{} \r\n:type:{}", orderCode, userId, ip, type); + + return weChatCommonTransfer( + orderCode + , providerId + , userId + , type + , WechatSetting.build(ip, WechatUtils.APPLET_PAY, "").addOpenId(openId), (setting, orderInfo) -> { + //获取预支付信息 +// WxTransferResult wxTransferResult = WechatUtils.getTransfers(setting, orderInfo); + WxTransferResult wxTransferResult = null; + try { + SegchkWXPayConfigImpl instance = SegchkWXPayConfigImpl.getInstance(); + instance.setAppId(setting.getAppId()); + instance.setMchId(setting.getMerchantNum()); + instance.setMchKey(setting.getApiKey()); + instance.setCertData(setting.getCertFile()); + WXPay wxPay = new WXPay(instance, false, !ObjectUtils.isEmpty(sandbox)); + Map transfers = wxPay.transfers(orderInfo.getOrderCode(), openId, orderInfo.getPrice().toString(), String.valueOf(orderInfo.getType()), ip); + wxTransferResult = JSON.parseObject(JSON.toJSONString(transfers), WxTransferResult.class); + } catch (Exception e) { + e.printStackTrace(); + wxTransferResult = null; + } + //微信生成预支付信息错误 + if (ObjectUtils.isEmpty(wxTransferResult)) { + logger.error("wechatAppletTransfers fail due to wechat error...."); + return CommonResponse.build(null, -5); + } + return CommonResponse.build(wxTransferResult, 1); + }); + } + + /** + * 构建预支付订单信息 + * + * @param transCode 交易号 + * @param money 订单金额 + * @param type 类型 1:订单支付 2:预存款充值 + */ + private OrderInfoForPay buildOrderInfoForPay(String transCode, BigDecimal money, int type) { + OrderInfoForPay orderInfoForPay = new OrderInfoForPay(); + //商品名 + orderInfoForPay.setGoodsName("用户支付"); + //订单号 + orderInfoForPay.setOrderCode(transCode); + //订单金额 + orderInfoForPay.setPrice(money); + //支付类型 + orderInfoForPay.setType(type); + return orderInfoForPay; + } + + /** + * 构建预支付订单信息 + * + * @param transCode 交易号 + * @param money 订单金额 + * @param type 类型 1:订单支付 2:预存款充值 + */ + private OrderInfoForPay buildOrderInfoForTrans(String transCode, BigDecimal money, int type) { + OrderInfoForPay orderInfoForPay = new OrderInfoForPay(); + //商品名 + orderInfoForPay.setGoodsName("用户奖励"); + //订单号 + orderInfoForPay.setOrderCode(transCode + type); + //订单金额 + orderInfoForPay.setPrice(money); + //支付类型 + orderInfoForPay.setType(type); + return orderInfoForPay; + } + + /** + * 获得付款的实体 + * + * @param chargeId 订单code + * @param userId 会员id + * @param type 类型 1 订单 2 预存款 3 门店订单 + * @return 返回付款实体 + */ + private OrderInfoForPay getOrderInfoForPay(String chargeId, Long userId, int type) { + + SegchkUserCharge segchkUserCharge = segchkUserChargeMapper.selectSegchkUserChargeByChargeId(Long.valueOf(chargeId)); + if(ObjectUtils.isEmpty(segchkUserCharge)) { + return null; + } + return buildOrderInfoForPay(chargeId, segchkUserCharge.getCharge(), type); + } + + /** + * 获得付款的实体 + * + * @param cashId 订单code + * @param userId 会员id + * @param type 类型 1 商户 2 用户 3 门店订单 + * @return 返回付款实体 + */ + private OrderInfoForPay getTransfersInfoForPay(String cashId, Long userId, int type) { + switch (type){ + case 1: { + SegchkStoreCash segchkStoreCash = segchkStoreCashMapper.selectSegchkStoreCashByCashId(Long.valueOf(cashId)); + if(ObjectUtils.isEmpty(segchkStoreCash)) { + return null; + } + return buildOrderInfoForTrans(cashId, segchkStoreCash.getCash(), type); + } + case 2: { + SegchkUserCash segchkUserCash = segchkUserCashMapper.selectSegchkUserCashByCashId(Long.valueOf(cashId)); + if(ObjectUtils.isEmpty(segchkUserCash)) { + return null; + } + return buildOrderInfoForTrans(cashId, segchkUserCash.getCash(), type); + } + case 0: { + return null; + } + + } + return null; + + } + + /** + * 微信支付公共方法 + * + * @param orderCode 订单号 + * @param userId 用户id + * @param providerId 用户id + * @param type 支付类型 1 订单支付 2 预存充值 1商户,2用户 + * @param wechatSetting 微信设置 + * @param supplier 回调 + * @return -8 没有设置微信支付信息 -9 微信支付没启动 -7 没有配置站点信息 -1 用户不存在 -3 没有待支付订单 -5 微信生存支付信息失败 1 成功 + */ + private CommonResponse weChatCommonPay(String orderCode, Long providerId, Long userId, int type, WechatSetting wechatSetting, PaySupplier> supplier) { + + logger.debug("weChatCommonPay and orderCode:{} \r\n customerId:{} \r\n:type:{}", orderCode, userId, type); + + //微信支付设置(数据库) + WechatPaySet wechatPaySet = new WechatPaySet(); + + // 微信app、小程序支付和其他微信支付配置的信息不一样所以这边分开获取微信支付信息 +// wechatPaySet.setAppSecret(appSecrt); +// wechatPaySet.setAppId(appId); +// wechatPaySet.setIsUse("1"); + if (wechatSetting.isAppPay()) { + wechatPaySet = paySetService.queryPaySet().getWechatAppPaySet(); + } else if (wechatSetting.isAppletPay()) { +// 微信小程序 + wechatPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + } else { + wechatPaySet = paySetService.queryPaySet().getWechatPaySet(); + } + + // 没设置微信支付信息 + if (ObjectUtils.isEmpty(wechatPaySet)) { + logger.error("wechatQRPay fail due to no wechatPaySet is empty...."); + return CommonResponse.build(null, -8); + } + + // 微信支付没启用 + if (!wechatPaySet.checkIsUse()) { + logger.error("wechatQRPay fail due to not used...."); + return CommonResponse.build(null, -9); + } + + // 网站基本信息 + BaseInfoSet baseInfoSet = segchkSystemSettingService.queryBaseInfoSet(); + + if (ObjectUtils.isEmpty(baseInfoSet) || StringUtils.isEmpty(baseInfoSet.getSiteUrlWithBias()) || StringUtils.isEmpty(baseInfoSet.getSiteName())) { + logger.error("wechatH5Pay fail due to no baseinfoset...."); + return CommonResponse.build(null, -7); + } + + // 设置网站名称和网站地址 + wechatSetting.addSiteName(baseInfoSet.getSiteName()).addSiteUrl(baseInfoSet.getSiteUrlWithBias()); + + // 设置微信支付成功后回调地址 + wechatSetting.setPayCallback(baseInfoSet.getSiteUrlWithBias() + wechatSetting.getPayCallback()); + + BeanUtils.copyProperties(wechatPaySet, wechatSetting); + logger.info("wechatSetting="+wechatSetting); + + // 检查参数 + if (!wechatSetting.checkPayParams()) { + logger.error("wechatQRPay fail due to no checkPayParams fail...."); + return CommonResponse.build(null, -8); + } + + // 查询用户信息 + Map parmMap = new HashMap<>(); + parmMap.put("userId", userId); + parmMap.put("providerId", providerId); + int usercount = segchkUserIndexMapper.userIsExit(parmMap); + + // 用户信息为空 则直接返回 + if (Objects.isNull(usercount)) { + logger.error("weChatCommonPay fail due to member is not "); + return CommonResponse.build(null, -1); + } + + // 待支付订单 + OrderInfoForPay orderInfoForPay = getOrderInfoForPay(orderCode, userId, type); + + // 没有待支付订单直接返回 + if (Objects.isNull(orderInfoForPay)) { + logger.error("weChatCommonPay fail due to no order...."); + return CommonResponse.build(null, -3); + } + + return supplier.getPayParams(wechatSetting, orderInfoForPay); + } + + /** + * 微信提现公共方法 + * + * @param cashCode 订单号 + * @param userId 用户id + * @param providerId 用户id + * @param type 支付类型 1 订单支付 2 预存充值 1商户,2用户 + * @param wechatSetting 微信设置 + * @param supplier 回调 + * @return -8 没有设置微信支付信息 -9 微信支付没启动 -7 没有配置站点信息 -1 用户不存在 -3 没有待支付订单 -5 微信生存支付信息失败 1 成功 + */ + private CommonResponse weChatCommonTransfer(String cashCode, Long providerId, Long userId, int type, WechatSetting wechatSetting, PaySupplier> supplier) { + + logger.debug("weChatCommonTransfer and orderCode:{} \r\n customerId:{} \r\n:type:{}", cashCode, userId, type); + + //微信支付设置(数据库) + WechatPaySet wechatPaySet = new WechatPaySet(); + + // 微信app、小程序支付和其他微信支付配置的信息不一样所以这边分开获取微信支付信息 +// wechatPaySet.setAppSecret(appSecrt); +// wechatPaySet.setAppId(appId); +// wechatPaySet.setIsUse("1"); + if (wechatSetting.isAppPay()) { + wechatPaySet = paySetService.queryPaySet().getWechatAppPaySet(); + } else if (wechatSetting.isAppletPay()) { +// 小程序支付 + wechatPaySet = paySetService.queryPaySet().getWechatAppletPaySet(); + } else { + wechatPaySet = paySetService.queryPaySet().getWechatPaySet(); + } + + // 没设置微信支付信息 + if (ObjectUtils.isEmpty(wechatPaySet)) { + logger.error("weChatCommonTransfer fail due to no wechatPaySet is empty...."); + return CommonResponse.build(null, -8); + } + + // 微信支付没启用 + if (!wechatPaySet.checkIsUse()) { + logger.error("weChatCommonTransfer fail due to not used...."); + return CommonResponse.build(null, -9); + } + + // 微信支付没启用 + if (StringUtils.isEmpty(wechatPaySet.getCertFile())) { + logger.error("weChatCommonTransfer fail due to mch can not transfer...."); + return CommonResponse.build(null, -10); + } + + BeanUtils.copyProperties(wechatPaySet, wechatSetting); + logger.info("wechatSetting="+wechatSetting); + + // 检查参数 + if (!wechatSetting.checkPayParams()) { + logger.error("weChatCommonTransfer fail due to no checkPayParams fail...."); + return CommonResponse.build(null, -8); + } + + // 待支付订单 + OrderInfoForPay orderInfoForPay = getTransfersInfoForPay(cashCode, userId, type); + + // 没有待支付订单直接返回 + if (Objects.isNull(orderInfoForPay)) { + logger.error("weChatCommonTransfer fail due to no order...."); + return CommonResponse.build(null, -11); + } + + return supplier.getPayParams(wechatSetting, orderInfoForPay); + } + + @Override + public int weChatAppletNotify(InputStream inputStream) { + logger.debug("weChatAppletNotify...... "); + return weChatCommonNotify(inputStream, paySetService.queryPaySet().getWechatAppletPaySet()); + } + + /** + * 根据预约单,查询相关信息 + * + * @param segchkUserLikego 包含预约单id + * @return SegchkUserLikego + */ + @Override + public SegchkUserLikego selectUserLikeGo(SegchkUserLikego segchkUserLikego) { + List segchkUserLikegos = segchkUserLikegoMapper.selectSegchkUserLikegoList(segchkUserLikego); + if(ObjectUtils.isEmpty(segchkUserLikegos)){ + return null; + } + return segchkUserLikegos.get(0); + } + + @Override + public int insertSegchkUserCharge(SegchkUserCharge segchkUserCharge) { + int i = segchkUserChargeMapper.addSegchkUserChargeWithRecommend(segchkUserCharge); + if(i < 1){ +// 生成订单失败 + return i; + } + if(segchkUserCharge.getAccountUsed().compareTo(new BigDecimal(0.0)) > 1){ +// 只要使用了余额就进行余额更新无论充值是否实际发生支付 ,防止被其他行为如提现,返利打乱造成数据不一致 +// 如果全部使用用户余额支付,则更新用户余额信息 + SegchkUserAccount segchkUserAccount = new SegchkUserAccount(); + segchkUserAccount.setProviderId(segchkUserCharge.getProviderId()); + segchkUserAccount.setChargeId(segchkUserCharge.getChargeId()); + segchkUserAccount.setUserId(segchkUserCharge.getUserId()); +// 把用户使用充值的余额写进余额中 + segchkUserAccount.setAccount(segchkUserCharge.getAccountUsed()); + i = segchkUserAccountService.insertSegchkUserAccountBuyCharge(segchkUserAccount); + } + return i; + + } + + @Override + public SegchkUserWechat queryWeChatInfoByUserId(Claims claims) { + + switch (claims.getUserLevel()){ + case 0: { + String s = segchkProviderIndexService.selectWeChatInfoByProviderId(claims.getProviderId()); + SegchkUserWechat segchkUserWechat = new SegchkUserWechat(); + segchkUserWechat.setProviderId(claims.getProviderId()); + segchkUserWechat.setUserId(claims.getUserId()); + segchkUserWechat.setOpenid(s); + return segchkUserWechat; + } + case 1: { + WeChatCustomerLink weChatCustomerLink = segchkStoreIndexService.selectWeChatInfoByStoreId(claims.getUserId()); + SegchkUserWechat segchkUserWechat = new SegchkUserWechat(); + segchkUserWechat.setProviderId(claims.getProviderId()); + segchkUserWechat.setUserId(claims.getUserId()); + segchkUserWechat.setOpenid(weChatCustomerLink.getOpenId()); + segchkUserWechat.setUnionId(weChatCustomerLink.getUnionId()); + return segchkUserWechat; + } + case 2: {SegchkUserWechat segchkUserWechat = segchkUserWechatMapper.selectSegchkUserWechatByUserId(claims.getUserId()); + return segchkUserWechat; + } + default: {return null;} + } + } + + + /** + * 微信支付回调 + * + * @param inputStream 微信输入流 + * @param wechatPaySet 微信设置 + * @return 返回 0失败,大于0成功 + */ + private int weChatCommonNotify(InputStream inputStream, WechatPaySet wechatPaySet) { + logger.debug("weChatCommonNotifya and wechatPaySet:{}", wechatPaySet); + WechatSetting wechatSetting = new WechatSetting(); + BeanUtils.copyProperties(wechatPaySet, wechatSetting); + if (StringUtils.isEmpty(wechatPaySet.getAppId()) || StringUtils.isEmpty(wechatPaySet.getMerchantNum())) { + logger.error("weChatNotify fail due to no checkPayParams fail...."); + return -2; + } + OrderInfoAfterPay orderInfoAfterPay = WechatUtils.afterPayInfo(inputStream, wechatSetting); +// String chargeId = orderInfoAfterPay.getTransCode().substring(0, orderInfoAfterPay.getTransCode().length() - 1); + if (!orderInfoAfterPay.isSuccess()) { + logger.error("weChatNotify fail due to notify fail...."); + + chargeRet(orderInfoAfterPay.getOrderCode(), 1); + return -3; + } + chargeRet(orderInfoAfterPay.getOrderCode(), 0); + return 1; +// return paySuccess(orderInfoAfterPay.getOrderCode(), CommonConstant.QUERY_WITH_NO_CUSTOMER, orderInfoAfterPay.getType(), CommonConstant.WECHAT_PAY, orderInfoAfterPay.getTransCode()); + } + + /** + * 支付成功后的操作 + * + * @param orderCode 订单code + * @param customerId 用户id + * @param type 1:订单支付 2 预存款充值 + * @param channel 支付方式,预存款充值使用 + * @param transCode 交易流水号 + * @return 0失败,大于0成功 + */ + /*private int paySuccess(String orderCode, long customerId, int type, String channel, String transCode) { + logger.debug("paySuccess and orderCode:{} \r\n customerId:{} \r\n type:{} \r\n transCode:{}", orderCode, customerId, type, transCode); + //订单支付 + if (CommonConstant.ORDER_PAY == type) { + // 根据订单编号和用户id查询待付款的订单信息 + List orders = orderService.queryOrderByOrderCode(orderCode, customerId); + // 没有待支付的订单 则直接返回 + if (CollectionUtils.isEmpty(orders)) { + logger.error("paySuccess fail due to no order...."); + return -1; + } + // 修改订单状态 + return orderServiceApi.confirmOrderPayed(ConfirmOrderParams.buildCustomerSource(customerId, 0, orders.stream().map(OmsOrder::getOrderCode).collect(Collectors.toList()), transCode, channel)); + } else if (CommonConstant.RECHARGE_PAY == type) { + //预存款充值 + return predepositRecordServiceApi.updateStatusSuccessByTransCode(orderCode, CommonConstant.QUERY_WITH_NO_CUSTOMER, channel, transCode); + } else { + // 根据订单编号和用户id查询待付款的门店订单信息 + List storeOrders = storeOrderService.queryOrderByOrderCode(orderCode, customerId); + + if (CollectionUtils.isEmpty(storeOrders)) { + logger.error("paySuccess fail due to no order...."); + return -1; + } + + return storeOrderServiceApi.confirmOrderPayed(customerId, storeOrders.stream().map(TStoreOrder::getOrderCode).collect(Collectors.toList()), "0", transCode, channel); + } + + }*/ + + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserLikegoServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserLikegoServiceImpl.java new file mode 100644 index 0000000..5c78c47 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserLikegoServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.segchk.domain.SegchkUserLikego; +import com.ruoyi.segchk.mapper.SegchkUserLikegoMapper; +import com.ruoyi.segchk.service.ISegchkUserLikegoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * seg用户想去记录Service业务层处理 + * + * @author yinzhiying + * @date 2021-08-23 + */ +@Service +public class SegchkUserLikegoServiceImpl implements ISegchkUserLikegoService +{ + @Autowired + private SegchkUserLikegoMapper segchkUserLikegoMapper; + + /** + * 查询seg用户想去记录 + * + * @param likegoId seg用户想去记录主键 + * @return seg用户想去记录 + */ + @Override + public SegchkUserLikego selectSegchkUserLikegoByLikegoId(Long likegoId) + { + return segchkUserLikegoMapper.selectSegchkUserLikegoByLikegoId(likegoId); + } + + /** + * 查询seg用户想去记录列表 + * + * @param segchkUserLikego seg用户想去记录 + * @return seg用户想去记录 + */ + @Override + public List selectSegchkUserLikegoList(SegchkUserLikego segchkUserLikego) + { + return segchkUserLikegoMapper.selectSegchkUserLikegoList(segchkUserLikego); + } + + /** + * 新增seg用户想去记录 + * + * @param segchkUserLikego seg用户想去记录 + * @return 结果 + */ + @Override + public int insertSegchkUserLikego(SegchkUserLikego segchkUserLikego) + { + // 此处根据用户id,卡id,卡类型,卡标签,商户id,及运营商id,生成预约二维码 + segchkUserLikego.setQrCode(String.format("qrcode-%s-%s-%s-%s-%s", segchkUserLikego.getProviderId(), segchkUserLikego.getStoreId(), segchkUserLikego.getUserId(), segchkUserLikego.getCardId(), segchkUserLikego.getCardType())); + return segchkUserLikegoMapper.insertSegchkUserLikego(segchkUserLikego); + } + + /** + * 修改seg用户想去记录 + * + * @param segchkUserLikego seg用户想去记录 + * @return 结果 + */ + @Override + public int updateSegchkUserLikego(SegchkUserLikego segchkUserLikego) + { + return segchkUserLikegoMapper.updateSegchkUserLikego(segchkUserLikego); + } + + /** + * 批量删除seg用户想去记录 + * + * @param likegoIds 需要删除的seg用户想去记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserLikegoByLikegoIds(Long[] likegoIds) + { + return segchkUserLikegoMapper.deleteSegchkUserLikegoByLikegoIds(likegoIds); + } + + /** + * 删除seg用户想去记录信息 + * + * @param likegoId seg用户想去记录主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserLikegoByLikegoId(Long likegoId) + { + return segchkUserLikegoMapper.deleteSegchkUserLikegoByLikegoId(likegoId); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserWechatServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserWechatServiceImpl.java new file mode 100644 index 0000000..25eaa10 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/segchk/service/impl/SegchkUserWechatServiceImpl.java @@ -0,0 +1,94 @@ +package com.ruoyi.segchk.service.impl; + +import com.ruoyi.segchk.domain.SegchkUserWechat; +import com.ruoyi.segchk.mapper.SegchkUserWechatMapper; +import com.ruoyi.segchk.service.ISegchkUserWechatService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * seg用户微信信息Service业务层处理 + * + * @author yinzhiying + * @date 2021-08-23 + */ +@Service +public class SegchkUserWechatServiceImpl implements ISegchkUserWechatService +{ + @Autowired + private SegchkUserWechatMapper segchkUserWechatMapper; + + /** + * 查询seg用户微信信息 + * + * @param userId seg用户微信信息主键 + * @return seg用户微信信息 + */ + @Override + public SegchkUserWechat selectSegchkUserWechatByUserId(Long userId) + { + return segchkUserWechatMapper.selectSegchkUserWechatByUserId(userId); + } + + /** + * 查询seg用户微信信息列表 + * + * @param segchkUserWechat seg用户微信信息 + * @return seg用户微信信息 + */ + @Override + public List selectSegchkUserWechatList(SegchkUserWechat segchkUserWechat) + { + return segchkUserWechatMapper.selectSegchkUserWechatList(segchkUserWechat); + } + + /** + * 新增seg用户微信信息 + * + * @param segchkUserWechat seg用户微信信息 + * @return 结果 + */ + @Override + public int insertSegchkUserWechat(SegchkUserWechat segchkUserWechat) + { + return segchkUserWechatMapper.insertSegchkUserWechat(segchkUserWechat); + } + + /** + * 修改seg用户微信信息 + * + * @param segchkUserWechat seg用户微信信息 + * @return 结果 + */ + @Override + public int updateSegchkUserWechat(SegchkUserWechat segchkUserWechat) + { + return segchkUserWechatMapper.updateSegchkUserWechat(segchkUserWechat); + } + + /** + * 批量删除seg用户微信信息 + * + * @param userIds 需要删除的seg用户微信信息主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserWechatByUserIds(Long[] userIds) + { + return segchkUserWechatMapper.deleteSegchkUserWechatByUserIds(userIds); + } + + /** + * 删除seg用户微信信息信息 + * + * @param userId seg用户微信信息主键 + * @return 结果 + */ + @Override + public int deleteSegchkUserWechatByUserId(Long userId) + { + return segchkUserWechatMapper.deleteSegchkUserWechatByUserId(userId); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/AliPaySet.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/AliPaySet.java new file mode 100644 index 0000000..246ca7a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/AliPaySet.java @@ -0,0 +1,83 @@ +package com.ruoyi.setting.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 支付设置接口-支付宝支付接口设置实体类 + * + * @author 魔金商城 on 2017/5/17. + */ + +public class AliPaySet { + /** + * appid + */ + + private String appId; + /** + * 开发者私钥,由开发者自己生成 + */ + + private String appPrivateKey; + /** + * 支付宝公钥,由支付宝生成 + */ + + private String alipayPublicKey; + /** + * 是否启用 1启用 0不启用 + */ + + private String isUse; + + /** + * 清理敏感信息 + */ + public void clearSensitiveInfo() { + this.appId = ""; + this.appPrivateKey = ""; + this.alipayPublicKey = ""; + } + + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppPrivateKey() { + return appPrivateKey; + } + + public void setAppPrivateKey(String appPrivateKey) { + this.appPrivateKey = appPrivateKey; + } + + public String getAlipayPublicKey() { + return alipayPublicKey; + } + + public void setAlipayPublicKey(String alipayPublicKey) { + this.alipayPublicKey = alipayPublicKey; + } + + public String getIsUse() { + return isUse; + } + + public void setIsUse(String isUse) { + this.isUse = isUse; + } + + /** + * 检测是否启用 true 启用,反之不启用 + */ + @JsonIgnore + public boolean checkIsUse() { + return StringUtils.isEmpty(isUse) || "1".equals(isUse); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/OssSetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/OssSetting.java new file mode 100644 index 0000000..225a16a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/OssSetting.java @@ -0,0 +1,136 @@ +package com.ruoyi.setting.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ruoyi.util.bean.OssYunConf; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * Created by luozhuo on 20/7/7. + * 云存储配置类 + */ +@ApiModel(description = "云存储配置实体") +public class OssSetting { + + /** + * 主键id + */ + @ApiModelProperty(value = "主键id") + private Long id; + + /** + * 域名 + */ + @ApiModelProperty(value = "域名") + private String address; + + /** + * 授权ID + */ + @ApiModelProperty(value = "授权ID") + private String accessKeyId; + + /** + * 授权密钥 + */ + @ApiModelProperty(value = "授权密钥") + private String accessKeySecret; + + /** + * 桶名 + */ + @ApiModelProperty(value = "桶名") + private String bucketName; + + /** + * 节点名 + */ + @ApiModelProperty(value = "节点名") + private String endPoint; + + /** + * 样式 + */ + @ApiModelProperty(value = "样式") + private String styleName; + + /** + * 前缀 + */ + @ApiModelProperty(value = "前缀") + private String prefix; + + /** + * 获得阿里云的配置 + * + * @return 返回阿里云配置 + */ + @JsonIgnore + public OssYunConf getUpYunConf() { + return OssYunConf.buildOssYunConf(this.accessKeyId, this.accessKeySecret, this.bucketName, this.endPoint, this.styleName, this.prefix, this.address); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getAccessKeyId() { + return accessKeyId; + } + + public void setAccessKeyId(String accessKeyId) { + this.accessKeyId = accessKeyId; + } + + public String getAccessKeySecret() { + return accessKeySecret; + } + + public void setAccessKeySecret(String accessKeySecret) { + this.accessKeySecret = accessKeySecret; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getEndPoint() { + return endPoint; + } + + public void setEndPoint(String endPoint) { + this.endPoint = endPoint; + } + + public String getStyleName() { + return styleName; + } + + public void setStyleName(String styleName) { + this.styleName = styleName; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySet.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySet.java new file mode 100644 index 0000000..bbfa9b8 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySet.java @@ -0,0 +1,75 @@ +package com.ruoyi.setting.bean; + + +/** + * 支付接口设置数据库映射类 + * + * @author 魔金商城 on 2017/5/17. + */ + +public class PaySet { + /** + * 主键id + */ + private long id; + /** + * 支付方式 1:支付宝 2:微信 3:银联 4:预存款 5:微信APP支付 6:微信小程序支付 + */ + private String codeType; + /** + * 字段名称 + */ + private String columnName; + /** + * 字段值 + */ + private String columnValue; + + /** + * 组装数据-用于向数据库插入数据 + * + * @param paySet 数据库映射对象 + * @param codeType 支付设置类型 1:支付宝 2:微信 3:银联 4:预存款 5:微信APP支付 6:微信小程序支付 + * @param columnValue 字段的值 + * @param columnName 字段名称 + * @return paySet对象 + */ + public static PaySet getPaySet(PaySet paySet, String codeType, String columnValue, String columnName) { + paySet.setCodeType(codeType); + paySet.setColumnName(columnName); + paySet.setColumnValue(columnValue); + return paySet; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getCodeType() { + return codeType; + } + + public void setCodeType(String codeType) { + this.codeType = codeType; + } + + public String getColumnName() { + return columnName; + } + + public void setColumnName(String columnName) { + this.columnName = columnName; + } + + public String getColumnValue() { + return columnValue; + } + + public void setColumnValue(String columnValue) { + this.columnValue = columnValue; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySetCommon.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySetCommon.java new file mode 100644 index 0000000..f75c1e0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PaySetCommon.java @@ -0,0 +1,232 @@ +package com.ruoyi.setting.bean; + + +import java.util.List; +import java.util.Objects; + +/** + * 支付设置统一类 + * + * @author 魔金商城 on 2017/5/17. + */ + +public class PaySetCommon { + + /** + * 阿里支付 + */ + private AliPaySet aliPaySet = new AliPaySet(); + /** + * 微信支付(公众号、扫码、H5) + */ + + private WechatPaySet wechatPaySet = new WechatPaySet(); + /** + * 微信支付(app) + */ + + private WechatPaySet wechatAppPaySet = new WechatPaySet(); + + /** + * 微信支付(小程序支付) + */ + + private WechatPaySet wechatAppletPaySet = new WechatPaySet(); + + /** + * 银联支付 + */ + private UnionPaySet unionPaySet = new UnionPaySet(); + + /** + * 预存款支付 + */ + private PrePaySet prePaySet = new PrePaySet(); + + /** + * 用于组装支付设置对象在前端显示 + * + * @param paySetCommon 支付设置对象 + * @param paySets 数据库映射对象 + * @return 支付设置对象 + */ + public static PaySetCommon getPaySetCommon(PaySetCommon paySetCommon, List paySets) { + paySets.forEach(paySet -> { + String value = paySet.getColumnValue(); + //支付宝 + if ("1".equals(paySet.getCodeType())) { + if ("appId".equals(paySet.getColumnName())) { + paySetCommon.aliPaySet.setAppId(value); + } + if ("alipayPublicKey".equals(paySet.getColumnName())) { + paySetCommon.aliPaySet.setAlipayPublicKey(value); + } + if ("appPrivateKey".equals(paySet.getColumnName())) { + paySetCommon.aliPaySet.setAppPrivateKey(value); + } + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.aliPaySet.setIsUse(value); + } + } + //微信(公众号、扫码、H5) + if ("2".equals(paySet.getCodeType())) { + if ("appId".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setAppId(value); + } + if ("appSecret".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setAppSecret(value); + } + if ("merchantNum".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setMerchantNum(value); + } + if ("apiKey".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setApiKey(value); + } + if ("loginNotice".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setLoginNotice(value); + } + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.wechatPaySet.setIsUse(value); + } + } + //银联 + if ("3".equals(paySet.getCodeType())) { + if ("merchantNum".equals(paySet.getColumnName())) { + paySetCommon.unionPaySet.setMerchantNum(value); + } + if ("apiKey".equals(paySet.getColumnName())) { + paySetCommon.unionPaySet.setApiKey(value); + } + + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.unionPaySet.setIsUse(value); + } + } + //预存款 + if ("4".equals(paySet.getCodeType())) { + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.prePaySet.setIsUse(value); + } + } + //微信支付(app) + if ("5".equals(paySet.getCodeType())) { + if ("appId".equals(paySet.getColumnName())) { + paySetCommon.wechatAppPaySet.setAppId(value); + } + if ("appSecret".equals(paySet.getColumnName())) { + paySetCommon.wechatAppPaySet.setAppSecret(value); + } + if ("merchantNum".equals(paySet.getColumnName())) { + paySetCommon.wechatAppPaySet.setMerchantNum(value); + } + if ("apiKey".equals(paySet.getColumnName())) { + paySetCommon.wechatAppPaySet.setApiKey(value); + } + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.wechatAppPaySet.setIsUse(value); + } + } + + //微信支付(小程序) + if ("6".equals(paySet.getCodeType())) { + if ("appId".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setAppId(value); + } + if ("appSecret".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setAppSecret(value); + } + if ("merchantNum".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setMerchantNum(value); + } + if ("apiKey".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setApiKey(value); + } + if ("isUse".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setIsUse(value); + } + if ("certFile".equals(paySet.getColumnName())) { + paySetCommon.wechatAppletPaySet.setCertFile(value); + } + } + }); + return paySetCommon; + } + + /** + * 清除敏感 信息 + * + * @return 返回当前对象 + */ + public PaySetCommon clearSensitiveInfo() { + + if (Objects.nonNull(this.wechatPaySet)) { + wechatPaySet.clearSensitiveInfo(); + } + + if (Objects.nonNull(this.wechatAppPaySet)) { + wechatAppPaySet.clearSensitiveInfo(); + } + + if (Objects.nonNull(this.wechatAppletPaySet)) { + wechatAppletPaySet.clearSensitiveInfo(); + } + + if (Objects.nonNull(this.aliPaySet)) { + aliPaySet.clearSensitiveInfo(); + } + + + if (Objects.nonNull(this.unionPaySet)) { + unionPaySet.clearSensitiveInfo(); + } + return this; + } + + public AliPaySet getAliPaySet() { + return aliPaySet; + } + + public void setAliPaySet(AliPaySet aliPaySet) { + this.aliPaySet = aliPaySet; + } + + public WechatPaySet getWechatPaySet() { + return wechatPaySet; + } + + public void setWechatPaySet(WechatPaySet wechatPaySet) { + this.wechatPaySet = wechatPaySet; + } + + public WechatPaySet getWechatAppPaySet() { + return wechatAppPaySet; + } + + public void setWechatAppPaySet(WechatPaySet wechatAppPaySet) { + this.wechatAppPaySet = wechatAppPaySet; + } + + public WechatPaySet getWechatAppletPaySet() { + return wechatAppletPaySet; + } + + public void setWechatAppletPaySet(WechatPaySet wechatAppletPaySet) { + this.wechatAppletPaySet = wechatAppletPaySet; + } + + public UnionPaySet getUnionPaySet() { + return unionPaySet; + } + + public void setUnionPaySet(UnionPaySet unionPaySet) { + this.unionPaySet = unionPaySet; + } + + public PrePaySet getPrePaySet() { + return prePaySet; + } + + public void setPrePaySet(PrePaySet prePaySet) { + this.prePaySet = prePaySet; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PrePaySet.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PrePaySet.java new file mode 100644 index 0000000..50d868b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/PrePaySet.java @@ -0,0 +1,33 @@ +package com.ruoyi.setting.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 预支付设置 + */ + +public class PrePaySet { + + /** + * 是否启用 1启用 0不启用 + */ + + private String isUse; + + public String getIsUse() { + return isUse; + } + + public void setIsUse(String isUse) { + this.isUse = isUse; + } + + /** + * 检测是否启用 true 启用,反之不启用 + */ + @JsonIgnore + public boolean checkIsUse() { + return StringUtils.isEmpty(isUse) || "1".equals(isUse); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UnionPaySet.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UnionPaySet.java new file mode 100644 index 0000000..896558b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UnionPaySet.java @@ -0,0 +1,68 @@ +package com.ruoyi.setting.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 支付设置接口-银联支付接口设置实体类 + * + * @author 魔金商城 on 2017/5/17. + */ + +public class UnionPaySet { + /** + * 商户号 + */ + private String merchantNum; + /** + * API-KEY + */ + private String apiKey; + /** + * 是否启用 1启用 0不启用 + */ + + private String isUse; + + public String getMerchantNum() { + return merchantNum; + } + + public void setMerchantNum(String merchantNum) { + this.merchantNum = merchantNum; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getIsUse() { + return isUse; + } + + public void setIsUse(String isUse) { + this.isUse = isUse; + } + + /** + * 清理敏感信息 + */ + public void clearSensitiveInfo() { + this.merchantNum = ""; + this.apiKey = ""; + } + + + /** + * 检测是否启用 true 启用,反之不启用 + */ + @JsonIgnore + public boolean checkIsUse() { + return StringUtils.isEmpty(isUse) || "1".equals(isUse); + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UploadData.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UploadData.java new file mode 100644 index 0000000..cb46369 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/UploadData.java @@ -0,0 +1,91 @@ +package com.ruoyi.setting.bean; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; + +/** + * 上传对象实体类 + */ +public class UploadData { + + MultipartFile multipartFile; + /** + * 输入流 + */ + private InputStream inputStream; + + /** + * 数据 + */ + private byte[] datas; + + + /** + * 用户上传的文件名 + */ + private String fileOriginName; + + /** + * 上传的类型 0 图片 1 视频 + */ + private String type; + + + /** + * 构造上传对象 + * + * @param inputStream 输入流 + * @param datas 数据 + * @return 返回上传对象 + */ + public static UploadData build(InputStream inputStream, byte[] datas, String fileOriginName, String type, MultipartFile multipartFile) { + UploadData uploadData = new UploadData(); + uploadData.inputStream = inputStream; + uploadData.datas = datas; + uploadData.fileOriginName = fileOriginName; + uploadData.type = type; + uploadData.multipartFile = multipartFile; + return uploadData; + } + + public MultipartFile getMultipartFile() { + return multipartFile; + } + + public void setMultipartFile(MultipartFile multipartFile) { + this.multipartFile = multipartFile; + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + public byte[] getDatas() { + return datas; + } + + public void setDatas(byte[] datas) { + this.datas = datas; + } + + public String getFileOriginName() { + return fileOriginName; + } + + public void setFileOriginName(String fileOriginName) { + this.fileOriginName = fileOriginName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/WechatPaySet.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/WechatPaySet.java new file mode 100644 index 0000000..17e9cec --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/bean/WechatPaySet.java @@ -0,0 +1,126 @@ +package com.ruoyi.setting.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 支付设置接口-微信支付接口设置实体类 + * + * @author 魔金商城 on 2017/5/17. + */ + +public class WechatPaySet { + /** + * 公众号appId + */ + + private String appId; + /** + * AppSecret + */ + + private String appSecret; + /** + * 商户号 + */ + + private String merchantNum; + + /** + * API密钥 + */ + + private String apiKey; + + /** + * 微信公众号 登录回调地址 + */ + private String loginNotice; + + /** + * 是否启用 1启用 0不启用 + */ + + private String isUse; + + /** + * 是否启用 1启用 0不启用 + */ + + private String certFile; + + /** + * 清理敏感信息 + */ + public void clearSensitiveInfo() { + this.appId = ""; + this.appSecret = ""; + this.merchantNum = ""; + this.apiKey = ""; + this.certFile = ""; + } + + public String getLoginNotice() { + return loginNotice; + } + + public void setLoginNotice(String loginNotice) { + this.loginNotice = loginNotice; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } + + public String getMerchantNum() { + return merchantNum; + } + + public void setMerchantNum(String merchantNum) { + this.merchantNum = merchantNum; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getIsUse() { + return isUse; + } + + public void setIsUse(String isUse) { + this.isUse = isUse; + } + + /** + * 检测是否启用 true 启用,反之不启用 + */ + @JsonIgnore + public boolean checkIsUse() { + return StringUtils.isEmpty(isUse) || "1".equals(isUse); + } + + public String getCertFile() { + return certFile; + } + + public void setCertFile(String certFile) { + this.certFile = certFile; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/KsdSmsReq.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/KsdSmsReq.java new file mode 100644 index 0000000..3e68416 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/KsdSmsReq.java @@ -0,0 +1,5 @@ +package com.ruoyi.setting.domain; + + +public class KsdSmsReq { +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsCity.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsCity.java new file mode 100644 index 0000000..5144aca --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsCity.java @@ -0,0 +1,158 @@ +package com.ruoyi.setting.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.Date; +import java.util.List; + +/** + * 区域市对象 ls_city + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsCity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 市的名称 + */ + @Excel(name = "市的名称") + private String name; + + /** + * 该市所属的省份id 对应ls_province 中的id + */ + @Excel(name = "该市所属的省份id 对应ls_province 中的id") + private Long provinceId; + + /** + * 排序 数值越小 排序越前 + */ + @Excel(name = "排序 数值越小 排序越前") + private Long sort; + + /** + * 删除标记 0未删除 1删除 默认0 + */ + private int delFlag; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modifyTime; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "删除时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date delTime; + + /** + * 市下面的区 + */ + @ApiModelProperty(value = "市下面的区") + private List child; + + + /** + * 设置添加市的默认 + * + * @return 返回市 + */ + public LsCity setDefaultValuesForAdd() { + this.delFlag = 0; + return this; + } + + 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 Long getProvinceId() { + return provinceId; + } + + public void setProvinceId(Long provinceId) { + this.provinceId = provinceId; + } + + public Long getSort() { + return sort; + } + + public void setSort(Long sort) { + this.sort = sort; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + public Date getDelTime() { + return delTime; + } + + public void setDelTime(Date delTime) { + this.delTime = delTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("provinceId", getProvinceId()) + .append("sort", getSort()) + .append("delFlag", getDelFlag()) + .append("createTime", getCreateTime()) + .append("modifyTime", getModifyTime()) + .append("delTime", getDelTime()) + .toString(); + } + + public List getChild() { + return child; + } + + public void setChild(List child) { + this.child = child; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsDistrict.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsDistrict.java new file mode 100644 index 0000000..84f2aac --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsDistrict.java @@ -0,0 +1,131 @@ +package com.ruoyi.setting.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.Date; + +/** + * 区域区对象 ls_district + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsDistrict extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 区名称 + */ + @Excel(name = "区名称") + private String name; + + /** + * 对应ls_city表中的id + */ + @Excel(name = "对应ls_city表中的id") + private Long cityId; + + /** + * 排序 数值越小 越前 + */ + @Excel(name = "排序 数值越小 越前") + private Long sort; + + /** + * 删除标记 0 未删除 1删除 默认0 + */ + private int delFlag; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modifyTime; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "删除时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date delTime; + + 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 Long getCityId() { + return cityId; + } + + public void setCityId(Long cityId) { + this.cityId = cityId; + } + + public Long getSort() { + return sort; + } + + public void setSort(Long sort) { + this.sort = sort; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + public Date getDelTime() { + return delTime; + } + + public void setDelTime(Date delTime) { + this.delTime = delTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("cityId", getCityId()) + .append("sort", getSort()) + .append("delFlag", getDelFlag()) + .append("createTime", getCreateTime()) + .append("modifyTime", getModifyTime()) + .append("delTime", getDelTime()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsEmailSetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsEmailSetting.java new file mode 100644 index 0000000..353c094 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsEmailSetting.java @@ -0,0 +1,126 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 邮箱设置对象 ls_email_setting + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public class LsEmailSetting extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 发信邮箱 + */ + @Excel(name = "发信邮箱") + private String senderMail; + + /** + * 发信人 + */ + @Excel(name = "发信人") + private String senderName; + + /** + * SMTP的服务器地址 + */ + @Excel(name = "SMTP的服务器地址") + private String smtpServer; + + /** + * SMTP 的端口 + */ + @Excel(name = "SMTP 的端口") + private Long smtpPort; + + /** + * 邮箱帐号 + */ + @Excel(name = "邮箱帐号") + private String username; + + /** + * 邮箱密码 + */ + @Excel(name = "邮箱密码") + private String password; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSenderMail() { + return senderMail; + } + + public void setSenderMail(String senderMail) { + this.senderMail = senderMail; + } + + public String getSenderName() { + return senderName; + } + + public void setSenderName(String senderName) { + this.senderName = senderName; + } + + public String getSmtpServer() { + return smtpServer; + } + + public void setSmtpServer(String smtpServer) { + this.smtpServer = smtpServer; + } + + public Long getSmtpPort() { + return smtpPort; + } + + public void setSmtpPort(Long smtpPort) { + this.smtpPort = smtpPort; + } + + 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; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("senderMail", getSenderMail()) + .append("senderName", getSenderName()) + .append("smtpServer", getSmtpServer()) + .append("smtpPort", getSmtpPort()) + .append("username", getUsername()) + .append("password", getPassword()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsProvince.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsProvince.java new file mode 100644 index 0000000..becc46f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsProvince.java @@ -0,0 +1,141 @@ +package com.ruoyi.setting.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.Date; +import java.util.List; + +/** + * 区域省对象 ls_province + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsProvince extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 省份的名称 + */ + @Excel(name = "省份的名称") + private String name; + + /** + * 排序 + */ + @Excel(name = "排序") + private Long sort; + + /** + * 删除标记 0 未删除 1删除 + */ + private int delFlag; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date modifyTime; + + /** + * 删除时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "删除时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date delTime; + /** + * 省下面的市 + */ + @ApiModelProperty(value = "省下面的市") + private List child; + + /** + * 设置添加省份的默认 + * + * @return 返回省份 + */ + public LsProvince setDefaultValuesForAdd() { + this.delFlag = 0; + return this; + } + + 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 Long getSort() { + return sort; + } + + public void setSort(Long sort) { + this.sort = sort; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + public Date getDelTime() { + return delTime; + } + + public void setDelTime(Date delTime) { + this.delTime = delTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("sort", getSort()) + .append("delFlag", getDelFlag()) + .append("createTime", getCreateTime()) + .append("modifyTime", getModifyTime()) + .append("delTime", getDelTime()) + .toString(); + } + + public List getChild() { + return child; + } + + public void setChild(List child) { + this.child = child; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSmsSetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSmsSetting.java new file mode 100644 index 0000000..abd3da4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSmsSetting.java @@ -0,0 +1,197 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 短信接口设置对象 ls_sms_setting + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public class LsSmsSetting extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * AppSecret + */ + @Excel(name = "AppSecret") + private String secret; + + /** + * 短信接口地址 + */ + @Excel(name = "短信接口地址") + private String url; + + /** + * 短信签名 + */ + @Excel(name = "短信签名") + private String sign; + + /** + * 模板id + */ + @Excel(name = "模板id") + private String templateId; + + /** + * 核销门店订单的模版id + */ + @Excel(name = "核销门店订单的模版id") + private String writeoffTemplateId; + + /** + * 虚拟订单核销的模版id + */ + @Excel(name = "虚拟订单核销的模版id") + private String virtualOrderTemplateId; + + /** + * AppKey + */ + @Excel(name = "AppKey") + private String key; + + /** + * 社区团购审核结果通知模版id + */ + @Excel(name = "社区团购审核结果通知模版id") + private String auditTemplateId; + + /** + * 社区团购佣金结算模版id + */ + @Excel(name = "社区团购佣金结算模版id") + private String settlementTemplateId; + + /** + * 社区团购提现打款模版id + */ + @Excel(name = "社区团购提现打款模版id") + private String withdrawTemplateId; + @ApiModelProperty("启用状态") + private Boolean status; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getTemplateId() { + return templateId; + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + } + + public String getWriteoffTemplateId() { + return writeoffTemplateId; + } + + public void setWriteoffTemplateId(String writeoffTemplateId) { + this.writeoffTemplateId = writeoffTemplateId; + } + + public String getVirtualOrderTemplateId() { + return virtualOrderTemplateId; + } + + public void setVirtualOrderTemplateId(String virtualOrderTemplateId) { + this.virtualOrderTemplateId = virtualOrderTemplateId; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getAuditTemplateId() { + return auditTemplateId; + } + + public void setAuditTemplateId(String auditTemplateId) { + this.auditTemplateId = auditTemplateId; + } + + public String getSettlementTemplateId() { + return settlementTemplateId; + } + + public void setSettlementTemplateId(String settlementTemplateId) { + this.settlementTemplateId = settlementTemplateId; + } + + public String getWithdrawTemplateId() { + return withdrawTemplateId; + } + + public void setWithdrawTemplateId(String withdrawTemplateId) { + this.withdrawTemplateId = withdrawTemplateId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("secret", getSecret()) + .append("url", getUrl()) + .append("sign", getSign()) + .append("templateId", getTemplateId()) + .append("writeoffTemplateId", getWriteoffTemplateId()) + .append("virtualOrderTemplateId", getVirtualOrderTemplateId()) + .append("key", getKey()) + .append("auditTemplateId", getAuditTemplateId()) + .append("settlementTemplateId", getSettlementTemplateId()) + .append("withdrawTemplateId", getWithdrawTemplateId()) + .toString(); + } + + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsStationLetter.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsStationLetter.java new file mode 100644 index 0000000..6fd2656 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsStationLetter.java @@ -0,0 +1,111 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 站内信对象 ls_station_letter + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsStationLetter extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 会员id + */ + @Excel(name = "会员id") + private Long customerId; + + /** + * 站内信标题 + */ + @Excel(name = "站内信标题") + private String title; + + /** + * 站内信内容 + */ + @Excel(name = "站内信内容") + private String content; + + /** + * 是否已读 0 未读 1 已读 默认0 + */ + @Excel(name = "是否已读 0 未读 1 已读 默认0 ") + private String isRead; + + /** + * 删除标记 0 未删除 1 删除 默认0 + */ + private int delFlag; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCustomerId() { + return customerId; + } + + public void setCustomerId(Long customerId) { + this.customerId = customerId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getIsRead() { + return isRead; + } + + public void setIsRead(String isRead) { + this.isRead = isRead; + } + + public int getDelFlag() { + return delFlag; + } + + public void setDelFlag(int delFlag) { + this.delFlag = delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("customerId", getCustomerId()) + .append("title", getTitle()) + .append("content", getContent()) + .append("isRead", getIsRead()) + .append("delFlag", getDelFlag()) + .append("createTime", getCreateTime()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSystemSeo.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSystemSeo.java new file mode 100644 index 0000000..36e822a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsSystemSeo.java @@ -0,0 +1,96 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 系统seo设置对象 ls_system_seo + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsSystemSeo extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * seo标题 + */ + @Excel(name = "seo标题") + private String title; + + /** + * seo关键字 + */ + @Excel(name = "seo关键字") + private String keyWord; + + /** + * seo描述 + */ + @Excel(name = "seo描述") + private String seoDesc; + + /** + * 是否开启 0 未开启 1 开启 + */ + @Excel(name = "是否开启 0 未开启 1 开启 ") + private String isOpen; + + 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 getKeyWord() { + return keyWord; + } + + public void setKeyWord(String keyWord) { + this.keyWord = keyWord; + } + + public String getSeoDesc() { + return seoDesc; + } + + public void setSeoDesc(String seoDesc) { + this.seoDesc = seoDesc; + } + + public String getIsOpen() { + return isOpen; + } + + public void setIsOpen(String isOpen) { + this.isOpen = isOpen; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("title", getTitle()) + .append("keyWord", getKeyWord()) + .append("seoDesc", getSeoDesc()) + .append("isOpen", getIsOpen()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsWxCustomerLink.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsWxCustomerLink.java new file mode 100644 index 0000000..6046d70 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/LsWxCustomerLink.java @@ -0,0 +1,96 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 微信登录和商城用户的关联对象 ls_wx_customer_link + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public class LsWxCustomerLink extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 微信的联合登录id + */ + @Excel(name = "微信的联合登录id") + private String wxUnionId; + + /** + * 用户id + */ + @Excel(name = "用户id") + private Long customerId; + + /** + * 微信的openid + */ + @Excel(name = "微信的openid") + private String wxOpenId; + + /** + * 小程序的openid + */ + @Excel(name = "小程序的openid") + private String wxAppletOpenId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getWxUnionId() { + return wxUnionId; + } + + public void setWxUnionId(String wxUnionId) { + this.wxUnionId = wxUnionId; + } + + public Long getCustomerId() { + return customerId; + } + + public void setCustomerId(Long customerId) { + this.customerId = customerId; + } + + public String getWxOpenId() { + return wxOpenId; + } + + public void setWxOpenId(String wxOpenId) { + this.wxOpenId = wxOpenId; + } + + public String getWxAppletOpenId() { + return wxAppletOpenId; + } + + public void setWxAppletOpenId(String wxAppletOpenId) { + this.wxAppletOpenId = wxAppletOpenId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("wxUnionId", getWxUnionId()) + .append("customerId", getCustomerId()) + .append("wxOpenId", getWxOpenId()) + .append("wxAppletOpenId", getWxAppletOpenId()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SCommunityBuySetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SCommunityBuySetting.java new file mode 100644 index 0000000..f132c71 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SCommunityBuySetting.java @@ -0,0 +1,111 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 社区团购设置对象 s_community_buy_setting + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public class SCommunityBuySetting extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * $column.columnComment + */ + private Long id; + + /** + * 团长名称 + */ + @Excel(name = "团长名称") + private String name; + + /** + * 是否开启审核 0 开启 1 关闭 默认0 + */ + @Excel(name = "是否开启审核 0 开启 1 关闭 默认0") + private String audit; + + /** + * 审核结果通知 0 通知 1 不通知 默认0 + */ + @Excel(name = "审核结果通知 0 通知 1 不通知 默认0 ") + private String smsAuditNotice; + + /** + * 打款通知 0 通知 1 不通知默认0 + */ + @Excel(name = "打款通知 0 通知 1 不通知默认0 ") + private String smsPayNotice; + + /** + * 佣金结算通知 0 通知 1 不通知默认0 + */ + @Excel(name = "佣金结算通知 0 通知 1 不通知默认0 ") + private String smsCommissionNotice; + + 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 getAudit() { + return audit; + } + + public void setAudit(String audit) { + this.audit = audit; + } + + public String getSmsAuditNotice() { + return smsAuditNotice; + } + + public void setSmsAuditNotice(String smsAuditNotice) { + this.smsAuditNotice = smsAuditNotice; + } + + public String getSmsPayNotice() { + return smsPayNotice; + } + + public void setSmsPayNotice(String smsPayNotice) { + this.smsPayNotice = smsPayNotice; + } + + public String getSmsCommissionNotice() { + return smsCommissionNotice; + } + + public void setSmsCommissionNotice(String smsCommissionNotice) { + this.smsCommissionNotice = smsCommissionNotice; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("audit", getAudit()) + .append("smsAuditNotice", getSmsAuditNotice()) + .append("smsPayNotice", getSmsPayNotice()) + .append("smsCommissionNotice", getSmsCommissionNotice()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SegchkPaySetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SegchkPaySetting.java new file mode 100644 index 0000000..e086ec0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/domain/SegchkPaySetting.java @@ -0,0 +1,81 @@ +package com.ruoyi.setting.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 支付设置对象 ls_pay_setting + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public class SegchkPaySetting extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 支付方式 1:支付宝 2:微信 3:银联 4:预存款 5:微信APP支付 6:微信小程序支付 + */ + @Excel(name = "支付方式 1:支付宝 2:微信 3:银联 4:预存款 5:微信APP支付 6:微信小程序支付") + private String codetype; + + /** + * 字段名称 + */ + @Excel(name = "字段名称") + private String columnName; + + /** + * 字段值 + */ + @Excel(name = "字段值") + private String columnValue; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCodetype() { + return codetype; + } + + public void setCodetype(String codetype) { + this.codetype = codetype; + } + + public String getColumnName() { + return columnName; + } + + public void setColumnName(String columnName) { + this.columnName = columnName; + } + + public String getColumnValue() { + return columnValue; + } + + public void setColumnValue(String columnValue) { + this.columnValue = columnValue; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("codetype", getCodetype()) + .append("columnName", getColumnName()) + .append("columnValue", getColumnValue()) + .toString(); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/AreaMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/AreaMapper.java new file mode 100644 index 0000000..4827c80 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/AreaMapper.java @@ -0,0 +1,160 @@ +package com.ruoyi.setting.mapper; + + +import com.ruoyi.setting.domain.LsCity; +import com.ruoyi.setting.domain.LsDistrict; +import com.ruoyi.setting.domain.LsProvince; + +import java.util.List; + +/** + * Created by 魔金商城 on 17/5/15. + * 地区数据库接口 + */ +public interface AreaMapper { + + /** + * 查询所有省份 + * + * @return 返回所有省份 + */ + + List queryAllProvinces(); + + /** + * 根据省份id查询该省下面的市 + * + * @param provinceId 省id + * @return 返回省下面的市 + */ + + List queryCityByProvinceId(long provinceId); + + + /** + * 根据市id查询下面的区 + * + * @param cityId 市id + * @return 返回该市下面的区 + */ + + List queryDistrictByCityId(long cityId); + + /** + * 添加省份 + * + * @param province 省份信息 + * @return 成功返回1 失败返回0 + */ + + int addProvince(LsProvince province); + + /** + * 添加市 + * + * @param city 市信息 + * @return 成功返回1 失败返回0 + */ + + int addCity(LsCity city); + + /** + * 添加区 + * + * @param district 区信息 + * @return 成功返回1 失败返回0 + */ + + int addDistrict(LsDistrict district); + + + /** + * 根据省份id删除省份信息 + * + * @param provinceId 省份id + * @return 成功返回1 失败返回0 + */ + + int deleteProvinceById(long provinceId); + + /** + * 根据市id删除市信息 + * + * @param cityId 市id + * @return 成功返回1 失败返回0 + */ + + int deleteCityById(long cityId); + + /** + * 根据区id删除区信息 + * + * @param districtId 区id + * @return 成功返回1 失败返回0 + */ + + int deleteDistrictById(long districtId); + + /** + * 根据省id查询省份信息 + * + * @param id 省id + * @return 返回省份信息 + */ + + LsProvince queryProvinceById(long id); + + /** + * 根据市id查询市信息 + * + * @param id 市id + * @return 返回市信息 + */ + + LsCity queryCityById(long id); + + /** + * 根据区id查询区信息 + * + * @param id 区id + * @return 返回区信息 + */ + + LsDistrict queryDistrictById(long id); + + /** + * 修改省份信息 + * + * @param province 修改省份 + * @return 成功返回1 失败返回0 + */ + + int updateProvince(LsProvince province); + + /** + * 修改市信息 + * + * @param city 市信息 + * @return 成功返回1 失败返回0 + */ + + int updateCity(LsCity city); + + /** + * 修改区信息 + * + * @param district 区信息 + * @return 成功返回1 失败返回0 + */ + + int updateDistrict(LsDistrict district); + + /** + * 根据名称查询市id + * + * @param cityName 市名称 + * @return 市id + */ + + Long queryCityIdByName(String cityName); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/BaseInfoSetMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/BaseInfoSetMapper.java new file mode 100644 index 0000000..ac05963 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/BaseInfoSetMapper.java @@ -0,0 +1,55 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.segchk.domain.BaseInfoSet; + +/** + * 基本信息设置mapper层 + * + * @author 魔金商城 on 2017/5/17. + */ + +public interface BaseInfoSetMapper { + /** + * 查询基本信息设置 + * + * @return 基本信息设置实体类 + */ + + BaseInfoSet queryBaseInfoSet(); + + /** + * 编辑基本信息 + * + * @param baseInfoSet 信息实体类 + * @return 编辑返回码 + */ + + int editBaseInfoSetA(BaseInfoSet baseInfoSet); + + /** + * 编辑高级信息 + * + * @param baseInfoSet 信息实体类 + * @return 编辑返回码 + */ + + int editBaseInfoSetB(BaseInfoSet baseInfoSet); + + /** + * 设置审核开关 + * + * @param storeSpuAudit 店铺商品审核开关 0 需要审核 1 不需要 默认0 + * @return 成功返回1,失败返回0 + */ + + int setAuditSwitch(String storeSpuAudit); + + /** + * 设置审核开关 + * + * @param memberPriceStatus 会员等级启用状态 0 启用 1 不启用 默认0 + * @return 成功返回1,失败返回0 + */ + + int setMemberPriceStatus(String memberPriceStatus); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsCityMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsCityMapper.java new file mode 100644 index 0000000..b501955 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsCityMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsCity; + +import java.util.List; + +/** + * 区域市Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsCityMapper { + /** + * 查询区域市 + * + * @param id 区域市ID + * @return 区域市 + */ + public LsCity selectLsCityById(Long id); + + /** + * 查询区域市列表 + * + * @param lsCity 区域市 + * @return 区域市集合 + */ + public List selectLsCityList(LsCity lsCity); + + /** + * 新增区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + public int insertLsCity(LsCity lsCity); + + /** + * 修改区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + public int updateLsCity(LsCity lsCity); + + /** + * 删除区域市 + * + * @param id 区域市ID + * @return 结果 + */ + public int deleteLsCityById(Long id); + + /** + * 批量删除区域市 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsCityByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsDistrictMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsDistrictMapper.java new file mode 100644 index 0000000..47d9c14 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsDistrictMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsDistrict; + +import java.util.List; + +/** + * 区域区Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsDistrictMapper { + /** + * 查询区域区 + * + * @param id 区域区ID + * @return 区域区 + */ + public LsDistrict selectLsDistrictById(Long id); + + /** + * 查询区域区列表 + * + * @param lsDistrict 区域区 + * @return 区域区集合 + */ + public List selectLsDistrictList(LsDistrict lsDistrict); + + /** + * 新增区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + public int insertLsDistrict(LsDistrict lsDistrict); + + /** + * 修改区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + public int updateLsDistrict(LsDistrict lsDistrict); + + /** + * 删除区域区 + * + * @param id 区域区ID + * @return 结果 + */ + public int deleteLsDistrictById(Long id); + + /** + * 批量删除区域区 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsDistrictByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsEmailSettingMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsEmailSettingMapper.java new file mode 100644 index 0000000..582c4d0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsEmailSettingMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsEmailSetting; + +import java.util.List; + +/** + * 邮箱设置Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface LsEmailSettingMapper { + /** + * 查询邮箱设置 + * + * @param id 邮箱设置ID + * @return 邮箱设置 + */ + public LsEmailSetting selectLsEmailSettingById(Long id); + + /** + * 查询邮箱设置列表 + * + * @param lsEmailSetting 邮箱设置 + * @return 邮箱设置集合 + */ + public List selectLsEmailSettingList(LsEmailSetting lsEmailSetting); + + /** + * 新增邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + public int insertLsEmailSetting(LsEmailSetting lsEmailSetting); + + /** + * 修改邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + public int updateLsEmailSetting(LsEmailSetting lsEmailSetting); + + /** + * 删除邮箱设置 + * + * @param id 邮箱设置ID + * @return 结果 + */ + public int deleteLsEmailSettingById(Long id); + + /** + * 批量删除邮箱设置 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsEmailSettingByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsProvinceMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsProvinceMapper.java new file mode 100644 index 0000000..8dba4d3 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsProvinceMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsProvince; + +import java.util.List; + +/** + * 区域省Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsProvinceMapper { + /** + * 查询区域省 + * + * @param id 区域省ID + * @return 区域省 + */ + public LsProvince selectLsProvinceById(Long id); + + /** + * 查询区域省列表 + * + * @param lsProvince 区域省 + * @return 区域省集合 + */ + public List selectLsProvinceList(LsProvince lsProvince); + + /** + * 新增区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + public int insertLsProvince(LsProvince lsProvince); + + /** + * 修改区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + public int updateLsProvince(LsProvince lsProvince); + + /** + * 删除区域省 + * + * @param id 区域省ID + * @return 结果 + */ + public int deleteLsProvinceById(Long id); + + /** + * 批量删除区域省 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsProvinceByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSmsSettingMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSmsSettingMapper.java new file mode 100644 index 0000000..346d114 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSmsSettingMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsSmsSetting; + +import java.util.List; + +/** + * 短信接口设置Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface LsSmsSettingMapper { + /** + * 查询短信接口设置 + * + * @param id 短信接口设置ID + * @return 短信接口设置 + */ + public LsSmsSetting selectLsSmsSettingById(Long id); + + /** + * 查询短信接口设置列表 + * + * @param lsSmsSetting 短信接口设置 + * @return 短信接口设置集合 + */ + public List selectLsSmsSettingList(LsSmsSetting lsSmsSetting); + + /** + * 新增短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + public int insertLsSmsSetting(LsSmsSetting lsSmsSetting); + + /** + * 修改短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + public int updateLsSmsSetting(LsSmsSetting lsSmsSetting); + + /** + * 删除短信接口设置 + * + * @param id 短信接口设置ID + * @return 结果 + */ + public int deleteLsSmsSettingById(Long id); + + /** + * 批量删除短信接口设置 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsSmsSettingByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsStationLetterMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsStationLetterMapper.java new file mode 100644 index 0000000..c55e93f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsStationLetterMapper.java @@ -0,0 +1,116 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsStationLetter; + +import java.util.List; +import java.util.Map; + +/** + * 站内信Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsStationLetterMapper { + /** + * 新增站内信 + * + * @param stationLetters 站内信 + * @return 成功返回>1 失败返回0 + */ + + int addStationLetters(List stationLetters); + + /** + * 删除站内信 + * + * @param id 站内信id + * @return 成功返回1,失败返回0 + */ + + int deleteStationLetters(long id); + + /** + * 根据会员id查询会员的站内信 + * + * @param params 查询参数 + * @return 返回会员的站内信 + */ + + List queryStationLettersByCustomerId(Map params); + + /** + * 查询会员的站内信总纪录数 + * + * @param params 查询参数 + * @return 返回会员的站内信总记录数 + */ + + int queryStationLettersCountByCustomerId(Map params); + + /** + * 更新会员的站内信的阅读状态 + * + * @param params 参数 + * @return 成功返回1,失败返回0 + */ + + int updateStationLettersIsRead(Map params); + + /** + * 获得用户未读消息的数量 + * + * @param customerId 用户id + * @return 返回用户未读消息的数量 + */ + + int unReadNum(long customerId); + + /** + * 查询站内信 + * + * @param id 站内信ID + * @return 站内信 + */ + public LsStationLetter selectLsStationLetterById(Long id); + + /** + * 查询站内信列表 + * + * @param lsStationLetter 站内信 + * @return 站内信集合 + */ + public List selectLsStationLetterList(LsStationLetter lsStationLetter); + + /** + * 新增站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + public int insertLsStationLetter(LsStationLetter lsStationLetter); + + /** + * 修改站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + public int updateLsStationLetter(LsStationLetter lsStationLetter); + + /** + * 删除站内信 + * + * @param id 站内信ID + * @return 结果 + */ + public int deleteLsStationLetterById(Long id); + + /** + * 批量删除站内信 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsStationLetterByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSystemSeoMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSystemSeoMapper.java new file mode 100644 index 0000000..dabdaa7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsSystemSeoMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsSystemSeo; + +import java.util.List; + +/** + * 系统seo设置Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsSystemSeoMapper { + /** + * 查询系统seo设置 + * + * @param id 系统seo设置ID + * @return 系统seo设置 + */ + public LsSystemSeo selectLsSystemSeoById(Long id); + + /** + * 查询系统seo设置列表 + * + * @param lsSystemSeo 系统seo设置 + * @return 系统seo设置集合 + */ + public List selectLsSystemSeoList(LsSystemSeo lsSystemSeo); + + /** + * 新增系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + public int insertLsSystemSeo(LsSystemSeo lsSystemSeo); + + /** + * 修改系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + public int updateLsSystemSeo(LsSystemSeo lsSystemSeo); + + /** + * 删除系统seo设置 + * + * @param id 系统seo设置ID + * @return 结果 + */ + public int deleteLsSystemSeoById(Long id); + + /** + * 批量删除系统seo设置 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsSystemSeoByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsWxCustomerLinkMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsWxCustomerLinkMapper.java new file mode 100644 index 0000000..82c3ccc --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/LsWxCustomerLinkMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.LsWxCustomerLink; + +import java.util.List; + +/** + * 微信登录和商城用户的关联Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface LsWxCustomerLinkMapper { + /** + * 查询微信登录和商城用户的关联 + * + * @param id 微信登录和商城用户的关联ID + * @return 微信登录和商城用户的关联 + */ + public LsWxCustomerLink selectLsWxCustomerLinkById(Long id); + + /** + * 查询微信登录和商城用户的关联列表 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 微信登录和商城用户的关联集合 + */ + public List selectLsWxCustomerLinkList(LsWxCustomerLink lsWxCustomerLink); + + /** + * 新增微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + public int insertLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink); + + /** + * 修改微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + public int updateLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink); + + /** + * 删除微信登录和商城用户的关联 + * + * @param id 微信登录和商城用户的关联ID + * @return 结果 + */ + public int deleteLsWxCustomerLinkById(Long id); + + /** + * 批量删除微信登录和商城用户的关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsWxCustomerLinkByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/OssMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/OssMapper.java new file mode 100644 index 0000000..ff793d1 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/OssMapper.java @@ -0,0 +1,30 @@ +package com.ruoyi.setting.mapper; + + +import com.ruoyi.setting.bean.OssSetting; +import org.springframework.stereotype.Repository; + +/** + * Created by luozhuo on 2020/7/7 + * 云存储设置数据库接口 + */ +@Repository +public interface OssMapper { + + /** + * 查询系统设置的云存储信息 + * + * @return 返回云存储信息 + */ + + OssSetting queryOssSetting(); + + /** + * 修改又拍云信息 + * + * @param ossSetting 云存储信息 + * @return 成功返回1 失败返回0 + */ + + int updateOss(OssSetting ossSetting); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SCommunityBuySettingMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SCommunityBuySettingMapper.java new file mode 100644 index 0000000..f401ad4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SCommunityBuySettingMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.domain.SCommunityBuySetting; + +import java.util.List; + +/** + * 社区团购设置Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface SCommunityBuySettingMapper { + /** + * 查询社区团购设置 + * + * @param id 社区团购设置ID + * @return 社区团购设置 + */ + public SCommunityBuySetting selectSCommunityBuySettingById(Long id); + + /** + * 查询社区团购设置列表 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 社区团购设置集合 + */ + public List selectSCommunityBuySettingList(SCommunityBuySetting sCommunityBuySetting); + + /** + * 新增社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + public int insertSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting); + + /** + * 修改社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + public int updateSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting); + + /** + * 删除社区团购设置 + * + * @param id 社区团购设置ID + * @return 结果 + */ + public int deleteSCommunityBuySettingById(Long id); + + /** + * 批量删除社区团购设置 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteSCommunityBuySettingByIds(Long[] ids); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SegchkPaySettingMapper.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SegchkPaySettingMapper.java new file mode 100644 index 0000000..dbbc923 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/mapper/SegchkPaySettingMapper.java @@ -0,0 +1,82 @@ +package com.ruoyi.setting.mapper; + +import com.ruoyi.setting.bean.PaySet; +import com.ruoyi.setting.domain.SegchkPaySetting; + +import java.util.List; + +/** + * 支付设置Mapper接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface SegchkPaySettingMapper { + /** + * 查询支付设置 + * + * @param id 支付设置ID + * @return 支付设置 + */ + public SegchkPaySetting selectLsPaySettingById(Long id); + + /** + * 查询支付设置列表 + * + * @param segchkPaySetting 支付设置 + * @return 支付设置集合 + */ + public List selectLsPaySettingList(SegchkPaySetting segchkPaySetting); + + /** + * 新增支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + public int insertLsPaySetting(SegchkPaySetting segchkPaySetting); + + /** + * 修改支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + public int updateLsPaySetting(SegchkPaySetting segchkPaySetting); + + /** + * 删除支付设置 + * + * @param id 支付设置ID + * @return 结果 + */ + public int deleteLsPaySettingById(Long id); + + /** + * 批量删除支付设置 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteLsPaySettingByIds(Long[] ids); + + List queryPaySet(); + + /** + * 根据codeType删除支付接口设置 + * + * @param codeType 1支付宝 2微信 3银联 + * @return 返回删除行数 + */ + + int deletePaySet(String codeType); + + /** + * 批量插入支付接口设置 + * + * @param list PaySet集合 + * @return 返回插入行数 + */ + + int addPaySet(List list); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/AreaService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/AreaService.java new file mode 100644 index 0000000..f8b9fca --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/AreaService.java @@ -0,0 +1,155 @@ +package com.ruoyi.setting.service; + + +import com.ruoyi.setting.domain.LsCity; +import com.ruoyi.setting.domain.LsDistrict; +import com.ruoyi.setting.domain.LsProvince; +import com.ruoyi.setting.vo.AreaItem; +import com.ruoyi.setting.vo.Locality; + +import java.util.List; + +/** + * Created by 魔金商城 on 17/5/15. + * 地区服务接口 + */ +public interface AreaService { + + /** + * 查询所有省份 + * + * @param areaItems 查询参数 不带只查询省 + * @return 返回所有省份 + */ + List queryAllProvinces(AreaItem... areaItems); + + + /** + * 查询所有地区信息(特殊数据接口) + * + * @return 所有地区信息 + */ + List queryAllLocality(); + + + /** + * 根据省份id查询下面的市 + * + * @param provinceId 省份id + * @return 返回该省下面的市 + */ + List queryCityByProvinceId(long provinceId); + + /** + * 根据市id查询下面的区县 + * + * @param cityId 市id + * @return 返回市下面的区县 + */ + List queryDistrictByCityId(long cityId); + + /** + * 添加省份 + * + * @param province 省份信息 + * @return 成功返回1 失败返回0 + */ + int addProvince(LsProvince province); + + /** + * 添加市 + * + * @param city 市 + * @return 成返回1 失败返回0 + */ + int addCity(LsCity city); + + /** + * 添加区 + * + * @param district 区信息 + * @return 成功返回1 失败返回0 + */ + int addDistrict(LsDistrict district); + + + /** + * 根据省份id删除省信息 + * + * @param provinceId 省份id + * @return 1 成功 0 失败 -1 下面有市不能删除 + */ + int deleteProvinceById(long provinceId); + + /** + * 根据市id删除市信息 + * + * @param cityId 市id + * @return 返回 1 成功 0 失败 -1 下面有区 不能删除 + */ + int deleteCityById(long cityId); + + /** + * 根据区id删除区 + * + * @param districtId 区id + * @return 返回 1 成功 0 失败 + */ + int deleteDistrictById(long districtId); + + /** + * 根据省份id查询省份信息 + * + * @param id 省份id + * @return 返回省份信息 + */ + LsProvince queryProvinceById(long id); + + /** + * 根据市id查询市信息 + * + * @param id 市id + * @return 返回市信息 + */ + LsCity queryCityById(long id); + + /** + * 根据区id查询区信息 + * + * @param id 区id + * @return 返回区信息 + */ + LsDistrict queryDistrictById(long id); + + /** + * 修改省份 + * + * @param province 省份信息 + * @return 成功返回1 失败返回0 + */ + int updateProvince(LsProvince province); + + /** + * 修改市 + * + * @param city 市信息 + * @return 成功返回1 失败返回0 + */ + int updateCity(LsCity city); + + /** + * 修改区 + * + * @param district 区信息 + * @return 成功返回1 失败返回0 + */ + int updateDistrict(LsDistrict district); + + /** + * 根据市名称查找市id + * + * @param cityName 市名称 + * @return 市id + */ + long queryCityIdByName(String cityName); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/BaseInfoSetService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/BaseInfoSetService.java new file mode 100644 index 0000000..3f079c5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/BaseInfoSetService.java @@ -0,0 +1,49 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.segchk.domain.BaseInfoSet; + +/** + * 基本信息设置service层 + * + * @author 魔金商城 on 2017/5/17. + */ +public interface BaseInfoSetService { + /** + * 查询基本信息和高级信息设置 + * + * @return 基本信息设置实体类 + */ + BaseInfoSet queryBaseInfoSet(); + + /** + * 编辑基本信息和高级信息 + * + * @param baseInfoSet 基本信息实体类 + * @param type 1 基本信息 0高级信息 + * @return -1编辑失败 1编辑成功 0编辑失败 + */ + int editBaseInfoSet(BaseInfoSet baseInfoSet, int type); + + /** + * 设置审核开关 + * + * @param storeSpuAudit 店铺商品审核开关 0 需要审核 1 不需要 默认0 + * @return 成功返回1,失败返回0 + */ + int setAuditSwitch(String storeSpuAudit); + + /** + * 设置会员价启用状态 + * + * @param memberPriceStatus 会员等级启用状态 0 启用 1 不启用 默认0 + * @return 成功返回1,失败返回0 + */ + int setMemberPriceStatus(String memberPriceStatus); + + /** + * 判断单品是否需要审核 + * + * @return 需要审核返回true 不需要返回false + */ + boolean isSkuNeedAudit(); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsCityService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsCityService.java new file mode 100644 index 0000000..72e28cb --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsCityService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsCity; + +import java.util.List; + +/** + * 区域市Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsCityService { + /** + * 查询区域市 + * + * @param id 区域市ID + * @return 区域市 + */ + public LsCity selectLsCityById(Long id); + + /** + * 查询区域市列表 + * + * @param lsCity 区域市 + * @return 区域市集合 + */ + public List selectLsCityList(LsCity lsCity); + + /** + * 新增区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + public int insertLsCity(LsCity lsCity); + + /** + * 修改区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + public int updateLsCity(LsCity lsCity); + + /** + * 批量删除区域市 + * + * @param ids 需要删除的区域市ID + * @return 结果 + */ + public int deleteLsCityByIds(Long[] ids); + + /** + * 删除区域市信息 + * + * @param id 区域市ID + * @return 结果 + */ + public int deleteLsCityById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsDistrictService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsDistrictService.java new file mode 100644 index 0000000..f1d9db9 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsDistrictService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsDistrict; + +import java.util.List; + +/** + * 区域区Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsDistrictService { + /** + * 查询区域区 + * + * @param id 区域区ID + * @return 区域区 + */ + public LsDistrict selectLsDistrictById(Long id); + + /** + * 查询区域区列表 + * + * @param lsDistrict 区域区 + * @return 区域区集合 + */ + public List selectLsDistrictList(LsDistrict lsDistrict); + + /** + * 新增区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + public int insertLsDistrict(LsDistrict lsDistrict); + + /** + * 修改区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + public int updateLsDistrict(LsDistrict lsDistrict); + + /** + * 批量删除区域区 + * + * @param ids 需要删除的区域区ID + * @return 结果 + */ + public int deleteLsDistrictByIds(Long[] ids); + + /** + * 删除区域区信息 + * + * @param id 区域区ID + * @return 结果 + */ + public int deleteLsDistrictById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsEmailSettingService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsEmailSettingService.java new file mode 100644 index 0000000..a851365 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsEmailSettingService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsEmailSetting; + +import java.util.List; + +/** + * 邮箱设置Service接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface ILsEmailSettingService { + /** + * 查询邮箱设置 + * + * @param id 邮箱设置ID + * @return 邮箱设置 + */ + public LsEmailSetting selectLsEmailSettingById(Long id); + + /** + * 查询邮箱设置列表 + * + * @param lsEmailSetting 邮箱设置 + * @return 邮箱设置集合 + */ + public List selectLsEmailSettingList(LsEmailSetting lsEmailSetting); + + /** + * 新增邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + public int insertLsEmailSetting(LsEmailSetting lsEmailSetting); + + /** + * 修改邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + public int updateLsEmailSetting(LsEmailSetting lsEmailSetting); + + /** + * 批量删除邮箱设置 + * + * @param ids 需要删除的邮箱设置ID + * @return 结果 + */ + public int deleteLsEmailSettingByIds(Long[] ids); + + /** + * 删除邮箱设置信息 + * + * @param id 邮箱设置ID + * @return 结果 + */ + public int deleteLsEmailSettingById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsPaySettingService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsPaySettingService.java new file mode 100644 index 0000000..349e9ca --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsPaySettingService.java @@ -0,0 +1,76 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.bean.PaySetCommon; +import com.ruoyi.setting.domain.SegchkPaySetting; + +import java.util.List; + +/** + * 支付设置Service接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface ILsPaySettingService { + /** + * 查询所有支付接口设置 + * + * @return 返回PaySetCommon + */ + PaySetCommon queryPaySet(); + + /** + * 编辑支付接口设置 + * + * @return -1编辑出错 1成功 + */ + int editPaySet(PaySetCommon paySetCommon, String codeType); + + /** + * 查询支付设置 + * + * @param id 支付设置ID + * @return 支付设置 + */ + public SegchkPaySetting selectLsPaySettingById(Long id); + + /** + * 查询支付设置列表 + * + * @param segchkPaySetting 支付设置 + * @return 支付设置集合 + */ + public List selectLsPaySettingList(SegchkPaySetting segchkPaySetting); + + /** + * 新增支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + public int insertLsPaySetting(SegchkPaySetting segchkPaySetting); + + /** + * 修改支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + public int updateLsPaySetting(SegchkPaySetting segchkPaySetting); + + /** + * 批量删除支付设置 + * + * @param ids 需要删除的支付设置ID + * @return 结果 + */ + public int deleteLsPaySettingByIds(Long[] ids); + + /** + * 删除支付设置信息 + * + * @param id 支付设置ID + * @return 结果 + */ + public int deleteLsPaySettingById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsProvinceService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsProvinceService.java new file mode 100644 index 0000000..bf6b104 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsProvinceService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsProvince; + +import java.util.List; + +/** + * 区域省Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsProvinceService { + /** + * 查询区域省 + * + * @param id 区域省ID + * @return 区域省 + */ + public LsProvince selectLsProvinceById(Long id); + + /** + * 查询区域省列表 + * + * @param lsProvince 区域省 + * @return 区域省集合 + */ + public List selectLsProvinceList(LsProvince lsProvince); + + /** + * 新增区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + public int insertLsProvince(LsProvince lsProvince); + + /** + * 修改区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + public int updateLsProvince(LsProvince lsProvince); + + /** + * 批量删除区域省 + * + * @param ids 需要删除的区域省ID + * @return 结果 + */ + public int deleteLsProvinceByIds(Long[] ids); + + /** + * 删除区域省信息 + * + * @param id 区域省ID + * @return 结果 + */ + public int deleteLsProvinceById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSmsSettingService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSmsSettingService.java new file mode 100644 index 0000000..ea1ccb7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSmsSettingService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsSmsSetting; + +import java.util.List; + +/** + * 短信接口设置Service接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface ILsSmsSettingService { + /** + * 查询短信接口设置 + * + * @param id 短信接口设置ID + * @return 短信接口设置 + */ + public LsSmsSetting selectLsSmsSettingById(Long id); + + /** + * 查询短信接口设置列表 + * + * @param lsSmsSetting 短信接口设置 + * @return 短信接口设置集合 + */ + public List selectLsSmsSettingList(LsSmsSetting lsSmsSetting); + + /** + * 新增短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + public int insertLsSmsSetting(LsSmsSetting lsSmsSetting); + + /** + * 修改短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + public int updateLsSmsSetting(LsSmsSetting lsSmsSetting); + + /** + * 批量删除短信接口设置 + * + * @param ids 需要删除的短信接口设置ID + * @return 结果 + */ + public int deleteLsSmsSettingByIds(Long[] ids); + + /** + * 删除短信接口设置信息 + * + * @param id 短信接口设置ID + * @return 结果 + */ + public int deleteLsSmsSettingById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsStationLetterService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsStationLetterService.java new file mode 100644 index 0000000..c352bfa --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsStationLetterService.java @@ -0,0 +1,105 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsStationLetter; +import com.ruoyi.util.PageHelper; + +import java.util.List; + +/** + * 站内信Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsStationLetterService { + /** + * 查询站内信 + * + * @param id 站内信ID + * @return 站内信 + */ + public LsStationLetter selectLsStationLetterById(Long id); + + /** + * 查询站内信列表 + * + * @param lsStationLetter 站内信 + * @return 站内信集合 + */ + public List selectLsStationLetterList(LsStationLetter lsStationLetter); + + /** + * 新增站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + public int insertLsStationLetter(LsStationLetter lsStationLetter); + + /** + * 修改站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + public int updateLsStationLetter(LsStationLetter lsStationLetter); + + /** + * 批量删除站内信 + * + * @param ids 需要删除的站内信ID + * @return 结果 + */ + public int deleteLsStationLetterByIds(Long[] ids); + + /** + * 删除站内信信息 + * + * @param id 站内信ID + * @return 结果 + */ + public int deleteLsStationLetterById(Long id); + + /** + * 新增站内信 + * + * @param stationLetters 站内信集合 + * @return 成功返回>1 失败返回0 + */ + int addStationLetters(List stationLetters); + + /** + * 删除站内信 + * + * @param id 站内信id + * @return 成功返回1,失败返回0 + */ + int deleteStationLetters(long id); + + /** + * 根据会员di查询会员的站内信 + * + * @param pageHelper 分页帮助类 + * @param customerId 会员id + * @return 返回会员的站内信 + */ + PageHelper queryStationLettersByCustomerId(PageHelper pageHelper, long customerId); + + /** + * 更新会员的站内信的阅读状态 + * + * @param id 站内信id + * @param customerId 用户id + * @return 成功返回1,失败返回0 + */ + int updateStationLettersIsRead(long id, long customerId); + + /** + * 获得用户未读的消息数量 + * + * @param customerId 会员id + * @return 返回用户未读消息的数量 + */ + int unReadNum(long customerId); + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSystemSeoService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSystemSeoService.java new file mode 100644 index 0000000..75851c1 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsSystemSeoService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsSystemSeo; + +import java.util.List; + +/** + * 系统seo设置Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsSystemSeoService { + /** + * 查询系统seo设置 + * + * @param id 系统seo设置ID + * @return 系统seo设置 + */ + public LsSystemSeo selectLsSystemSeoById(Long id); + + /** + * 查询系统seo设置列表 + * + * @param lsSystemSeo 系统seo设置 + * @return 系统seo设置集合 + */ + public List selectLsSystemSeoList(LsSystemSeo lsSystemSeo); + + /** + * 新增系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + public int insertLsSystemSeo(LsSystemSeo lsSystemSeo); + + /** + * 修改系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + public int updateLsSystemSeo(LsSystemSeo lsSystemSeo); + + /** + * 批量删除系统seo设置 + * + * @param ids 需要删除的系统seo设置ID + * @return 结果 + */ + public int deleteLsSystemSeoByIds(Long[] ids); + + /** + * 删除系统seo设置信息 + * + * @param id 系统seo设置ID + * @return 结果 + */ + public int deleteLsSystemSeoById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsWxCustomerLinkService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsWxCustomerLinkService.java new file mode 100644 index 0000000..b2d328a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ILsWxCustomerLinkService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.LsWxCustomerLink; + +import java.util.List; + +/** + * 微信登录和商城用户的关联Service接口 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +public interface ILsWxCustomerLinkService { + /** + * 查询微信登录和商城用户的关联 + * + * @param id 微信登录和商城用户的关联ID + * @return 微信登录和商城用户的关联 + */ + public LsWxCustomerLink selectLsWxCustomerLinkById(Long id); + + /** + * 查询微信登录和商城用户的关联列表 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 微信登录和商城用户的关联集合 + */ + public List selectLsWxCustomerLinkList(LsWxCustomerLink lsWxCustomerLink); + + /** + * 新增微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + public int insertLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink); + + /** + * 修改微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + public int updateLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink); + + /** + * 批量删除微信登录和商城用户的关联 + * + * @param ids 需要删除的微信登录和商城用户的关联ID + * @return 结果 + */ + public int deleteLsWxCustomerLinkByIds(Long[] ids); + + /** + * 删除微信登录和商城用户的关联信息 + * + * @param id 微信登录和商城用户的关联ID + * @return 结果 + */ + public int deleteLsWxCustomerLinkById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ISCommunityBuySettingService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ISCommunityBuySettingService.java new file mode 100644 index 0000000..c620b1a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/ISCommunityBuySettingService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + +import com.ruoyi.setting.domain.SCommunityBuySetting; + +import java.util.List; + +/** + * 社区团购设置Service接口 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +public interface ISCommunityBuySettingService { + /** + * 查询社区团购设置 + * + * @param id 社区团购设置ID + * @return 社区团购设置 + */ + public SCommunityBuySetting selectSCommunityBuySettingById(Long id); + + /** + * 查询社区团购设置列表 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 社区团购设置集合 + */ + public List selectSCommunityBuySettingList(SCommunityBuySetting sCommunityBuySetting); + + /** + * 新增社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + public int insertSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting); + + /** + * 修改社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + public int updateSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting); + + /** + * 批量删除社区团购设置 + * + * @param ids 需要删除的社区团购设置ID + * @return 结果 + */ + public int deleteSCommunityBuySettingByIds(Long[] ids); + + /** + * 删除社区团购设置信息 + * + * @param id 社区团购设置ID + * @return 结果 + */ + public int deleteSCommunityBuySettingById(Long id); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/OssService.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/OssService.java new file mode 100644 index 0000000..f59a877 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/OssService.java @@ -0,0 +1,61 @@ +package com.ruoyi.setting.service; + + +import com.ruoyi.setting.bean.OssSetting; +import com.ruoyi.setting.bean.UploadData; + +import java.util.List; + +/** + * Created by luozhuo on 2020/7/7. + * 云存储服务接口 + */ +public interface OssService { + + /** + * 上传到云存储 + * + * @param uploadDatas 上传的参数 + * @return 返回图片在云存储的地址 + */ + List uploadToQqOss(List uploadDatas); + + /** + * 上传到腾讯云存储(上传base64图片) + * + * @param uploadDatas 上传的参数 + * @return 返回图片在云存储的地址 + */ + List uploadToQqOssForBase64(List uploadDatas); + + /** + * 上传到腾讯云存储 + * + * @param uploadDatas 上传的参数 + * @return 返回图片在云存储的地址 + */ + List uploadToOss(List uploadDatas); + + /** + * 上传到云存储(上传base64图片) + * + * @param uploadDatas 上传的参数 + * @return 返回图片在云存储的地址 + */ + List uploadToOssForBase64(List uploadDatas); + + /** + * 查询系统设置的云存储信息 + * + * @return 返回云存储信息 + */ + OssSetting queryOssSetting(); + + /** + * 修改云存储设置信息 + * + * @param OssSetting 云存储设置实体 + * @return 成功返回1 失败返回0 + */ + int updateOss(OssSetting OssSetting); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/AreaServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/AreaServiceImpl.java new file mode 100644 index 0000000..d1905be --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/AreaServiceImpl.java @@ -0,0 +1,270 @@ +package com.ruoyi.setting.service.impl; + + +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.setting.domain.LsCity; +import com.ruoyi.setting.domain.LsDistrict; +import com.ruoyi.setting.domain.LsProvince; +import com.ruoyi.setting.mapper.AreaMapper; +import com.ruoyi.setting.service.AreaService; +import com.ruoyi.setting.vo.AreaItem; +import com.ruoyi.setting.vo.Locality; +import com.ruoyi.common.utils.RedisCahceKey; +import org.apache.commons.lang.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Created by 魔金商城 on 17/5/15 + * 地区服务实现接口 + */ +@Service +public class AreaServiceImpl implements AreaService { + + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(AreaServiceImpl.class); + + /** + * 地区数据库接口 + */ + @Autowired + private AreaMapper areaMapper; + + @Cacheable(value = RedisCahceKey.AREA, key = "'AREA'+#areaItems.hashCode()") + @Override + public List queryAllProvinces(AreaItem... areaItems) { + logger.debug("queryAllProvinces.....areaItems:{}", areaItems); + + List provinces = areaMapper.queryAllProvinces(); + + // 如果没有省则直接返回 + if (CollectionUtils.isEmpty(provinces)) { + return provinces; + } + + // 设置省下面的市 + if (ArrayUtils.contains(areaItems, AreaItem.CITY)) { + provinces.parallelStream().forEach(province -> province.setChild(this.queryCityByProvinceId(province.getId()))); + } + + // 设置市下面的区 + if (ArrayUtils.contains(areaItems, AreaItem.DISTRICT)) { + provinces.parallelStream().forEach(province -> province.getChild().stream().forEach(city -> city.setChild(this.queryDistrictByCityId(city.getId())))); + } + + // 查询所有省市区 + if (ArrayUtils.contains(areaItems, AreaItem.ALL)) { + provinces.parallelStream().forEach(province -> province.setChild(this.queryCityByProvinceId(province.getId()))); + provinces.parallelStream().forEach(province -> province.getChild().stream().forEach(city -> city.setChild(this.queryDistrictByCityId(city.getId())))); + } + + return provinces; + } + + + /** + * 查询所有地区信息(特殊数据接口) + * + * @return 所有地区信息 + */ + @Override + public List queryAllLocality() { + logger.debug("queryAllLocality...."); + + List provinceList = SpringUtils.getBean(AreaService.class).queryAllProvinces(AreaItem.ALL); + + //初始化返回集合 + List localities = new ArrayList<>(); + + //构建数据结构 + for (int i = 0, size = provinceList.size(); i < size; i++) { + //省份 + localities.add(new Locality(provinceList.get(i).getName(), "P-" + provinceList.get(i).getId(), "0", provinceList.get(i).getId())); + for (int k = 0; k < provinceList.get(i).getChild().size(); k++) { + //城市 + localities.add(new Locality(provinceList.get(i).getChild().get(k).getName(), "C-" + provinceList.get(i).getChild().get(k).getId(), "P-" + provinceList.get(i).getChild().get(k).getProvinceId(), provinceList.get(i).getChild().get(k).getId())); + for (int j = 0; j < provinceList.get(i).getChild().get(k).getChild().size(); j++) { + //地区 + localities.add(new Locality(provinceList.get(i).getChild().get(k).getChild().get(j).getName(), "D-" + provinceList.get(i).getChild().get(k).getChild().get(j).getId(), "C-" + provinceList.get(i).getChild().get(k).getId(), provinceList.get(i).getChild().get(k).getChild().get(j).getId())); + } + } + } + + return localities; + + } + + + @Override + public List queryCityByProvinceId(long provinceId) { + logger.debug("queryCityByProvinceId and provinceId:{}", provinceId); + return areaMapper.queryCityByProvinceId(provinceId); + } + + @Override + public List queryDistrictByCityId(long cityId) { + logger.debug("queryDistrictByCityId and cityId:{}", cityId); + return areaMapper.queryDistrictByCityId(cityId); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int addProvince(LsProvince province) { + logger.debug("addProvince and province:{}", province); + + if (Objects.isNull(province)) { + logger.error("addProvince fail due to province is null...."); + return 0; + } + return areaMapper.addProvince(province); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int addCity(LsCity city) { + logger.debug("addCity and city :{}", city); + if (Objects.isNull(city)) { + logger.error("addCity fail due to city is null...."); + return 0; + } + return areaMapper.addCity(city); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int addDistrict(LsDistrict district) { + + logger.debug("addDistrict and district:{}", district); + + if (Objects.isNull(district)) { + logger.error("addDistrict fail due to district is null..."); + return 0; + } + return areaMapper.addDistrict(district); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int deleteProvinceById(long provinceId) { + logger.debug("deleteProvinceById and provinceId:{}", provinceId); + + if (!isProvinceCanDelete(provinceId)) { + logger.error("deleteProvinceById fail due to province has city..."); + return -1; + } + + return areaMapper.deleteProvinceById(provinceId); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int deleteCityById(long cityId) { + logger.debug("deleteCityById and cityId:{}", cityId); + + if (!isCityCanDelete(cityId)) { + logger.error("deleteCityById fail due to city has district"); + return -1; + } + return areaMapper.deleteCityById(cityId); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int deleteDistrictById(long districtId) { + logger.debug("deleteDistrictById and districtId:{}", districtId); + return areaMapper.deleteDistrictById(districtId); + } + + + @Override + public LsProvince queryProvinceById(long id) { + logger.debug("queryProvinceById and id:{}", id); + return areaMapper.queryProvinceById(id); + } + + @Override + public LsCity queryCityById(long id) { + logger.debug("queryCityById and id:{}", id); + return areaMapper.queryCityById(id); + } + + @Override + public LsDistrict queryDistrictById(long id) { + logger.debug("queryDistrictById and id :{}", id); + return areaMapper.queryDistrictById(id); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int updateProvince(LsProvince province) { + logger.debug("updateProvince and province:{}", province); + if (Objects.isNull(province)) { + logger.error("updateProvince fail ..."); + return 0; + } + return areaMapper.updateProvince(province); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int updateCity(LsCity city) { + logger.debug("updateCity and city:{}", city); + + if (Objects.isNull(city)) { + logger.error("updateCity fail..."); + return 0; + } + return areaMapper.updateCity(city); + } + + @CacheEvict(value = RedisCahceKey.AREA, allEntries = true) + @Override + public int updateDistrict(LsDistrict district) { + logger.debug("updateDistrict and district:{}", district); + + if (Objects.isNull(district)) { + logger.error("updateDistrict fail...."); + return 0; + } + return areaMapper.updateDistrict(district); + } + + @Override + public long queryCityIdByName(String cityName) { + logger.debug("queryCityIdByName and cityName:{}", cityName); + Long cityId = areaMapper.queryCityIdByName(cityName); + return Objects.isNull(cityId) ? -1 : cityId; + } + + + /** + * 判断市是否可以删除 + * + * @param cityId 市id + * @return 可以返回true 不可以返回false 市下面有区则不能删除 + */ + private boolean isCityCanDelete(long cityId) { + return CollectionUtils.isEmpty(this.queryDistrictByCityId(cityId)); + } + + /** + * 判断省份是否可以删除 + * + * @param provinceId 省份id + * @return 可以删除 返回true 不可以删除 返回false (省份下面有市则不能删除) + */ + private boolean isProvinceCanDelete(long provinceId) { + return CollectionUtils.isEmpty(this.queryCityByProvinceId(provinceId)); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/BaseInfoSetServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/BaseInfoSetServiceImpl.java new file mode 100644 index 0000000..4c4672c --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/BaseInfoSetServiceImpl.java @@ -0,0 +1,117 @@ +package com.ruoyi.setting.service.impl; + + +import com.ruoyi.setting.mapper.BaseInfoSetMapper; +import com.ruoyi.setting.service.BaseInfoSetService; +import com.ruoyi.common.utils.RedisCahceKey; +import com.ruoyi.segchk.domain.BaseInfoSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +/** + * 基本信息设置service实现类 + * + * @author 魔金商城 on 2017/5/17. + */ +@Service +public class BaseInfoSetServiceImpl implements BaseInfoSetService { + + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(BaseInfoSetServiceImpl.class); + + /** + * 注入信息设置mapper + */ + @Autowired + private BaseInfoSetMapper baseInfoSetMapper; + + /** + * 查询基本信息和高级信息设置 + * + * @return 基本信息和高级信息设置实体类 + */ + @Cacheable(value = RedisCahceKey.BASE_INFO_SET, key = "'BaseInfoSet'") + @Override + public BaseInfoSet queryBaseInfoSet() { + logger.debug("queryBaseInfoSet..."); + return baseInfoSetMapper.queryBaseInfoSet(); + } + + /** + * 编辑基本信息和高级信息 + * + * @param baseInfoSet 基本信息实体类 + * @param type 1 基本信息 0高级信息 + * @return -1编辑失败 1编辑成功 0编辑失败 + */ + @CacheEvict(value = RedisCahceKey.BASE_INFO_SET, allEntries = true) + @Override + public int editBaseInfoSet(BaseInfoSet baseInfoSet, int type) { + logger.debug("editBaseInfoSet and baseInfoSet:{}\r\n type:{}", baseInfoSet, type); + //非法参数 + if (!checkParam(type)) { + logger.error("editBaseInfoSet error due to type is illegal..."); + return -1; + } + baseInfoSet.dealPicUrl(); + //设置基本信息 + if (type == 1) { + logger.debug("editBaseInfoSet to editBaseInfoSetA and type:{}", type); + return baseInfoSetMapper.editBaseInfoSetA(baseInfoSet); + } + //设置高级信息 + if (type == 0) { + logger.debug("editBaseInfoSet to editBaseInfoSetB and type:{}", type); + return baseInfoSetMapper.editBaseInfoSetB(baseInfoSet); + } + return 0; + } + + /** + * 设置审核开关 + * + * @param storeSpuAudit 店铺商品审核开关 0 需要审核 1 不需要 默认0 + * @return 成功返回1,失败返回0 + */ + @CacheEvict(value = RedisCahceKey.BASE_INFO_SET, allEntries = true) + @Override + public int setAuditSwitch(String storeSpuAudit) { + logger.debug("setAuditSwitch and storeSpuAudit :{}", storeSpuAudit); + return baseInfoSetMapper.setAuditSwitch(storeSpuAudit); + } + + /** + * 设置会员价启用状态 + * + * @param memberPriceStatus 会员等级启用状态 0 启用 1 不启用 默认0 + * @return 成功返回1,失败返回0 + */ + @CacheEvict(value = RedisCahceKey.BASE_INFO_SET, allEntries = true) + @Override + public int setMemberPriceStatus(String memberPriceStatus) { + logger.debug("setMemberPriceStatus and memberPriceStatus :{}", memberPriceStatus); + return baseInfoSetMapper.setMemberPriceStatus(memberPriceStatus); + } + + @Override + public boolean isSkuNeedAudit() { + return queryBaseInfoSet().isSpuNeedAudit(); + } + + /** + * 校验参数是否为 0 或 1 + * + * @param type 参数 + * @return 正确true 错误 FALSE + */ + private boolean checkParam(int type) { + return type == 1 || type == 0; + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsCityServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsCityServiceImpl.java new file mode 100644 index 0000000..79a1ffd --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsCityServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.setting.domain.LsCity; +import com.ruoyi.setting.mapper.LsCityMapper; +import com.ruoyi.setting.service.ILsCityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 区域市Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsCityServiceImpl implements ILsCityService { + private static final Logger logger = LoggerFactory.getLogger(LsCityServiceImpl.class); + @Autowired + private LsCityMapper lsCityMapper; + + /** + * 查询区域市 + * + * @param id 区域市ID + * @return 区域市 + */ + @Override + public LsCity selectLsCityById(Long id) { + return lsCityMapper.selectLsCityById(id); + } + + /** + * 查询区域市列表 + * + * @param lsCity 区域市 + * @return 区域市 + */ + @Override + public List selectLsCityList(LsCity lsCity) { + return lsCityMapper.selectLsCityList(lsCity); + } + + /** + * 新增区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + @Override + public int insertLsCity(LsCity lsCity) { + lsCity.setCreateTime(DateUtils.getNowDate()); + return lsCityMapper.insertLsCity(lsCity); + } + + /** + * 修改区域市 + * + * @param lsCity 区域市 + * @return 结果 + */ + @Override + public int updateLsCity(LsCity lsCity) { + return lsCityMapper.updateLsCity(lsCity); + } + + /** + * 批量删除区域市 + * + * @param ids 需要删除的区域市ID + * @return 结果 + */ + @Override + public int deleteLsCityByIds(Long[] ids) { + return lsCityMapper.deleteLsCityByIds(ids); + } + + /** + * 删除区域市信息 + * + * @param id 区域市ID + * @return 结果 + */ + @Override + public int deleteLsCityById(Long id) { + return lsCityMapper.deleteLsCityById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsDistrictServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsDistrictServiceImpl.java new file mode 100644 index 0000000..2bbca57 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsDistrictServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.setting.domain.LsDistrict; +import com.ruoyi.setting.mapper.LsDistrictMapper; +import com.ruoyi.setting.service.ILsDistrictService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 区域区Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsDistrictServiceImpl implements ILsDistrictService { + private static final Logger logger = LoggerFactory.getLogger(LsDistrictServiceImpl.class); + @Autowired + private LsDistrictMapper lsDistrictMapper; + + /** + * 查询区域区 + * + * @param id 区域区ID + * @return 区域区 + */ + @Override + public LsDistrict selectLsDistrictById(Long id) { + return lsDistrictMapper.selectLsDistrictById(id); + } + + /** + * 查询区域区列表 + * + * @param lsDistrict 区域区 + * @return 区域区 + */ + @Override + public List selectLsDistrictList(LsDistrict lsDistrict) { + return lsDistrictMapper.selectLsDistrictList(lsDistrict); + } + + /** + * 新增区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + @Override + public int insertLsDistrict(LsDistrict lsDistrict) { + lsDistrict.setCreateTime(DateUtils.getNowDate()); + return lsDistrictMapper.insertLsDistrict(lsDistrict); + } + + /** + * 修改区域区 + * + * @param lsDistrict 区域区 + * @return 结果 + */ + @Override + public int updateLsDistrict(LsDistrict lsDistrict) { + return lsDistrictMapper.updateLsDistrict(lsDistrict); + } + + /** + * 批量删除区域区 + * + * @param ids 需要删除的区域区ID + * @return 结果 + */ + @Override + public int deleteLsDistrictByIds(Long[] ids) { + return lsDistrictMapper.deleteLsDistrictByIds(ids); + } + + /** + * 删除区域区信息 + * + * @param id 区域区ID + * @return 结果 + */ + @Override + public int deleteLsDistrictById(Long id) { + return lsDistrictMapper.deleteLsDistrictById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsEmailSettingServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsEmailSettingServiceImpl.java new file mode 100644 index 0000000..38c3b1f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsEmailSettingServiceImpl.java @@ -0,0 +1,90 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.domain.LsEmailSetting; +import com.ruoyi.setting.mapper.LsEmailSettingMapper; +import com.ruoyi.setting.service.ILsEmailSettingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 邮箱设置Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +@Service +public class LsEmailSettingServiceImpl implements ILsEmailSettingService { + private static final Logger logger = LoggerFactory.getLogger(LsEmailSettingServiceImpl.class); + @Autowired + private LsEmailSettingMapper lsEmailSettingMapper; + + /** + * 查询邮箱设置 + * + * @param id 邮箱设置ID + * @return 邮箱设置 + */ + @Override + public LsEmailSetting selectLsEmailSettingById(Long id) { + return lsEmailSettingMapper.selectLsEmailSettingById(id); + } + + /** + * 查询邮箱设置列表 + * + * @param lsEmailSetting 邮箱设置 + * @return 邮箱设置 + */ + @Override + public List selectLsEmailSettingList(LsEmailSetting lsEmailSetting) { + return lsEmailSettingMapper.selectLsEmailSettingList(lsEmailSetting); + } + + /** + * 新增邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + @Override + public int insertLsEmailSetting(LsEmailSetting lsEmailSetting) { + return lsEmailSettingMapper.insertLsEmailSetting(lsEmailSetting); + } + + /** + * 修改邮箱设置 + * + * @param lsEmailSetting 邮箱设置 + * @return 结果 + */ + @Override + public int updateLsEmailSetting(LsEmailSetting lsEmailSetting) { + return lsEmailSettingMapper.updateLsEmailSetting(lsEmailSetting); + } + + /** + * 批量删除邮箱设置 + * + * @param ids 需要删除的邮箱设置ID + * @return 结果 + */ + @Override + public int deleteLsEmailSettingByIds(Long[] ids) { + return lsEmailSettingMapper.deleteLsEmailSettingByIds(ids); + } + + /** + * 删除邮箱设置信息 + * + * @param id 邮箱设置ID + * @return 结果 + */ + @Override + public int deleteLsEmailSettingById(Long id) { + return lsEmailSettingMapper.deleteLsEmailSettingById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsPaySettingServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsPaySettingServiceImpl.java new file mode 100644 index 0000000..617b08f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsPaySettingServiceImpl.java @@ -0,0 +1,174 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.bean.PaySet; +import com.ruoyi.setting.bean.PaySetCommon; +import com.ruoyi.setting.domain.SegchkPaySetting; +import com.ruoyi.setting.mapper.SegchkPaySettingMapper; +import com.ruoyi.setting.service.ILsPaySettingService; +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 支付设置Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +@Service +public class LsPaySettingServiceImpl implements ILsPaySettingService { + private static final Logger logger = LoggerFactory.getLogger(LsPaySettingServiceImpl.class); + /** + * 支付类型列表 + */ + private final static List codeTypeList = Arrays.asList("1", "2", "3", "4", "5", "6"); + @Autowired + private SegchkPaySettingMapper segchkPaySettingMapper; + + /** + * 查询支付设置 + * + * @param id 支付设置ID + * @return 支付设置 + */ + @Override + public SegchkPaySetting selectLsPaySettingById(Long id) { + return segchkPaySettingMapper.selectLsPaySettingById(id); + } + + /** + * 查询支付接口设置 + * + * @return 返回PaySetCommon + */ + @Override + public PaySetCommon queryPaySet() { + logger.debug("queryPaySet..."); + return PaySetCommon.getPaySetCommon(new PaySetCommon(), segchkPaySettingMapper.queryPaySet()); + } + + /** + * 编辑支付接口设置 + * + * @param paySetCommon 实体类参数 + * @param codeType 支付设置类型 1 支付宝 2 微信(扫码,公众号,H5) 3 银联 4预存款 5 微信支app付 6微信小程序支付 + * @return -1编辑出错 >=1成功 + */ + @Override + @Transactional + public int editPaySet(PaySetCommon paySetCommon, String codeType) { + List list = new ArrayList<>(); + if (codeTypeList.indexOf(codeType) < 0) { + logger.error("editPaySet error codeType is illegal"); + return -1; + } + //先删后增 + segchkPaySettingMapper.deletePaySet(codeType); + if ("1".equals(codeType)) { + logger.debug("editPaySet aliPay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getAliPaySet().getAppId(), "appId")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getAliPaySet().getAlipayPublicKey(), "alipayPublicKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getAliPaySet().getAppPrivateKey(), "appPrivateKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getAliPaySet().getIsUse(), "isUse")); + } + if ("2".equals(codeType)) { + logger.debug("editPaySet wechatPay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getAppId(), "appId")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getAppSecret(), "appSecret")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getMerchantNum(), "merchantNum")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getApiKey(), "apiKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getLoginNotice(), "loginNotice")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatPaySet().getIsUse(), "isUse")); + } + if ("3".equals(codeType)) { + logger.debug("editPaySet unionPay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getUnionPaySet().getMerchantNum(), "merchantNum")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getUnionPaySet().getApiKey(), "apiKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getUnionPaySet().getIsUse(), "isUse")); + } + if ("4".equals(codeType)) { + logger.debug("editPaySet prePay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getPrePaySet().getIsUse(), "isUse")); + } + if ("5".equals(codeType)) { + logger.debug("editPaySet wechatAppPay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppPaySet().getAppId(), "appId")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppPaySet().getAppSecret(), "appSecret")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppPaySet().getMerchantNum(), "merchantNum")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppPaySet().getApiKey(), "apiKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppPaySet().getIsUse(), "isUse")); + } + if ("6".equals(codeType)) { +// 微信小程序 + logger.debug("editPaySet wechatAppletPay..."); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getAppId(), "appId")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getAppSecret(), "appSecret")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getMerchantNum(), "merchantNum")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getApiKey(), "apiKey")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getIsUse(), "isUse")); + list.add(PaySet.getPaySet(new PaySet(), codeType, paySetCommon.getWechatAppletPaySet().getCertFile(), "certFile")); + } + return segchkPaySettingMapper.addPaySet(list); + } + + /** + * 查询支付设置列表 + * + * @param segchkPaySetting 支付设置 + * @return 支付设置 + */ + @Override + public List selectLsPaySettingList(SegchkPaySetting segchkPaySetting) { + return segchkPaySettingMapper.selectLsPaySettingList(segchkPaySetting); + } + + /** + * 新增支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + @Override + public int insertLsPaySetting(SegchkPaySetting segchkPaySetting) { + return segchkPaySettingMapper.insertLsPaySetting(segchkPaySetting); + } + + /** + * 修改支付设置 + * + * @param segchkPaySetting 支付设置 + * @return 结果 + */ + @Override + public int updateLsPaySetting(SegchkPaySetting segchkPaySetting) { + return segchkPaySettingMapper.updateLsPaySetting(segchkPaySetting); + } + + /** + * 批量删除支付设置 + * + * @param ids 需要删除的支付设置ID + * @return 结果 + */ + @Override + public int deleteLsPaySettingByIds(Long[] ids) { + return segchkPaySettingMapper.deleteLsPaySettingByIds(ids); + } + + /** + * 删除支付设置信息 + * + * @param id 支付设置ID + * @return 结果 + */ + @Override + public int deleteLsPaySettingById(Long id) { + return segchkPaySettingMapper.deleteLsPaySettingById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsProvinceServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsProvinceServiceImpl.java new file mode 100644 index 0000000..1e4fb0c --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsProvinceServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.setting.domain.LsProvince; +import com.ruoyi.setting.mapper.LsProvinceMapper; +import com.ruoyi.setting.service.ILsProvinceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 区域省Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsProvinceServiceImpl implements ILsProvinceService { + private static final Logger logger = LoggerFactory.getLogger(LsProvinceServiceImpl.class); + @Autowired + private LsProvinceMapper lsProvinceMapper; + + /** + * 查询区域省 + * + * @param id 区域省ID + * @return 区域省 + */ + @Override + public LsProvince selectLsProvinceById(Long id) { + return lsProvinceMapper.selectLsProvinceById(id); + } + + /** + * 查询区域省列表 + * + * @param lsProvince 区域省 + * @return 区域省 + */ + @Override + public List selectLsProvinceList(LsProvince lsProvince) { + return lsProvinceMapper.selectLsProvinceList(lsProvince); + } + + /** + * 新增区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + @Override + public int insertLsProvince(LsProvince lsProvince) { + lsProvince.setCreateTime(DateUtils.getNowDate()); + return lsProvinceMapper.insertLsProvince(lsProvince); + } + + /** + * 修改区域省 + * + * @param lsProvince 区域省 + * @return 结果 + */ + @Override + public int updateLsProvince(LsProvince lsProvince) { + return lsProvinceMapper.updateLsProvince(lsProvince); + } + + /** + * 批量删除区域省 + * + * @param ids 需要删除的区域省ID + * @return 结果 + */ + @Override + public int deleteLsProvinceByIds(Long[] ids) { + return lsProvinceMapper.deleteLsProvinceByIds(ids); + } + + /** + * 删除区域省信息 + * + * @param id 区域省ID + * @return 结果 + */ + @Override + public int deleteLsProvinceById(Long id) { + return lsProvinceMapper.deleteLsProvinceById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSmsSettingServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSmsSettingServiceImpl.java new file mode 100644 index 0000000..05430f0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSmsSettingServiceImpl.java @@ -0,0 +1,90 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.domain.LsSmsSetting; +import com.ruoyi.setting.mapper.LsSmsSettingMapper; +import com.ruoyi.setting.service.ILsSmsSettingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 短信接口设置Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +@Service +public class LsSmsSettingServiceImpl implements ILsSmsSettingService { + private static final Logger logger = LoggerFactory.getLogger(LsSmsSettingServiceImpl.class); + @Autowired + private LsSmsSettingMapper lsSmsSettingMapper; + + /** + * 查询短信接口设置 + * + * @param id 短信接口设置ID + * @return 短信接口设置 + */ + @Override + public LsSmsSetting selectLsSmsSettingById(Long id) { + return lsSmsSettingMapper.selectLsSmsSettingById(id); + } + + /** + * 查询短信接口设置列表 + * + * @param lsSmsSetting 短信接口设置 + * @return 短信接口设置 + */ + @Override + public List selectLsSmsSettingList(LsSmsSetting lsSmsSetting) { + return lsSmsSettingMapper.selectLsSmsSettingList(lsSmsSetting); + } + + /** + * 新增短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + @Override + public int insertLsSmsSetting(LsSmsSetting lsSmsSetting) { + return lsSmsSettingMapper.insertLsSmsSetting(lsSmsSetting); + } + + /** + * 修改短信接口设置 + * + * @param lsSmsSetting 短信接口设置 + * @return 结果 + */ + @Override + public int updateLsSmsSetting(LsSmsSetting lsSmsSetting) { + return lsSmsSettingMapper.updateLsSmsSetting(lsSmsSetting); + } + + /** + * 批量删除短信接口设置 + * + * @param ids 需要删除的短信接口设置ID + * @return 结果 + */ + @Override + public int deleteLsSmsSettingByIds(Long[] ids) { + return lsSmsSettingMapper.deleteLsSmsSettingByIds(ids); + } + + /** + * 删除短信接口设置信息 + * + * @param id 短信接口设置ID + * @return 结果 + */ + @Override + public int deleteLsSmsSettingById(Long id) { + return lsSmsSettingMapper.deleteLsSmsSettingById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsStationLetterServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsStationLetterServiceImpl.java new file mode 100644 index 0000000..d37857f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsStationLetterServiceImpl.java @@ -0,0 +1,147 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.setting.domain.LsStationLetter; +import com.ruoyi.setting.mapper.LsStationLetterMapper; +import com.ruoyi.setting.service.ILsStationLetterService; +import com.ruoyi.util.PageHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.*; + +/** + * 站内信Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsStationLetterServiceImpl implements ILsStationLetterService { + private static final Logger logger = LoggerFactory.getLogger(LsStationLetterServiceImpl.class); + @Autowired + private LsStationLetterMapper lsStationLetterMapper; + + /** + * 查询站内信 + * + * @param id 站内信ID + * @return 站内信 + */ + @Override + public LsStationLetter selectLsStationLetterById(Long id) { + return lsStationLetterMapper.selectLsStationLetterById(id); + } + + /** + * 查询站内信列表 + * + * @param lsStationLetter 站内信 + * @return 站内信 + */ + @Override + public List selectLsStationLetterList(LsStationLetter lsStationLetter) { + return lsStationLetterMapper.selectLsStationLetterList(lsStationLetter); + } + + /** + * 新增站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + @Override + public int insertLsStationLetter(LsStationLetter lsStationLetter) { + lsStationLetter.setCreateTime(DateUtils.getNowDate()); + return lsStationLetterMapper.insertLsStationLetter(lsStationLetter); + } + + /** + * 修改站内信 + * + * @param lsStationLetter 站内信 + * @return 结果 + */ + @Override + public int updateLsStationLetter(LsStationLetter lsStationLetter) { + return lsStationLetterMapper.updateLsStationLetter(lsStationLetter); + } + + /** + * 批量删除站内信 + * + * @param ids 需要删除的站内信ID + * @return 结果 + */ + @Override + public int deleteLsStationLetterByIds(Long[] ids) { + return lsStationLetterMapper.deleteLsStationLetterByIds(ids); + } + + + @Override + public int addStationLetters(List stationLetters) { + logger.debug("addStationLetters and stationLetters:{}", stationLetters); + + if (CollectionUtils.isEmpty(stationLetters)) { + logger.error("addStationLetters fail due to params is null..."); + return 0; + } + return lsStationLetterMapper.addStationLetters(stationLetters); + } + + /** + * 删除站内信 + * + * @param id 站内信id + * @return 成功返回1,失败返回0 + */ + @Override + public int deleteStationLetters(long id) { + logger.debug("deleteStationLetters and id :{}", id); + return lsStationLetterMapper.deleteStationLetters(id); + } + + /** + * 更新会员的站内信的阅读状态 + * + * @param id 站内信id + * @return 成功返回1,失败返回0 + */ + @Override + public int updateStationLettersIsRead(long id, long customerId) { + logger.debug("updateStationLettersIsRead and id :{} \r\n customerId:{}", id, customerId); + Map params = new HashMap<>(); + params.put("id", id); + params.put("customerId", customerId); + return lsStationLetterMapper.updateStationLettersIsRead(params); + } + + @Override + public PageHelper queryStationLettersByCustomerId(PageHelper pageHelper, long customerId) { + logger.debug("queryStationLettersByCustomerId and customerId:{} and pageHelper:{}", customerId, pageHelper); + Map params = new HashMap<>(); + params.put("customerId", customerId); + return pageHelper.setListDates(lsStationLetterMapper.queryStationLettersByCustomerId(pageHelper.getQueryParams(params, lsStationLetterMapper.queryStationLettersCountByCustomerId(params)))); + } + + @Override + public int unReadNum(long customerId) { + logger.debug("unReadNum and customerId:{}", customerId); + return lsStationLetterMapper.unReadNum(customerId); + } + + /** + * 删除站内信信息 + * + * @param id 站内信ID + * @return 结果 + */ + @Override + public int deleteLsStationLetterById(Long id) { + return lsStationLetterMapper.deleteLsStationLetterById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSystemSeoServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSystemSeoServiceImpl.java new file mode 100644 index 0000000..8c9622b --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsSystemSeoServiceImpl.java @@ -0,0 +1,90 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.domain.LsSystemSeo; +import com.ruoyi.setting.mapper.LsSystemSeoMapper; +import com.ruoyi.setting.service.ILsSystemSeoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统seo设置Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsSystemSeoServiceImpl implements ILsSystemSeoService { + private static final Logger logger = LoggerFactory.getLogger(LsSystemSeoServiceImpl.class); + @Autowired + private LsSystemSeoMapper lsSystemSeoMapper; + + /** + * 查询系统seo设置 + * + * @param id 系统seo设置ID + * @return 系统seo设置 + */ + @Override + public LsSystemSeo selectLsSystemSeoById(Long id) { + return lsSystemSeoMapper.selectLsSystemSeoById(id); + } + + /** + * 查询系统seo设置列表 + * + * @param lsSystemSeo 系统seo设置 + * @return 系统seo设置 + */ + @Override + public List selectLsSystemSeoList(LsSystemSeo lsSystemSeo) { + return lsSystemSeoMapper.selectLsSystemSeoList(lsSystemSeo); + } + + /** + * 新增系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + @Override + public int insertLsSystemSeo(LsSystemSeo lsSystemSeo) { + return lsSystemSeoMapper.insertLsSystemSeo(lsSystemSeo); + } + + /** + * 修改系统seo设置 + * + * @param lsSystemSeo 系统seo设置 + * @return 结果 + */ + @Override + public int updateLsSystemSeo(LsSystemSeo lsSystemSeo) { + return lsSystemSeoMapper.updateLsSystemSeo(lsSystemSeo); + } + + /** + * 批量删除系统seo设置 + * + * @param ids 需要删除的系统seo设置ID + * @return 结果 + */ + @Override + public int deleteLsSystemSeoByIds(Long[] ids) { + return lsSystemSeoMapper.deleteLsSystemSeoByIds(ids); + } + + /** + * 删除系统seo设置信息 + * + * @param id 系统seo设置ID + * @return 结果 + */ + @Override + public int deleteLsSystemSeoById(Long id) { + return lsSystemSeoMapper.deleteLsSystemSeoById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsWxCustomerLinkServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsWxCustomerLinkServiceImpl.java new file mode 100644 index 0000000..92d1bd5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/LsWxCustomerLinkServiceImpl.java @@ -0,0 +1,90 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.domain.LsWxCustomerLink; +import com.ruoyi.setting.mapper.LsWxCustomerLinkMapper; +import com.ruoyi.setting.service.ILsWxCustomerLinkService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 微信登录和商城用户的关联Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-29 + */ +@Service +public class LsWxCustomerLinkServiceImpl implements ILsWxCustomerLinkService { + private static final Logger logger = LoggerFactory.getLogger(LsWxCustomerLinkServiceImpl.class); + @Autowired + private LsWxCustomerLinkMapper lsWxCustomerLinkMapper; + + /** + * 查询微信登录和商城用户的关联 + * + * @param id 微信登录和商城用户的关联ID + * @return 微信登录和商城用户的关联 + */ + @Override + public LsWxCustomerLink selectLsWxCustomerLinkById(Long id) { + return lsWxCustomerLinkMapper.selectLsWxCustomerLinkById(id); + } + + /** + * 查询微信登录和商城用户的关联列表 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 微信登录和商城用户的关联 + */ + @Override + public List selectLsWxCustomerLinkList(LsWxCustomerLink lsWxCustomerLink) { + return lsWxCustomerLinkMapper.selectLsWxCustomerLinkList(lsWxCustomerLink); + } + + /** + * 新增微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + @Override + public int insertLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink) { + return lsWxCustomerLinkMapper.insertLsWxCustomerLink(lsWxCustomerLink); + } + + /** + * 修改微信登录和商城用户的关联 + * + * @param lsWxCustomerLink 微信登录和商城用户的关联 + * @return 结果 + */ + @Override + public int updateLsWxCustomerLink(LsWxCustomerLink lsWxCustomerLink) { + return lsWxCustomerLinkMapper.updateLsWxCustomerLink(lsWxCustomerLink); + } + + /** + * 批量删除微信登录和商城用户的关联 + * + * @param ids 需要删除的微信登录和商城用户的关联ID + * @return 结果 + */ + @Override + public int deleteLsWxCustomerLinkByIds(Long[] ids) { + return lsWxCustomerLinkMapper.deleteLsWxCustomerLinkByIds(ids); + } + + /** + * 删除微信登录和商城用户的关联信息 + * + * @param id 微信登录和商城用户的关联ID + * @return 结果 + */ + @Override + public int deleteLsWxCustomerLinkById(Long id) { + return lsWxCustomerLinkMapper.deleteLsWxCustomerLinkById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/OssServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/OssServiceImpl.java new file mode 100644 index 0000000..6c743c9 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/OssServiceImpl.java @@ -0,0 +1,89 @@ +package com.ruoyi.setting.service.impl; + + +import com.ruoyi.setting.bean.OssSetting; +import com.ruoyi.setting.bean.UploadData; +import com.ruoyi.setting.mapper.OssMapper; +import com.ruoyi.setting.service.OssService; +import com.ruoyi.util.YunUploadUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + + +/** + * Created by luozhuo on 2020/7/7. + * 云存储服务实现类 + */ +@Service +public class OssServiceImpl implements OssService { + + private Logger logger = LoggerFactory.getLogger(OssServiceImpl.class); + + @Autowired + private OssMapper ossMapper; + + @Override + public List uploadToQqOss(List uploadDatas) { + logger.debug("Begin to uploadToQqOss...."); + if (CollectionUtils.isEmpty(uploadDatas)) { + logger.error("uploadDatas fail due to params is empty..."); + return Arrays.asList(""); + } + return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().uploadToQqOss(queryOssSetting().getUpYunConf(), uploadData.getMultipartFile(), uploadData.getDatas(), uploadData.getFileOriginName(), uploadData.getType())).collect(Collectors.toList()); + + } + + @Override + public List uploadToQqOssForBase64(List uploadDatas) { + if (CollectionUtils.isEmpty(uploadDatas)) { + logger.error("uploadToQqOssForBase64 fail due to params is empty..."); + return Arrays.asList(""); + } + return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance(). + uploadToQqForBase64(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName())).collect(Collectors.toList()); + + } + + @Override + public List uploadToOss(List uploadDatas) { + logger.debug("Begin to uploadToOss...."); + if (CollectionUtils.isEmpty(uploadDatas)) { + logger.error("uploadDatas fail due to params is empty..."); + return Arrays.asList(""); + } + return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().uploadToOssYun(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName(), uploadData.getType())).collect(Collectors.toList()); + + } + + @Override + public List uploadToOssForBase64(List uploadDatas) { + if (CollectionUtils.isEmpty(uploadDatas)) { + logger.error("uploadToOssForBase64 fail due to params is empty..."); + return Arrays.asList(""); + } + + return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance(). + uploadToQqForBase64(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName())).collect(Collectors.toList()); + + } + + @Override + public OssSetting queryOssSetting() { + logger.debug("Begin to queryUpYunSetting...."); + return ossMapper.queryOssSetting(); + } + + @Override + public int updateOss(OssSetting ossSetting) { + logger.error("updateOss and OssSetting:{}", ossSetting); + return ossMapper.updateOss(ossSetting); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/SCommunityBuySettingServiceImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/SCommunityBuySettingServiceImpl.java new file mode 100644 index 0000000..f9e4330 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/service/impl/SCommunityBuySettingServiceImpl.java @@ -0,0 +1,90 @@ +package com.ruoyi.setting.service.impl; + +import com.ruoyi.setting.domain.SCommunityBuySetting; +import com.ruoyi.setting.mapper.SCommunityBuySettingMapper; +import com.ruoyi.setting.service.ISCommunityBuySettingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 社区团购设置Service业务层处理 + * + * @author 魔金商城 + * @date 2020-07-28 + */ +@Service +public class SCommunityBuySettingServiceImpl implements ISCommunityBuySettingService { + private static final Logger logger = LoggerFactory.getLogger(SCommunityBuySettingServiceImpl.class); + @Autowired + private SCommunityBuySettingMapper sCommunityBuySettingMapper; + + /** + * 查询社区团购设置 + * + * @param id 社区团购设置ID + * @return 社区团购设置 + */ + @Override + public SCommunityBuySetting selectSCommunityBuySettingById(Long id) { + return sCommunityBuySettingMapper.selectSCommunityBuySettingById(id); + } + + /** + * 查询社区团购设置列表 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 社区团购设置 + */ + @Override + public List selectSCommunityBuySettingList(SCommunityBuySetting sCommunityBuySetting) { + return sCommunityBuySettingMapper.selectSCommunityBuySettingList(sCommunityBuySetting); + } + + /** + * 新增社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + @Override + public int insertSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting) { + return sCommunityBuySettingMapper.insertSCommunityBuySetting(sCommunityBuySetting); + } + + /** + * 修改社区团购设置 + * + * @param sCommunityBuySetting 社区团购设置 + * @return 结果 + */ + @Override + public int updateSCommunityBuySetting(SCommunityBuySetting sCommunityBuySetting) { + return sCommunityBuySettingMapper.updateSCommunityBuySetting(sCommunityBuySetting); + } + + /** + * 批量删除社区团购设置 + * + * @param ids 需要删除的社区团购设置ID + * @return 结果 + */ + @Override + public int deleteSCommunityBuySettingByIds(Long[] ids) { + return sCommunityBuySettingMapper.deleteSCommunityBuySettingByIds(ids); + } + + /** + * 删除社区团购设置信息 + * + * @param id 社区团购设置ID + * @return 结果 + */ + @Override + public int deleteSCommunityBuySettingById(Long id) { + return sCommunityBuySettingMapper.deleteSCommunityBuySettingById(id); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/AreaItem.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/AreaItem.java new file mode 100644 index 0000000..fb9974a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/AreaItem.java @@ -0,0 +1,9 @@ +package com.ruoyi.setting.vo; + +/** + * Created by 魔金商城 on 17/11/21. + * 区域枚举 + */ +public enum AreaItem { + CITY, DISTRICT, NO, ALL +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/Locality.java b/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/Locality.java new file mode 100644 index 0000000..42e40f7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/setting/vo/Locality.java @@ -0,0 +1,89 @@ +package com.ruoyi.setting.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @author 魔金商城 + * @date 2019-12-04 15:09 + *

    + * 地区新数据接口实体 + */ +@ApiModel(description = "地区新数据接口实体") +public class Locality { + + + /** + * 地区名称 + */ + @ApiModelProperty(value = "地区名称") + private String name; + + + /** + * 数据真实主键ID + */ + @ApiModelProperty(value = "数据真实主键ID") + private String id; + + + /** + * 临时Id字串 保证唯一 + */ + @ApiModelProperty(value = "临时Id字串 保证唯一") + private String value; + + + /** + * 父类的临时字串 一级为0 + */ + @ApiModelProperty(value = "父类的临时字串 一级为0") + private String parent; + + + /** + * 重写全参构造 + * + * @param name 地区名称 + * @param value ID + * @param parent 父类ID 一级为0 + */ + public Locality(String name, String value, String parent, long id) { + this.name = name; + this.value = value; + this.parent = parent; + this.id = String.valueOf(id); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/AesUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/AesUtils.java new file mode 100644 index 0000000..5eddba5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/AesUtils.java @@ -0,0 +1,82 @@ +package com.ruoyi.util; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.*; + +/** + * AES加密类 + * + * @author SK + * @since 2018/6/13 + */ +public class AesUtils { + + { + Security.addProvider(new BouncyCastleProvider()); + } + + /** + * 获取对象 + */ + public static AesUtils getInstance() { + return LazyHolder.aesUtils; + } + + // 生成iv + private static AlgorithmParameters generateIV(byte[] iv) throws Exception { + AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); + params.init(new IvParameterSpec(iv)); + return params; + } + + /** + * AES对称解密工具类 + * + * @param content 密文 + * @return + * @throws InvalidAlgorithmParameterException + * @throws NoSuchProviderException + */ + public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { + try { + // java是没有 + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); + Key sKeySpec = new SecretKeySpec(keyByte, "AES"); + + cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化 + byte[] result = cipher.doFinal(content); + return result; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 延迟加载(线程安全) + */ + private static class LazyHolder { + private static AesUtils aesUtils = new AesUtils(); + } +} + + diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/BaseResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/BaseResponse.java new file mode 100644 index 0000000..7bc2a82 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/BaseResponse.java @@ -0,0 +1,89 @@ +package com.ruoyi.util; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +/** + * Created by 魔金商城 on 17/5/9. + * 分页基础响应类 + */ +@ApiModel(description = "分页基础响应类") +public class BaseResponse { + + + /** + * 返回的数据 + */ + @ApiModelProperty(value = "返回的数据") + private List data; + /** + * 总记录数 + */ + @ApiModelProperty(value = "总记录数") + private int recordsTotal; + /** + * 过滤后的记录数 + */ + @ApiModelProperty(value = "过滤后的记录数") + private int recordsFiltered; + /** + * 总的页数 + */ + @ApiModelProperty(value = "总的页数") + private int totalPage; + + private BaseResponse() { + + } + + private BaseResponse(PageHelper pageHelper) { + this.data = pageHelper.getList(); + this.recordsTotal = pageHelper.getRows(); + this.recordsFiltered = pageHelper.getRows(); + this.totalPage = pageHelper.getTotalPages(); + } + + /** + * 构造分页响应实体 + * + * @param pageHelper 分页帮助类 + * @return 返回分页响应实体 + */ + public static BaseResponse build(PageHelper pageHelper) { + return new BaseResponse(pageHelper); + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public int getRecordsTotal() { + return recordsTotal; + } + + public void setRecordsTotal(int recordsTotal) { + this.recordsTotal = recordsTotal; + } + + public int getRecordsFiltered() { + return recordsFiltered; + } + + public void setRecordsFiltered(int recordsFiltered) { + this.recordsFiltered = recordsFiltered; + } + + public int getTotalPage() { + return totalPage; + } + + public void setTotalPage(int totalPage) { + this.totalPage = totalPage; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/Claims.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/Claims.java new file mode 100644 index 0000000..53a7ce4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/Claims.java @@ -0,0 +1,132 @@ +package com.ruoyi.util; + +import com.alibaba.fastjson.annotation.JSONField; +import org.springframework.util.StringUtils; + +/** + * Created by 魔金商城 on 2018/6/13. + * 小程序凭证实体 + */ +public class Claims { + + /** + * 小程序unionId + */ + @JSONField(name = "unionId") + private String unionId; + + /** + * 会员id + */ + @JSONField(name = "userId") + private Long userId; + + /** + * 小程序sessionKey + */ + @JSONField(name = "sessionKey") + private String sessionKey; + + /** + * 微信用户标识 + */ + @JSONField(name = "openId") + private String openId; + + /** + * 用户角色 + */ + @JSONField(name = "userLevel") + private int userLevel; + + /** + * 归属运营商id + */ + @JSONField(name = "providerId") + private Long providerId; + + + + + /** + * 判断是否有unionId + * + * @return 有返回true 没有返回fasle + */ + public boolean hasUnionId() { + return !StringUtils.isEmpty(this.unionId); + } + + /** + * 判断是否有会员id + * + * @return 有返回true 没有返回false + */ + public boolean hasCustomerId() { + return CommonConstant.NO_LOGIN_CUSTOMERID != this.userId; + } + + public String getUnionId() { + return unionId; + } + + public void setUnionId(String unionId) { + this.unionId = unionId; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public void setUserLevel(int userLevel) { + this.userLevel = userLevel; + } + + public void setProviderId(Long providerId) { + this.providerId = providerId; + } + + @Override + public String toString() { + return "Claims{" + + "unionId='" + unionId + '\'' + + ", userId=" + userId + + ", sessionKey='" + sessionKey + '\'' + + ", openId='" + openId + '\'' + + ", userLevel=" + userLevel + + ", providerId=" + providerId + + '}'; + } + + public Long getProviderId() { + return providerId; + } + + public int getUserLevel() { + return userLevel; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonConstant.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonConstant.java new file mode 100644 index 0000000..83c3599 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonConstant.java @@ -0,0 +1,310 @@ +package com.ruoyi.util; + +/** + * Created by 魔金商城 on 17/5/2. + * 公共常量类 + */ +public interface CommonConstant { + + /** + * 开始页 + */ + String START_ROW_NUM = "startRowNum"; + + /** + * 每页大小 + */ + String PAGE_SIZE = "pageSize"; + + /** + * store端session放置手机验证码的key(代客下单) + */ + String STORE_SHOPPING_CODE_KEY = "STORE_SHOPPING_CODE_KEY"; + + /** + * store端session放置验证标记key(代客下单) + */ + String STORE_SHOPPING_MOBILE_KEY = "STORE_SHOPPING_VALIDFLAG_KEY"; + + /** + * 加号替换 + */ + String PLUS_REPLACE = "5lec2shop0"; + /** + * 从pc端发出 + */ + String FROM_PC = "FROM_PC"; + + /** + * admin端店铺id默认值0 + */ + long ADMIN_STOREID = 0; + + /** + * 查询的时候不需要带店铺id过滤 + */ + long QUERY_WITH_NO_STORE = -1; + + /** + * 查询的收货不需要带用户id进行过滤 + */ + long QUERY_WITH_NO_CUSTOMER = -1; + + /** + * 评论、回复不根据ISSHOW显示 + */ + long QUERY_WITH_NO_ISSHOW = -1; + /** + * 评论、回复根据ISSHOW显示 + */ + long QUERY_WITH_ISSHOW = 1; + + /** + * 主题不根据ISUSE显示 + */ + long QUERY_WITH_NO_ISUSE = -1; + /** + * 主题根据ISUSE显示 + */ + long QUERY_WITH_ISUSE = 1; + /** + * 文章不根据columnId显示 + */ + long QUERY_WITH_NO_COLUMNID = -1; + /** + * 文章根据ISRELEASE显示 + */ + long QUERY_WITH_ISRELEASE = 1; + /** + * 验证通过标记 + */ + String PASS_FLAG = "PASS"; + + /** + * 未登录状态下的会员id + */ + long NO_LOGIN_CUSTOMERID = -1; + + /** + * 登录成功后把用户信息放入session的key + */ + String MOBILE_LOGIN_SESSION_KEY = "MOBILE_LOGIN_SESSION_KEY"; + + /** + * 微信授权后把openId放入session的key(微信内置浏览器) + */ + String MOBILE_OPENID_SESSION_KEY = "MOBILE_OPENID_SESSION_KEY"; + /** + * 微信授权后把unionId放入session的key(微信内置浏览器) + */ + String MOBILE_UNIONID_SESSION_KEY = "MOBILE_UNIONID_SESSION_KEY"; + + /** + * mobile端session放置手机验证码的key(注册) + */ + String MOBILE_REGISTER_CODE_KEY = "MOBILE_REGISTER_CODE_KEY"; + + /** + * mobile端session放置手机验证码的key(忘记密码) + */ + String MOBILE_FORGETPWD_CODE_KEY = "MOBILE_FORGETPWD_CODE_KEY"; + /** + * mobile端session放置手机验证码的key(绑定新手机_旧手机验证码) + */ + String MOBILE_BINDNEWMOBILE_CODE_KEY = "MOBILE_BINDNEWMOBILE_CODE_KEY"; + /** + * mobile端session放置手机验证码的key(绑定新手机_新手机验证码) + */ + String MOBILE_BINDNEWMOBILE_NEWMOBILE_CODE_KEY = "MOBILE_BINDNEWMOBILE_NEWMOBILE_CODE_KEY"; + /** + * mobile端session放置验证标记key(绑定新手机) + */ + String MOBILE_BINDNEWMOBILE_VALIDFLAG_KEY = "MOBILE_BINDNEWMOBILE_VALIDFLAG_KEY"; + /** + * mobile端session放置手机验证码的key(更新支付密码) + */ + String MOBILE_UPDATEPAYPWD_CODE_KEY = "MOBILE_UPDATEPAYPWD_CODE_KEY"; + /** + * mobile端session放置手机验证码的key(更新密码) + */ + String MOBILE_UPDATEPWD_CODE_KEY = "MOBILE_UPDATEPWD_CODE_KEY"; + /** + * 订单支付 + */ + int ORDER_PAY = 1; + + /** + * 门店订单支付 + */ + int STORE_ORDER_PAY = 3; + + /** + * 预存款充值 + */ + int RECHARGE_PAY = 2; + + /** + * 支付宝支付 + */ + String ALI_PAY = "支付宝"; + /** + * 微信支付 + */ + String WECHAT_PAY = "微信"; + /** + * 银联支付 + */ + String UNION_PAY = "银联"; + + /** + * 抢购代号 + */ + String PANIC_BUY = "3"; + + /** + * 未过期的活动标记 + */ + String NOT_PAST = "999"; + + /** + * 没有用户id + */ + long NO_CUSTOMER_ID = -1; + + /** + * 还没使用抢购 + */ + int NO_USE_PANIC = -1; + + /** + * 没有抢购促销 + */ + int NO_PANIC_MARKETING = -2; + + /** + * 没有商品试用申请 + */ + int NO_SKU_TRY_APPLY = -1; + + /** + * 平台关注人数 + */ + int ADMIN_FOLLOW_NUM = 10000; + + + /** + * 小程序端redis放置手机验证码的key(注册) + */ + String APPLET_REGISTER_CODE_KEY = "APPLET_REGISTER_CODE_KEY"; + + /** + * 小程序端redis短信验证测试key + */ + String SMS_TEST_KEY = "APPLET_TEST_KEY"; + + /** + * 小程序端redis放置登录的key(注册登录) + */ + String APPLET_LOGIN_KEY = "APPLET_LOGIN_KEY"; + String APPLET_BIND_OPENID = "APPLET_BIND_OPENID"; + + String APPLET_SERVICE_CHK = "APPLET_SERVICE_CHK"; + + + /** + * 与会员价互斥 + */ + long MEMBER_PRICE_EXCLUSION = 2L; + + /** + * 与商品组合互斥 + */ + long COMBINATION_EXCLUSION = 1L; + + /** + * 与批发单品互斥 + */ + long BATCH_SKU_EXCLUSION = 3L; + + + /** + * 上传的图片 + */ + String UPLOAD_PIC = "0"; + + /** + * 门店订单 + */ + String STORE_ORDER = "1"; + + /** + * 普通订单 + */ + String ORDINARY_ORDER = "2"; + + /** + * 预存款订单 + */ + String PREALSE_ORDER = "3"; + + /** + * 二级分销 + */ + String SECOND_COMMISSION_LEVEL = "2"; + + /** + * 抢购促销图片类型 + */ + String PANIC_MARKETING_PIC_TYPE = "1"; + + /** + * 预售促销图片类型 + */ + String PRESALE_MARKETING_PIC_TYPE = "2"; + + /** + * 拼团促销图片类型 + */ + String GROUP_MARKETING_PIC_TYPE = "3"; + + /** + * 试用促销图片类型 + */ + String TRY_MARKETING_PIC_TYPE = "4"; + + /** + * 秒杀促销显示 + */ + String PANIC_SHOW = "1"; + + /** + * 秒杀促销不显示 + */ + String PANIC_NOT_SHOW = "0"; + + /** + * 预售分类 + */ + String PRESALE_MARKETING_CATE = "1"; + + /** + * 拼团分类 + */ + String GROUP_MARKETING_CATE = "2"; + + /** + * 试用分类 + */ + String TRY_MARKETING_CATE = "3"; + + /** + * 定金预售类型 + */ + String DEPOSIT_PRESALE_TYPE = "1"; + + /** + * 全款预售类型 + */ + String FULL_PRESALE_TYPE = "2"; + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonResponse.java new file mode 100644 index 0000000..db7a516 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/CommonResponse.java @@ -0,0 +1,73 @@ +package com.ruoyi.util; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.util.ObjectUtils; + +/** + * Created by 魔金商城 on 17/12/1. + * 通用返回对象 + */ +@ApiModel(description = "通用返回对象") +public class CommonResponse { + + /** + * 返回码 1 成功 其他失败 默认0没有数据 + */ + @ApiModelProperty(value = "返回码 1 成功 其他失败 默认0没有数据") + private int flag = 0; + + /** + * 数据 + */ + @ApiModelProperty(value = "数据") + private T data; + + + /** + * 构造返回对象 + * + * @param t 返回的对象 + * @return 返回的对象 + */ + public static CommonResponse build(T t) { + CommonResponse commonResponse = new CommonResponse<>(); + // 没有数据 + if (ObjectUtils.isEmpty(t)) { + return commonResponse; + } + commonResponse.flag = 1; + commonResponse.data = t; + return commonResponse; + } + + /** + * 构造返回对象 + * + * @param t 返回的对象 + * @param code 返回码 + * @return 返回的对象 + */ + public static CommonResponse build(T t, int code) { + CommonResponse commonResponse = new CommonResponse<>(); + commonResponse.flag = code; + commonResponse.data = t; + return commonResponse; + } + + public int getFlag() { + return flag; + } + + public void setFlag(int flag) { + this.flag = flag; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/CustomHttpUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/CustomHttpUtils.java new file mode 100644 index 0000000..549613d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/CustomHttpUtils.java @@ -0,0 +1,349 @@ +package com.ruoyi.util; + +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.*; +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.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 自定义http工具类 + * + * @author 魔金商城 created on 2020/4/14 + */ +public class CustomHttpUtils { + + private static final Logger logger = LoggerFactory.getLogger(CustomHttpUtils.class); + /** + * 执行GET方法请求数据 + * + * @param url 请求地址 + * @return 返回数据 + */ + public static String doGet(String url) { + logger.debug("CustomHttpUtils.doGet and url:{}", url); + return getResult(getHttpClient(), new HttpGet(url)); + } + + /** + * 执行POST方法form方式请求数据 + * + * @param url 请求地址 + * @param params 请求参数 + * @return 返回数据 + */ + public static String postForm(String url, Map params) { + logger.debug("CustomHttpUtils.postForm and url:{} \r\n params:{}", url, params); + return getFormRequestResult(getHttpClient(), new HttpPost(url), params); + } + + + /** + * 执行POST方法json方式请求数据 + * + * @param url 请求地址 + * @param jsonString 请求参数(json字符串) + * @return 返回数据 + */ + public static String postJson(String url, String jsonString) { + logger.debug("CustomHttpUtils.postJson and url:{} \r\n jsonString:{}", url, jsonString); + return getJsonRequestResult(jsonString, getHttpClient(), new HttpPost(url)); + } + + + /** + * 执行DELETE方法请求数据 + * + * @param url 请求地址 + * @return 返回数据 + */ + public static String doDelete(String url) { + logger.debug("CustomHttpUtils.doDelete and url:{}", url); + return getResult(getHttpClient(), new HttpDelete(url)); + } + + + /** + * 执行put方法form方式请求数据 + * + * @param url 请求地址 + * @param params 请求参数 + * @return 返回数据 + */ + public static String putForm(String url, Map params) { + logger.debug("CustomHttpUtils.putForm and url:{} \r\n params:{}", url, params); + return getFormRequestResult(getHttpClient(), new HttpPut(url), params); + } + + + /** + * 执行put方法json方式请求数据 + * + * @param url 请求地址 + * @param jsonString 请求参数(json字符串) + * @return 返回数据 + */ + public static String putJson(String url, String jsonString) { + logger.debug("CustomHttpUtils.putJson and url:{} \r\n jsonString:{}", url, jsonString); + return getJsonRequestResult(jsonString, getHttpClient(), new HttpPut(url)); + } + + + /** + * 从cookie中获取token + */ + public static String getTokenFromCookie() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = ""; + Cookie[] cookies = request.getCookies(); + if (Objects.isNull(cookies)) { + return ""; + } + for (Cookie temp : cookies) { + if (temp.getName().equals("Authorization")) { + token = temp.getValue(); + } + } + return token; + } + + /** + * 从header中获取token + */ + public static String getTokenFromHeader() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = ""; + // 认证信息在header 中的key + final String authHeader = request.getHeader("Authorization"); + if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer ")) { + logger.info("getToken from header fail...."); + } else { + token = authHeader.substring(7); + } + return token; + } + + /** + * 通用获取token(如果request头中有Auth信息,则返回头中的token,否则返回cookie中的token) + * + * @return token + */ + private static String getTokenCommon() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + if (!StringUtils.isEmpty(request.getHeader("Authorization"))) { + logger.info("getTokenCommon:getAuthorization from header is not empty"); + return getTokenFromHeader(); + } + return getTokenFromCookie(); + } + +// /** +// * 从token获取userName +// * +// * @param token token +// * @param publicKey 公钥 +// * @return userName +// */ +// public static String getUserNameFromToken(String token, String publicKey) { +// log.debug("getUserNameFromToken and token:{} \r\n publicKey:{}", token, publicKey); +// if (StringUtils.isEmpty(token)) { +// return ""; +// } +// Jwt jwt = null; +// try { +// SignatureVerifier verifier = new RsaVerifier(publicKey); +// jwt = JwtHelper.decodeAndVerify(token, verifier); +// } catch (Exception e) { +// log.error(e.getMessage()); +// } +// if (Objects.nonNull(jwt)) { +// log.debug("getUserNameFromToken and claims:{}", jwt.getClaims()); +// JSONObject claims = JSONObject.parseObject(jwt.getClaims()); +// // 判断有效期是否过期 +// if (Long.parseLong(claims.getString("exp")) > new Date().getTime() / 1000) { +// return claims.getString("user_name"); +// } +// } +// return ""; +// } + + /** + * 下载文件 + * + * @param out 输出流 + * @param url 文件地址 + */ + public static void downLoadFile(OutputStream out, String url) { + logger.debug("downLoadFile and url:{}", url); + if (StringUtils.isEmpty(url)) { + logger.debug("downLoadFile fail : url is empty"); + return; + } + InputStream inputStream = null; + try { + inputStream = getInputStreamResultFormUrl(url); + int b = 0; + byte[] buffer = new byte[512]; + while (b != -1) { + b = inputStream.read(buffer); + //4.写到输出流(out)中 + out.write(buffer, 0, b); + } + + } catch (IOException e) { + logger.error(e.getMessage()); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + out.close(); + out.flush(); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + } + + public static InputStream getInputStreamResultFormUrl(String url) throws IOException { + return getInputStreamResult(getHttpClient(), new HttpGet(url)); + } + + /** + * 设置下载信息 + * + * @param response 返回 + * @param fileName 文件名 + */ + public static void setDownloadInfo(HttpServletResponse response, String fileName) { + //1.设置文件ContentType类型,这样设置,会自动判断下载文件类型 + response.setContentType("multipart/form-data"); + //2.设置文件头:最后一个参数是设置下载文件 + response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); + } + + /** + * 获取httpClient + */ + private static HttpClient getHttpClient() { + BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + return HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + } + + + /** + * 获取json请求返回值 + * + * @param jsonString 请求参数 + * @param httpClient http客户端 + * @param httpRequest 请求对象 + * @return 请求返回 + */ + private static String getJsonRequestResult(String jsonString, HttpClient httpClient, HttpEntityEnclosingRequestBase httpRequest) { + String result = null; + //设置token +// httpRequest.setHeader("Authorization", "Bearer " + getTokenCommon()); + httpRequest.setHeader("Content-type", "application/json; charset=utf-8"); + StringEntity requestParam = new StringEntity(jsonString, "UTF-8"); + requestParam.setContentType("application/json"); + try { + httpRequest.setEntity(requestParam); + result = EntityUtils.toString(httpClient.execute(httpRequest).getEntity(), "UTF-8");//取出应答字符串 + } catch (IOException e) { + logger.error(e.getMessage()); + } + logger.debug("getJsonRequestResult and result:{}", result == null ? "" : result); + return result; + } + + /** + * 获取form请求返回值 + * + * @param formParam 请求参数 + * @param httpClient http客户端 + * @param httpRequest 请求对象 + * @return 请求返回 + */ + private static String getFormRequestResult(HttpClient httpClient, HttpEntityEnclosingRequestBase httpRequest, Map formParam) { + String result = null; + List params = new ArrayList<>(); + if (Objects.nonNull(formParam)) { + formParam.forEach((key, value) -> params.add(new BasicNameValuePair(key, value))); + } +// httpRequest.setHeader("Authorization", "Bearer " + getTokenCommon()); + try { + httpRequest.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + result = EntityUtils.toString(httpClient.execute(httpRequest).getEntity(), "UTF-8");//取出应答字符串 + } catch (IOException e) { + logger.error(e.getMessage()); + } + logger.debug("getFormRequestResult and result:{}", result == null ? "" : result); + return result; + } + + /** + * 获取http请求返回 + * + * @param httpClient http客户端 + * @param httpRequest 请求对象 + * @return 请求返回 + */ + private static String getResult(HttpClient httpClient, HttpUriRequest httpRequest) { + String result = null; +// httpRequest.setHeader("Authorization", "Bearer " + getTokenCommon()); + try { + result = EntityUtils.toString(httpClient.execute(httpRequest).getEntity(), Charset.forName("utf-8"));//取出应答字符串 + } catch (IOException e) { + logger.error(e.getMessage()); + } + logger.debug("getResult and result:{}", result == null ? "" : result); + return result; + } + + /** + * 获取http请求输入流返回 + * + * @param httpClient http客户端 + * @param httpRequest 请求对象 + * @return 请求返回 + */ + private static InputStream getInputStreamResult(HttpClient httpClient, HttpUriRequest httpRequest) throws IOException { + return httpClient.execute(httpRequest).getEntity().getContent(); + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/Express100Utils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/Express100Utils.java new file mode 100644 index 0000000..2ee1b61 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/Express100Utils.java @@ -0,0 +1,47 @@ +package com.ruoyi.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 快递100工具类 + */ +public class Express100Utils { + + /** + * 快递100获取查询地址的接口地址 + */ + private final static String KUAIDI_URL = "https://www.kuaidi100.com/chaxun?com=%s&nu=%s"; + /** + * H5查询物流信息地址 + */ + private final static String H5_KUAIDI_URL = "https://m.kuaidi100.com/app/query/?coname=lecshop&com=%s&nu=%s&callbackurl=%s"; + /** + * 日志 + */ + static Logger logger = LoggerFactory.getLogger(Express100Utils.class); + + /** + * 获得htmlapi的快递查询地址 + * + * @param express100Code 快递代号 + * @param waybillCode 运单号 + */ + public static String getHtmlApiURl(String express100Code, String waybillCode) { + logger.debug("getHtmlApiURl and express100Code:{} \r\n waybillCode:{}", express100Code, waybillCode); + return String.format(KUAIDI_URL, express100Code, waybillCode); + } + + /** + * 生成H5查询物流信息url + * + * @param express100Code 快递代号 + * @param waybillCode 运单号 + * @param callBackUrl 回跳地址(http开头) + * @return h5物流信息url + */ + public static String formatH5Url(String express100Code, String waybillCode, String callBackUrl) { + return String.format(H5_KUAIDI_URL, express100Code, waybillCode, callBackUrl); + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/Graphics2DUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/Graphics2DUtils.java new file mode 100644 index 0000000..d012904 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/Graphics2DUtils.java @@ -0,0 +1,110 @@ +package com.ruoyi.util; + +import com.ruoyi.common.utils.StringUtils; + +import java.awt.*; +import java.util.ArrayList; + +public class Graphics2DUtils { + /** + * 向画布上写文字 + * + * @param g Graphics2D对象 + * @param color 颜色 + * @param font 字体 + * @param content 内容 + * @param x 坐标x + * @param y 坐标y + */ + public static void drawString(Graphics2D g, Color color, Font font, String content, float x, float y) { + g.setColor(color); + g.setFont(font); + g.drawString(content, x, y); + } + + /** + * 向画布上写多行文字文字,自动居中 + * + * @param g Graphics2D对象 + * @param color 颜色 + * @param font 字体 + * @param content 内容 + * @param x 坐标X + * @param y 坐标y + * @param width 画布宽度 + * @param lineWordNum 每行字数 + * @param linePadding 行间距 + * @param center 是否居中 + */ + public static void drawString(Graphics2D g, Color color, Font font, String content, float x, float y, int width, int lineWordNum, int linePadding, boolean center) { + int num = content.length(); + + ArrayList contents = new ArrayList<>(); + if (num <= lineWordNum) { + + contents.add(content); + } else { + for (int i = 0; i < num; i += lineWordNum) { + contents.add(StringUtils.substring(content, i, i + lineWordNum)); + } + + } + for (int i = 0; i < contents.size(); i++) { + String s = contents.get(i); + if (i != 0) { + y += linePadding + font.getSize(); + } + if (center) { + drawCenterString(g, color, font, s, width, y); + } else { + drawString(g, color, font, s, x, y); + } + } + } + + /** + * 向画布上写多行文字文字,自动居中 + * + * @param g Graphics2D对象 + * @param color 颜色 + * @param font 字体 + * @param content 内容 + * @param y 坐标y + * @param width 画布宽度 + * @param lineWordNum 每行字数 + * @param linePadding 行间距 + */ + public static void drawCenterString(Graphics2D g, Color color, Font font, String content, float y, int width, int lineWordNum, int linePadding) { + drawString(g, color, font, content, 0, y, width, lineWordNum, linePadding, true); + } + + /** + * 向画布上写文字,自动居中 + * + * @param g Graphics2D对象 + * @param color 颜色 + * @param font 字体 + * @param content 内容 + * @param width 画布宽度 + * @param y 坐标y + */ + public static void drawCenterString(Graphics2D g, Color color, Font font, String content, int width, float y) { + int textWidth = getStringWidth(g, font, content); + + drawString(g, color, font, content, (width - textWidth) / 2, y); + } + + /** + * 获取字符串内容的宽度 + * + * @param g Graphics2D对象 + * @param font 字体 + * @param content 内容 + * @return + */ + public static int getStringWidth(Graphics2D g, Font font, String content) { + FontMetrics fm = g.getFontMetrics(font); + //获取字符串宽度 + return fm.stringWidth(content); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/JaxbUtil.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/JaxbUtil.java new file mode 100644 index 0000000..d1c91f4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/JaxbUtil.java @@ -0,0 +1,130 @@ +package com.ruoyi.util; + + +import javax.xml.bind.*; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.namespace.QName; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Collection; + + +/** + * xml转换工具类 + */ +public class JaxbUtil { + // 多线程安全的Context. + private JAXBContext jaxbContext; + + /** + * @param types 所有需要序列化的Root对象的类型. + */ + public JaxbUtil(Class... types) { + try { + jaxbContext = JAXBContext.newInstance(types); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * Java Object->Xml. + */ + public String toXml(Object root, String encoding) { + try { + StringWriter writer = new StringWriter(); + createMarshaller(encoding).marshal(root, writer); + return writer.toString(); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * Java Object->Xml, 特别支持对Root Element是Collection的情形. + */ + @SuppressWarnings("unchecked") + public String toXml(Collection root, String rootName, String encoding) { + try { + CollectionWrapper wrapper = new CollectionWrapper(); + wrapper.collection = root; + + JAXBElement wrapperElement = new JAXBElement( + new QName(rootName), CollectionWrapper.class, wrapper); + + StringWriter writer = new StringWriter(); + createMarshaller(encoding).marshal(wrapperElement, writer); + + return writer.toString(); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * Xml->Java Object. + */ + @SuppressWarnings("unchecked") + public T fromXml(String xml) { + try { + StringReader reader = new StringReader(xml); + return (T) createUnmarshaller().unmarshal(reader); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * Xml->Java Object, 支持大小写敏感或不敏感. + */ + @SuppressWarnings("unchecked") + public T fromXml(String xml, boolean caseSensitive) { + try { + String fromXml = xml; + if (!caseSensitive) + fromXml = xml.toLowerCase(); + StringReader reader = new StringReader(fromXml); + return (T) createUnmarshaller().unmarshal(reader); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * 创建Marshaller, 设定encoding(可为Null). + */ + public Marshaller createMarshaller(String encoding) { + try { + Marshaller marshaller = jaxbContext.createMarshaller(); + + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + if (!org.springframework.util.StringUtils.isEmpty(encoding)) { + marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding); + } + return marshaller; + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * 创建UnMarshaller. + */ + public Unmarshaller createUnmarshaller() { + try { + return jaxbContext.createUnmarshaller(); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + } + + /** + * 封装Root Element 是 Collection的情况. + */ + public static class CollectionWrapper { + @SuppressWarnings("unchecked") + @XmlAnyElement + protected Collection collection; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/MarketingConstant.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/MarketingConstant.java new file mode 100644 index 0000000..d1b21bd --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/MarketingConstant.java @@ -0,0 +1,76 @@ +package com.ruoyi.util; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by 魔金商城 on 17/6/8. + * 促销常量类 + */ +public interface MarketingConstant { + + /** + * 直降促销 + */ + String FALL_MARKETING = "1"; + + /** + * 满赠 + */ + String FULL_GIFT_MARKETING = "2"; + + /** + * 抢购促销 + */ + String PANIC_BUY_MARKETING = "3"; + + /** + * 满减促销 + */ + String FULL_DOWN_MARKETING = "4"; + + /** + * 满折促销 + */ + String FULL_DISCOUNT_MARKETING = "5"; + + /** + * 包邮促销 + */ + String FREE_SHIP_MARKETING = "6"; + + /** + * 定金预售 + */ + String DEPOSIT_PRE_SALE_MARKETING = "7"; + + /** + * 全款预售 + */ + String FULL_PRE_SALE_MARKETING = "8"; + + /** + * 试用促销 + */ + String TRY_MARKETING = "9"; + + /** + * 拼团促销 + */ + String GROUP_MARKETING = "10"; + + /** + * 众筹促销 + */ + String CROWD_FUNDING_MARKETING = "11"; + + /** + * 存在互斥的促销类型 + */ + List EXCLUSION_MARKETING_TYPES = Arrays.asList(PANIC_BUY_MARKETING, FALL_MARKETING, GROUP_MARKETING, DEPOSIT_PRE_SALE_MARKETING, FULL_PRE_SALE_MARKETING, TRY_MARKETING, CROWD_FUNDING_MARKETING); + + /** + * 批发商品互斥的促销类型 + */ + List BATCH_EXCLUSION_MARKETING_TYPES = Arrays.asList(PANIC_BUY_MARKETING, GROUP_MARKETING, DEPOSIT_PRE_SALE_MARKETING, FULL_PRE_SALE_MARKETING, TRY_MARKETING, CROWD_FUNDING_MARKETING); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/PageHelper.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/PageHelper.java new file mode 100644 index 0000000..6290a95 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/PageHelper.java @@ -0,0 +1,132 @@ +package com.ruoyi.util; + + +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Created by 魔金商城 on 17/5/2. + * 分页帮助类 + */ + +public class PageHelper { + + /** + * 当前查询的列表数据 + */ + private List list = new ArrayList<>(); + + /** + * 总计录数 + */ + private int rows; + + /** + * 每页显示记录数 默认10条记录 + */ + private int pageSize = 10; + + /** + * 当前页码 默认第一页 + */ + private int pageNum = 0; + + /** + * 构造分页对象 + * + * @param pageHelper 原始分页对象 + * @param function 转化函数 + * @return 返回新的返回对象 + */ + public static PageHelper buildByCopy(PageHelper pageHelper, Function function) { + PageHelper pageHelper1 = new PageHelper(); + pageHelper1.setRows(pageHelper.getRows()); + pageHelper1.setPageNum(pageHelper.getPageNum()); + pageHelper1.setPageSize(pageHelper.getPageSize()); + + if (!CollectionUtils.isEmpty(pageHelper.getList())) { + pageHelper1.setList((List) pageHelper.getList().stream().map(function).collect(Collectors.toList())); + } + return pageHelper1; + } + + /** + * 获取开始页 + * + * @return 返回开始页 + */ + public int getStartRowNum() { + return pageNum * pageSize; + } + + /** + * 设置当前的数据列表 + * + * @param list 当前数据 + * @return 返回当前对象 + */ + public PageHelper setListDates(List list) { + this.list = list; + return this; + } + + /** + * 获得设置通用分页 + * + * @param params 查询参数 + * @param rows 总记录数 + * @return 返回查询参数 + */ + public Map getQueryParams(Map params, int rows) { + this.setRows(rows); + params.put(CommonConstant.START_ROW_NUM, this.getStartRowNum()); + params.put(CommonConstant.PAGE_SIZE, this.getPageSize()); + return params; + } + + /** + * 获得总页数 + * + * @return 返回总的页数 此方法不能删除 + */ + public int getTotalPages() { + return rows % pageSize == 0 ? rows / pageSize : rows / pageSize + 1; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getRows() { + return rows; + } + + public void setRows(int rows) { + this.rows = rows; + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public int getPageNum() { + return pageNum; + } + + public void setPageNum(int pageNum) { + this.pageNum = pageNum; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/PosterUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/PosterUtils.java new file mode 100644 index 0000000..60c3fd2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/PosterUtils.java @@ -0,0 +1,358 @@ +package com.ruoyi.util; + +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.UUID; +import com.ruoyi.setting.bean.PaySetCommon; +import com.ruoyi.setting.service.ILsPaySettingService; +//import com.sun.image.codec.jpeg.JPEGCodec; +//import com.sun.image.codec.jpeg.JPEGImageEncoder; +import net.sf.json.JSONObject; +import org.apache.commons.io.FileUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicHeader; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Component +public class PosterUtils extends BaseEntity { + private static final String ACCESS_TOKEN = "微信小程序token"; + + private static final Logger logger = LoggerFactory.getLogger(PosterUtils.class); + + /** + * 注入redis服务 + */ + @Autowired + private RedisCache redisService; + + /** + * 注入支付设置服务 + */ + @Autowired + private ILsPaySettingService paySetService; + + private static PosterUtils posterUtils; + + @PostConstruct + public void init(){ + posterUtils = this; + posterUtils.redisService = this.redisService; + posterUtils.paySetService = this.paySetService; + } + + public static String createPoster(String posterTitle, String scene, String moneyReward, String petNameUrl, String qrpath, String bgpath, String sitepage) throws Exception { +// String resourcePath = PosterUtils.class.getResource("/image/").getPath(); + long nowTime = System.currentTimeMillis(); + /*String qrcodeName = UUID.randomUUID().toString().replace("-", ""); + String petUrlName = UUID.randomUUID().toString().replace("-", ""); + URL petUnitUrl = new URL(petNameUrl); + HttpURLConnection conn = (HttpURLConnection) petUnitUrl.openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(5 * 1000); + BufferedInputStream biss = new BufferedInputStream(conn.getInputStream()); + OutputStream outputStream = new FileOutputStream(new File(resourcePath + petUrlName + ".png")); + int lens; + byte[] arrs = new byte[1024]; + while ((lens = biss.read(arrs)) != -1) { + outputStream.write(arrs, 0, lens); + outputStream.flush(); + } + outputStream.close();*/ + PaySetCommon paySetCommon = posterUtils.paySetService.queryPaySet(); + //二维码图片 + String urlstr ="https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token="; +// String url = "http://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="; + URL getCodeUrl = new URL(urlstr + GetAccessToken(paySetCommon.getWechatAppletPaySet().getAppId(), paySetCommon.getWechatAppletPaySet().getAppSecret())); + HttpURLConnection httpURLConnection = (HttpURLConnection) getCodeUrl.openConnection(); + httpURLConnection.setRequestMethod("POST");// 提交模式 + httpURLConnection.setDoOutput(true); + httpURLConnection.setDoInput(true); + PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); + JSONObject paramJson = new JSONObject(); + paramJson.accumulate("scene", scene).accumulate("page", sitepage); + paramJson.put("auto_color", false); + JSONObject lineColor = new JSONObject(); + lineColor.put("r", 0); + lineColor.put("g", 0); + lineColor.put("b", 0); + paramJson.put("line_color", lineColor); + printWriter.write(paramJson.toString()); + printWriter.flush(); +// BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream()); + BufferedImage qrimg = ImageIO.read(httpURLConnection.getInputStream()); + + ImageIO.write(qrimg, "jpg", new File(qrpath)); + /*OutputStream ost = new FileOutputStream(new File(qrpath)); + int len; + byte[] arr = new byte[1024]; + while ((len = bis.read(arr)) != -1) { + ost.write(arr, 0, len); + ost.flush(); + } + ost.close();*/ + + //合成图片 + String title = posterTitle; + if (title.length() > 21) { + title = StringUtils.substring(title, 0, 21) + "..."; + } + //宠物图片文件 + File petImg = FileUtils.toFile(PosterUtils.class.getResource("/templates/posters/bg.jpg")); + //二维码图片文件 1 + File qrCodeImg = new File(qrpath); + //背景地址 + //为了方便演示放在resources中,可根据实际情况(上传后)将背景模板放入单独的资源文件夹或远程资源服务器 + URL url = PosterUtils.class.getResource("/templates/posters/bg.jpg"); + File fileBg = FileUtils.toFile(url); + //1、背景图片输入流 + FileInputStream fis = new FileInputStream(fileBg); + //2、背景图片对象 + Image srcImg = ImageIO.read(fis); + //3、创建画布,根据背景图片的宽高 + BufferedImage bufferedImage = new BufferedImage( + //宽度 + srcImg.getWidth(null), + //高度 + srcImg.getHeight(null), + //图片类型 + BufferedImage.TYPE_INT_RGB); + int width = bufferedImage.getWidth(); + int height = bufferedImage.getHeight(); + //4、得到2d画笔对象 + Graphics2D g = bufferedImage.createGraphics(); + // 设置对线段的锯齿状边缘处理 + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + //5、设置画布背景 + g.drawImage(srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); + //6、```````````开始作画``````````` + Font rewardFirstFont = new Font("PingFang SC Bold", Font.PLAIN, 24); + Font rewardLastFont = new Font("PingFang SC Bold", Font.PLAIN, 48); + int rewardFirstWidth = Graphics2DUtils.getStringWidth(g, rewardFirstFont, "赏金¥"); + int rewardLastWidth = Graphics2DUtils.getStringWidth(g, rewardLastFont, moneyReward); + //赏金内容 + Graphics2DUtils.drawString(g, Color.decode("#ffd434"), rewardFirstFont, "赏金¥", (width - rewardFirstWidth - rewardLastWidth) / 2, 550); + Graphics2DUtils.drawString(g, Color.decode("#ffd434"), rewardLastFont, moneyReward, (width - rewardLastWidth + rewardFirstWidth) / 2, 550); + //标题 + Graphics2DUtils.drawString(g, Color.decode("#323232"), new Font("PingFang SC Bold", Font.BOLD, 34), title, 0, 400, width, 12, 5, true); + //把宠物图片和二维码图片划入背景 + g.drawImage(ImageIO.read(petImg), 130, 90, 362, 250, null); + g.drawImage(ImageIO.read(qrCodeImg), 100, 700, 175, 175, null); + // ```````````结束作画``````````` + //7、处理画作 + g.dispose(); + //8、得到输出流 + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ImageIO.write(bufferedImage, "jpg", os); + //9、转成base64编码前端可以直接显示,也可转换成其它形式比如文件 + String encodeStr = Base64.getEncoder().encodeToString(os.toByteArray()); + //保存为图片文件 + FileUtils.writeByteArrayToFile(new File(bgpath), os.toByteArray()); + //10、关闭输入输出流 + fis.close(); + os.close(); + qrCodeImg.delete(); + petImg.delete(); + return encodeStr; + + } + + public static String GetAccessToken(String appId, String secret) throws ClientProtocolException, + IOException { + String access_token1 = posterUtils.redisService.getCacheObject("access_token"); + if(!StringUtils.isEmpty(access_token1)){ + return access_token1; + } + HttpGet httpGet = new HttpGet( + "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + + appId + "&secret=" + + secret ); + HttpClient httpClient = HttpClients.createDefault(); + HttpResponse res = httpClient.execute(httpGet); + HttpEntity entity = res.getEntity(); + String result = EntityUtils.toString(entity, "UTF-8"); + JSONObject jsons = JSONObject.fromObject(result); + String expires_in = jsons.getString("expires_in"); + + //缓存 + if(Integer.parseInt(expires_in)==7200){ + //ok + String access_token = jsons.getString("access_token"); + posterUtils.redisService.setCacheObject("access_token", access_token, 2, TimeUnit.HOURS); + return access_token; + }else{ + System.out.println("出错获取token失败!"); + return null; + } + } + +// 获取二维码 信息图片 + public static String GetPostUrl(String access_token,String id) throws Exception { + //String result = HttpRequest.sendPost("http://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+access_token, path); + System.out.println(id); + String url ="https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token="; + Map map = new HashMap(); + map.put("path", "pages/index/index?###="+id);//你二维码中跳向的地址 + map.put("width", "430");//图片大小 + JSONObject json = JSONObject.fromObject(map); + System.out.println(json); +// String res= HttpClientConnectionManager.httpPostWithJSON(url +// + access_token, json.toString(),id); +// System.out.println(res); + return null; + } + +// 返回图片保存 ,根据 id + public static String httpPostWithJSON(String url, String json,String id) + throws Exception { + String result = null; + DefaultHttpClient httpClient = new DefaultHttpClient(); + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json"); + + StringEntity se = new StringEntity(json); + se.setContentType("application/json"); + se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, + "UTF-8")); + httpPost.setEntity(se); + // httpClient.execute(httpPost); + HttpResponse response = httpClient.execute(httpPost); + if (response != null) { + HttpEntity resEntity = response.getEntity(); + if (resEntity != null) { + InputStream instreams = resEntity.getContent(); + String uploadSysUrl = "D://erweima/"; + File saveFile = new File(uploadSysUrl+id+".png"); + // 判断这个文件(saveFile)是否存在 + if (!saveFile.getParentFile().exists()) { + // 如果不存在就创建这个文件夹 + saveFile.getParentFile().mkdirs(); + } + saveToImgByInputStream(instreams, uploadSysUrl, id+".png"); + } + } + httpPost.abort(); + return result; + } + + /* @param instreams 二进制流 + * @param imgPath 图片的保存路径 + * @param imgName 图片的名称 + * @return + * 1:保存正常 + * 0:保存失败 + */ + public static int saveToImgByInputStream(InputStream instreams,String imgPath,String imgName){ + + int stateInt = 1; + if(instreams != null){ + try { + File file=new File(imgPath+imgName);//可以是任何图片格式.jpg,.png等 + FileOutputStream fos=new FileOutputStream(file); + + byte[] b = new byte[1024]; + int nRead = 0; + while ((nRead = instreams.read(b)) != -1) { + fos.write(b, 0, nRead); + } + fos.flush(); + fos.close(); + } catch (Exception e) { + stateInt = 0; + e.printStackTrace(); + } finally { + try { + instreams.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + return stateInt; + } + +// 然后是图片重合和增加字体 + public void changeImage(String imageurl,String i ){ + try { +// InputStream imagein = new FileInputStream( +// "D:/systemAvatarNew1.png"); +// InputStream imagein2 = new FileInputStream( +// "D:/qqfile/1852230493/FileRecv/4-02.png"); + InputStream imagein = new FileInputStream( + "D:/systemAvatarNew1.png"); + InputStream imagein2 = new FileInputStream( + imageurl); + + BufferedImage image = ImageIO.read(imagein); + BufferedImage image2 = ImageIO.read(imagein2); + //image2.getWidth() - 160, image2.getHeight() - 155, + Graphics g = image.getGraphics(); + g.drawImage(image2, 300, 230, 410,422,null); +// g.drawImage(image2, image.getWidth() - image2.getWidth() - 195, +// image.getHeight() - image2.getHeight() - 190, +// 340,349,null); + OutputStream outImage = new FileOutputStream( + imageurl); +// JPEGImageEncoder enc = JPEGCodec.createJPEGEncoder(outImage); +// enc.encode(image); + + + BufferedImage bimg=ImageIO.read(new FileInputStream(imageurl)); + //得到Graphics2D 对象 + Graphics2D g2d=(Graphics2D)bimg.getGraphics(); + //设置颜色和画笔粗细 + g2d.setColor(Color.black); + g2d.setStroke(new BasicStroke(5)); + //String pathString = "D://qqfile/1852230493/FileRecv/SourceHanSansCN-/SourceHanSansCN-Heavy.otf"; +// Font dynamicFont = Font.createFont(Font.TRUETYPE_FONT, new File(pathString)); + + g2d.setFont(new Font("微软雅黑", Font.PLAIN, 36)); + //g2d.setFont(Loadfont.loadFont(pathString, 45)); + //绘制图案或文字 + g2d.drawString("编号: "+i, 320, 700); + // g2d.drawString(i, 450, 700); + + ImageIO.write(bimg, "JPG",new FileOutputStream(imageurl)); + + + File fromFile = new File(imageurl); + File toFile = new File(imageurl); +// Image Image1 =new Image(); +// Image1.resizePng(fromFile, toFile, 1000, 1000, false); + + + + imagein.close(); + imagein2.close(); + outImage.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/QRCodeUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/QRCodeUtils.java new file mode 100644 index 0000000..79bf8a4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/QRCodeUtils.java @@ -0,0 +1,192 @@ +package com.ruoyi.util; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.common.BitMatrix; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Hashtable; + +/** + * Created by 魔金商城 on 17/3/13. + * 二维码生成器 + */ +public final class QRCodeUtils { + + /** + * 黑色 + */ + private static final int BLACK = 0xFF000000; + + /** + * 白色 + */ + private static final int WHITE = 0xFFFFFFFF; + + private QRCodeUtils() { + + } + + /** + * 创建二维码图片 + * + * @param url 链接地址 + * @param width 宽 + * @param height 高 + */ + public static void createQRImg(HttpServletResponse response, String url, Integer width, Integer height) { + OutputStream outputStream = null; + try { + //如果宽高没有赋值,则给一个默认值 + if (ObjectUtils.isEmpty(width)) { + width = 200; + } + if (ObjectUtils.isEmpty(height)) { + height = 200; + } + outputStream = response.getOutputStream(); + QRCodeUtils.createQrCode(url, width, height, "jpg", outputStream, null, null); + outputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + + /** + * 生成二维码 + * + * @param content 内容 + * @param width 宽 + * @param height 高 + */ + public static void createQrCode(String content, int width, int height, String format, OutputStream stream, String qrPath, String bgPath) throws Exception { + + Hashtable hints = new Hashtable<>(); + hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); + BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); + + BufferedImage bufferedImage = toBufferedImage(deleteWhite(bitMatrix)); + if(!StringUtils.isEmpty(bgPath)) { +// 如果指定了海报路径。则说明是分享商家 + BufferedImage poster = QRPostersUtil.drawImage2out(bgPath, bufferedImage, qrPath); + ImageIO.write(poster, format, stream); + } + else{ + if(!StringUtils.isEmpty(qrPath)){ + ImageIO.write(bufferedImage, format, new File(qrPath)); + } + ImageIO.write(bufferedImage, format, stream); + } + } + + /** + * 生成二维码 + * + * @param content 内容 + * @param width 宽 + * @param height 高 + * @param format 图片格式 + * @return 返回图片字节 + */ + public static byte[] createQrCode(String content, int width, int height, String format) throws Exception { + + Hashtable hints = new Hashtable<>(); + hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); + BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); + + return imageToBytes(toBufferedImage(bitMatrix), format); + } + + + /** + * 生成图片 + */ + private static BufferedImage toBufferedImage(BitMatrix matrix) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); + } + } + return image; + } + + + /** + * 去白边 + */ + private static BitMatrix deleteWhite(BitMatrix matrix) { + int[] rec = matrix.getEnclosingRectangle(); + int resWidth = rec[2] + 1; + int resHeight = rec[3] + 1; + + BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); + resMatrix.clear(); + for (int i = 0; i < resWidth; i++) { + for (int j = 0; j < resHeight; j++) { + if (matrix.get(i + rec[0], j + rec[1])) { + resMatrix.set(i, j); + } + } + } + + int width = resMatrix.getWidth(); + int height = resMatrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, resMatrix.get(x, y) ? 0 : 255); + } + } + + return resMatrix; + + } + + /** + * 转换BufferedImage 数据为byte数组 + * + * @param bImage + * @param format image格式字符串.如"gif","png" + * @return byte数组 + */ + public static byte[] imageToBytes(BufferedImage bImage, String format) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] bytes = null; + try { + ImageIO.write(bImage, format, out); + bytes = out.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return bytes; + } + + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/QRPostersUtil.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/QRPostersUtil.java new file mode 100644 index 0000000..c25f279 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/QRPostersUtil.java @@ -0,0 +1,362 @@ +package com.ruoyi.util; + + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Component; +import org.springframework.util.ResourceUtils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Random; + +/** + * 提供二维码生成和解析工具类 + * @author Administrator + * + */ +public class QRPostersUtil { + + private static final String CHARSET = "utf-8"; + private static final String FORMAT_NAME = "JPG"; + private static final int QRCODE_SIZE = 150; // 二维码尺寸,宽度和高度均是300 + private static final int WIDTH = 50; //LOGO宽度 + private static final int HEIGHT = 50; //LOGO高度 + + + /** + * 生成二维码的方法 + * @param content 目标url + * @param imgPath logo图片地址 + * @param needCompress 是否压缩logo + * @return 二维码图片 + * @throws Exception + */ + private static BufferedImage createImage(String content, String imgPath,boolean needCompress) throws Exception { + Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//指定二维码的纠错等级为高级 + hints.put(EncodeHintType.CHARACTER_SET, CHARSET);//指定字符编码为“utf-8” + hints.put(EncodeHintType.MARGIN, 1); //设置图片的边距 + //参数1:内容,目标url,参数2:固定写法,参数3:二维码的宽度,参数4:二维码的高度,参数5:二维码属性设置 + BitMatrix bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); + int width = bitMatrix.getWidth();//二维码的宽度 + int height = bitMatrix.getHeight();//二维码的高度 + BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);//生成的二维码image + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000: 0xFFFFFFFF); + } + } + if (imgPath == null || "".equals(imgPath)) {//logo图片地址为null或空时 + return image; //只返回二维码图片,无中间的logo + } + // 插入logo图片 参数1:二维码图片,参数2:logo图片地址,参数3:压缩图片 + QRPostersUtil.insertImage(image, imgPath, needCompress); + return image; + } + /** + * 插入logo图片 + * @param source 二维码图片 + * @param imgPath LOGO图片地址 + * @param needCompress 是否压缩 + * @throws Exception + */ + private static void insertImage(BufferedImage source, String imgPath,boolean needCompress) throws Exception { + + File file = new File(imgPath);//logo图片地址放入文件 + Image src; + if (!file.exists()) { + //通过网络路径获取 + InputStream inputStream=getImageStream(imgPath); + src = ImageIO.read(inputStream); + }else { + //本地路径获取 + src = ImageIO.read(new File(imgPath)); + } + int width = src.getWidth(null); + int height = src.getHeight(null); + if (needCompress) { // 压缩LOGO + if (width > WIDTH) { //如果上传logo宽 >60 + width = WIDTH; + } + if (height > HEIGHT) { //如果上传logo高>60 + height = HEIGHT; + } + Image image = src.getScaledInstance(width, height,Image.SCALE_SMOOTH); + BufferedImage tag = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB); + Graphics g = tag.getGraphics(); + g.drawImage(image, 0, 0, null); // 绘制缩小后的图 + g.dispose(); + src = image; + } + // 插入LOGO + Graphics2D graph = source.createGraphics(); + int x = (QRCODE_SIZE - width) / 2; + int y = (QRCODE_SIZE - height) / 2; + graph.drawImage(src, x, y, width, height, null); + Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); + graph.setStroke(new BasicStroke(3f)); + graph.draw(shape); + graph.dispose(); + } + /** + * 生成二维码(内嵌LOGO) + * @param content 内容 + * @param imgPath logo地址 + * @param destPath 存放目录 + * @param needCompress 是否压缩logo + * @throws Exception + */ + public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception { + BufferedImage image = QRPostersUtil.createImage(content, imgPath,needCompress); //生成二维码 + mkdirs(destPath); + String file = new Random().nextInt(99999) + ".jpg"; + ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file)); + } + /** + * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常) + * @param destPath 存放目录 + */ + public static void mkdirs(String destPath) { + File file = new File(destPath); + if (!file.exists() && !file.isDirectory()) { + file.mkdirs(); + } + } + + + /** + * 生成二维码(内嵌LOGO) + * + * @param content 内容 + * @param imgPath LOGO地址 + * @param output 输出流 + * @param needCompress 是否压缩LOGO + * @throws Exception + */ + public static void encode(String content, String imgPath,OutputStream output, boolean needCompress) throws Exception { + BufferedImage image = QRPostersUtil.createImage(content, imgPath,needCompress); + ImageIO.write(image, FORMAT_NAME, output); + } + /** + * 生成二维码 + * + * @param content 内容 + * @param output 输出流 + * @throws Exception + */ + public static void encode(String content, OutputStream output)throws Exception { + QRPostersUtil.encode(content, null, output, false); + } + + + /** + * 获取网络图片流 + * + * @param url + * @return + */ + public static InputStream getImageStream(String url) { + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setReadTimeout(5000); + connection.setConnectTimeout(5000); + connection.setRequestMethod("GET"); + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + InputStream inputStream = connection.getInputStream(); + return inputStream; + } + } catch (IOException e) { + System.out.println("获取网络图片出现异常,图片路径为:" + url); + e.printStackTrace(); + } + return null; + } + + + /** + *将头像,二维码和海报合成 + * @throws IOException + */ + public static void drawImage() throws IOException { + //海报图 + String backgroundImageUrl = "https://img.redocn.com/sheji/20170911/daxuexiaoyuanyinlejiegechangbisaihaibao_8694885.jpg"; + //二维码 + String qrCodeImageUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1553504957130&di=02fae20a5c0f885d52299b2b1d682c86&imgtype=0&src=http%3A%2F%2Fimg.atobo.com%2FProductImg%2FEWM%2FUWeb%2F3%2F2%2F1%2F3%2F061%2F3213061%2F1.gif"; + //头像 + String headUrl = "http://pic.51yuansu.com/pic3/cover/00/63/25/589bdedf5475d_610.jpg"; + + BufferedImage bgBufImage = ImageIO.read(new URL(backgroundImageUrl)); + Graphics2D bgBufImageGraphics = bgBufImage.createGraphics(); + + BufferedImage qrCodeImage = ImageIO.read(new URL(qrCodeImageUrl)); + BufferedImage headImage = ImageIO.read(new URL(headUrl)); + //设置圆形图片 + BufferedImage roundHeadImg = new BufferedImage(headImage.getWidth(), headImage.getHeight(), BufferedImage.TYPE_INT_RGB); + + Graphics2D roundHeadGraphics = roundHeadImg.createGraphics(); + Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, roundHeadImg.getWidth(), roundHeadImg.getHeight()); + roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + roundHeadImg = roundHeadGraphics.getDeviceConfiguration().createCompatibleImage(headImage.getWidth(), headImage.getHeight(), + Transparency.TRANSLUCENT); + roundHeadGraphics = roundHeadImg.createGraphics(); + // 使用 setRenderingHint 设置抗锯齿 + roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + roundHeadGraphics.setClip(shape); + roundHeadGraphics.drawImage(headImage, 0, 0, null); + roundHeadGraphics.dispose(); + + bgBufImageGraphics.drawImage(qrCodeImage,390, 200, qrCodeImage.getWidth(), qrCodeImage.getHeight(), null); + //bgBufImageGraphics.drawImage(roundHeadImg, 50, 100, HEAD_URL_WIDTH, HEAD_URL_HEIGHT, null); + bgBufImageGraphics.dispose(); + ImageIO.write(bgBufImage, "png", new File("C:\\Users\\Public\\Desktop\\demo2.png")); + System.out.printf("生成图片完成"); + + } + + /** + *将二维码和海报合成一张图片 + * @throws IOException + */ + public static void drawImage1(String backgroundImageUrl,BufferedImage qrCodeImage,String putImgPoster) throws IOException { + //这里对方法进行了修改直接把 BufferedImage qrCodeImage传入进来方便处理 也可以传入 String qrCodeImageUrl 图片网络路径 + BufferedImage bgBufImage = ImageIO.read(new URL(backgroundImageUrl)); + Graphics2D bgBufImageGraphics = bgBufImage.createGraphics(); + //BufferedImage qrCodeImage = ImageIO.read(new URL(qrCodeImageUrl)); + bgBufImageGraphics.drawImage(qrCodeImage,390, 200, qrCodeImage.getWidth(), qrCodeImage.getHeight(), null); + bgBufImageGraphics.dispose(); + ImageIO.write(bgBufImage, "png", new File(putImgPoster)); + System.out.printf("生成图片完成"); + } + + /** + *将二维码和海报合成一张图片 + * @param backgroundImageUrl 海报背景图片url。为空时。使用 templates\posters\bg.jpg + * @param qrCodeImage 二维码图片流 + * @param putImgPoster 海报保存地址 + * @throws IOException + */ + public static BufferedImage drawImage2out(String backgroundImageUrl,BufferedImage qrCodeImage,String putImgPoster) throws IOException { + //这里对方法进行了修改直接把 BufferedImage qrCodeImage传入进来方便处理 也可以传入 String qrCodeImageUrl 图片网络路径 +// InputStream resourceAsStream = QRPostersUtil.class.getClassLoader().getResourceAsStream("templates/posters/bg.png"); +// File bgPath = ResourceUtils.getFile("classpath:templates/posters/bg.png"); +// Resource resource = new ClassPathResource("templates/posters/bg.png"); +// Resource resource = new DefaultResourceLoader().getResource("templates/posters/bg.png"); +// ClassPathResource classPathResource = new ClassPathResource("templates/posters/bg.png"); + BufferedImage bgBufImage = null; + File f = new File(backgroundImageUrl); + + if(f.exists()){ + bgBufImage = ImageIO.read(f); + } + else { + bgBufImage = ImageIO.read(new URL(backgroundImageUrl)); + } + Graphics2D bgBufImageGraphics = bgBufImage.createGraphics(); + //BufferedImage qrCodeImage = ImageIO.read(new URL(qrCodeImageUrl)); + Font font6 = new Font("苹方-简", Font.BOLD, 28); + drawString(bgBufImageGraphics, font6, "sdafasdfasdfasd",bgBufImage.getTileWidth(), 20, 10, 2 , 2); + bgBufImageGraphics.drawImage(qrCodeImage,(bgBufImage.getWidth()-qrCodeImage.getWidth())/2, (bgBufImage.getHeight()-qrCodeImage.getHeight())/2, qrCodeImage.getWidth(), qrCodeImage.getHeight(), null); + bgBufImageGraphics.dispose(); + if(putImgPoster != null){ +// Resource outres = new ClassPathResource("templates/posters/posters.png"); + ImageIO.write(bgBufImage, "png", new File(putImgPoster)); + } + System.out.printf("生成图片完成"); + return bgBufImage; + } + + /** + * 文字超出限定长度自动换行 + * + * @param g 画布 + * @param font 字体样式 + * @param text 文字 + * @param widthLength 最大长度 (多少长度后需要换行) + * @param x 文字位置坐标 x + * @param y 文字位置坐标 Y + * @param yn 每次换行偏移多少pt + * showLine 显示行数 文字可能过多 我们只显示showLine行文字 + */ + private static int drawString(Graphics2D g, Font font, String text, int widthLength, int x, int y, int yn,int showLine) { + FontMetrics fg = g.getFontMetrics(font); + ArrayList ls = new ArrayList(); + getListText(fg, text, widthLength, ls); + g.setFont(font); + for (int i = 0; i < ls.size(); i++) { + if(i==showLine) { + break; + } + if (i == 0) { + g.drawString(ls.get(i), x, y); + } else { + g.drawString(ls.get(i), x, y + i*yn); + } + } + int height=fg.getHeight(); + if(ls.size()<=showLine) { + y=y+height*ls.size(); + }else { + y=y+height*showLine; + } + return y; + } + + /** + * 递归 切割字符串 + * @param fg + * @param text + * @param widthLength + * @param ls + */ + private static void getListText(FontMetrics fg, String text, int widthLength, ArrayList ls) { + String ba = text; + boolean b = true; + int i = 1; + while (b) { + if (fg.stringWidth(text) > widthLength) { + text = text.substring(0, text.length() - 1); + i++; + } else { + b = false; + } + } + if (i != 1) { + ls.add(ba.substring(0, ba.length() - i)); + getListText(fg, ba.substring(ba.length() - i), widthLength, ls); + } else { + ls.add(text); + } + } + + public static void main(String[] args) throws Exception{ +// 先生成二维码 + BufferedImage ti =createImage("xh6lSOzYdIMVanArR9AY0","https://b-ssl.duitang.com/uploads/item/201706/27/20170627012435_mJLiX.thumb.700_0.jpeg",true); + //输出文件 + File file = new File("E:\\123.jpg"); + ImageIO.write(ti, "jpg", file); +// drawImage(); + drawImage1("https://img.redocn.com/sheji/20170911/daxuexiaoyuanyinlejiegechangbisaihaibao_8694885.jpg",ti,"C:\\Users\\Public\\Desktop\\dome.jpg"); + } + + +} + diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/QqOssClient.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/QqOssClient.java new file mode 100644 index 0000000..85969ea --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/QqOssClient.java @@ -0,0 +1,366 @@ +package com.ruoyi.util; + + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.exception.CosClientException; +import com.qcloud.cos.exception.CosServiceException; +import com.qcloud.cos.model.*; +import com.qcloud.cos.region.Region; +import com.ruoyi.util.bean.OssYunConf; +import com.ruoyi.util.md5.MD5; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; +import java.util.List; + +/** + * @Author: SunJunxian + * @Date: 2018/12/17 + * @Description: java实现腾讯云存储服务(COSClient) + * @REGIONID 区域 + * @KEY 上传上云之后的名字 + * @KEY01 需要删除的文件 + */ +public class QqOssClient { + + + private static final String ACCESSKEY = "AKID187989o64Q4hjfItRjjplnu6HFwouHOEo7AOQgl"; + private static final String SECRETKEY = "ysBE66Bs64LZ56onV1KPIu3CUWWGfngdIhpiKn"; + private static final String BUCKETNAME = "wans76787hunfu-1301582899"; + private static final String APPID = "125178787827811"; + private static final String REGIONID = "ap-g798uangzhou"; + private static final String KEY = "MyFile1/989zookeeper-3.4.8.tar.gz"; + private static final String KEY01 = "MyFil989e1/1.jpg"; + + /** + * 上传腾讯云 + * + * @param file + * @param bytes 图片字节 + * @param type 上传的类型 0 图片 1 视频 + * @return 返回图片在又拍云的地址 + */ + public static String uploadToQqOss(OssYunConf cloudStorageConfig, MultipartFile file, byte[] bytes, String fileOriginName, String type) { + String url = null; + + String accessKey = cloudStorageConfig.getAccessKeyId(); + String secretKey = cloudStorageConfig.getAccessKeySecret(); + String bucket = cloudStorageConfig.getEndPoint(); + // bucket的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 + String bucketName = cloudStorageConfig.getBucketName(); + // 1 初始化用户身份信息(secretId, secretKey) + COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); + // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224 + ClientConfig clientConfig = new ClientConfig(new Region(bucket)); + // 3 生成cos客户端 + COSClient cosclient = new COSClient(cred, clientConfig); + // String suffix = fileOriginName.substring(fileOriginName.lastIndexOf(".")).toLowerCase(); + //获取腾讯云路径前缀 + String dir = cloudStorageConfig.getPrefix(); + + // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口 + // 大文件上传请参照 API 文档高级 API 上传 + File localFile = null; + try { + // 获取字符串的MD5结果,file.getBytes()--输入的字符串转换成字节数组 + String md5 = MD5.getMessageDigest(file.getBytes()); + String filePath = String.format("%1$s/%2$s%3$s", dir, md5, fileOriginName); + localFile = File.createTempFile("temp", null); + file.transferTo(localFile); + // 指定要上传到 COS 上的路径 + String key = filePath; + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile); + PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest); + String qCloudDomain = cloudStorageConfig.getAddress(); + url = String.format("%1$s/%2$s", qCloudDomain, filePath); + + } catch (IOException e) { + + } finally { + // 关闭客户端(关闭后台线程) + cosclient.shutdown(); + } + + return url; + } + + /** + * 初始化CosClient相关配置, appid、accessKey、secretKey、region + * + * @return + */ + public static COSClient getCosClient() { + // 1 初始化用户身份信息(secretId, secretKey) + COSCredentials cred = new BasicCOSCredentials(ACCESSKEY, SECRETKEY); + // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224 + // clientConfig中包含了设置region, https(默认http), 超时, 代理等set方法, 使用可参见源码或者接口文档FAQ中说明 + ClientConfig clientConfig = new ClientConfig(new Region(REGIONID)); + // 3 生成cos客户端 + COSClient cosClient = new COSClient(cred, clientConfig); + // bucket的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 + //String bucketName = BUCKETNAME; + return cosClient; + } + + /** + * 上传文件 + * + * @return //绝对路径和相对路径都OK + */ + public static String uploadFile() { +// File localFile = new File("E:\\software\\JavaProject\\demo\\demo20\\src\\main\\resources\\1.jpg"); + File localFile = new File("C:\\Users\\DEL\\Desktop\\pic\\logo.png"); + PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKETNAME, localFile.getName(), localFile); + + // 设置存储类型, 默认是标准(Standard), 低频(standard_ia),一般为标准的 + putObjectRequest.setStorageClass(StorageClass.Standard); + + COSClient cc = getCosClient(); + try { + PutObjectResult putObjectResult = cc.putObject(putObjectRequest); + // putobjectResult会返回文件的etag + String etag = putObjectResult.getETag(); + + System.out.println(etag); + } catch (CosServiceException e) { + e.printStackTrace(); + } catch (CosClientException e) { + e.printStackTrace(); + } + // 关闭客户端 + cc.shutdown(); + return null; + } + + /** + * 下载文件 + * + * @param bucketName + * @param key + * @return + */ + public static String downLoadFile(String bucketName, String key) { + File downFile = new File("E:\\software\\1.jpg"); + COSClient cc = getCosClient(); + GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key); + + ObjectMetadata downObjectMeta = cc.getObject(getObjectRequest, downFile); + cc.shutdown(); + String etag = downObjectMeta.getETag(); + return etag; + } + + /** + * 删除文件 + * + * @param bucketName + * @param key + */ + public static void deleteFile(String bucketName, String key) { + COSClient cc = getCosClient(); + try { + cc.deleteObject(bucketName, key); + } catch (CosClientException e) { + e.printStackTrace(); + } finally { + cc.shutdown(); + } + + } + + /** + * 创建桶 + * + * @param bucketName + * @return + * @throws CosClientException + * @throws CosServiceException + */ + public static Bucket createBucket(String bucketName) throws CosClientException, CosServiceException { + COSClient cc = getCosClient(); + Bucket bucket = null; + try { + bucket = cc.createBucket(bucketName); + } catch (CosClientException e) { + e.printStackTrace(); + } finally { + } + return bucket; + } + + ; + + public static String uploadToUpYunForBase64(OssYunConf cloudStorageConfig, InputStream inputStream, byte[] bytes, String fileOriginName, byte[] bytes1) { + String url = null; + + String accessKey = cloudStorageConfig.getAccessKeyId(); + String secretKey = cloudStorageConfig.getAccessKeySecret(); + String bucket = cloudStorageConfig.getEndPoint(); + // bucket的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 + String bucketName = cloudStorageConfig.getBucketName(); + // 1 初始化用户身份信息(secretId, secretKey) + COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); + // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224 + ClientConfig clientConfig = new ClientConfig(new Region(bucket)); + // 3 生成cos客户端 + COSClient cosclient = new COSClient(cred, clientConfig); + // String suffix = fileOriginName.substring(fileOriginName.lastIndexOf(".")).toLowerCase(); + //获取腾讯云路径前缀 + String dir = cloudStorageConfig.getPrefix(); + + // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口 + // 大文件上传请参照 API 文档高级 API 上传 + try { + // 获取字符串的MD5结果,file.getBytes()--输入的字符串转换成字节数组 + String md5 = MD5.getMessageDigest(bytes); + String filePath = String.format("%1$s/%2$s%3$s", dir, md5, fileOriginName); + + // 指定要上传到 COS 上的路径 + String key = filePath; + ObjectMetadata metadata = new ObjectMetadata(); + // metadata.setContentType("image/jpeg"); + String backUrl = ""; + metadata.setContentLength(bytes.length); + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, new ByteArrayInputStream(bytes), + metadata); + + // 设置存储类型, 默认是标准(Standard), 低频(standard_ia) + putObjectRequest.setStorageClass(StorageClass.Standard_IA); + COSClient cc = getCosClient(); + try { + PutObjectResult putObjectResult1 = cc.putObject(putObjectRequest); + // putobjectResult会返回文件的etag + backUrl = cloudStorageConfig.getAddress() + "/" + key; + return backUrl; + } catch (CosServiceException e) { + e.printStackTrace(); + } catch (CosClientException e) { + e.printStackTrace(); + } + // 关闭客户端 + cc.shutdown(); + + return backUrl; + + } catch (Exception e) { + + } finally { + // 关闭客户端(关闭后台线程) + cosclient.shutdown(); + } + + return url; + } + + /** + * 判断桶是否存在 + * + * @param bucketName + * @return + * @throws CosClientException + * @throws CosServiceException + */ + public static boolean doesBucketExist(String bucketName) throws CosClientException, CosServiceException { + COSClient cc = getCosClient(); + boolean bucketExistFlag = cc.doesBucketExist(bucketName); + return bucketExistFlag; + } + + ; + + /** + * 查看桶文件 + * + * @param bucketName + * @return + * @throws CosClientException + * @throws CosServiceException + */ + public static ObjectListing listObjects(String bucketName) throws CosClientException, CosServiceException { + COSClient cc = getCosClient(); + + // 获取 bucket 下成员(设置 delimiter) + ListObjectsRequest listObjectsRequest = new ListObjectsRequest(); + listObjectsRequest.setBucketName(bucketName); + // 设置 list 的 prefix, 表示 list 出来的文件 key 都是以这个 prefix 开始 + listObjectsRequest.setPrefix(""); + // 设置 delimiter 为/, 即获取的是直接成员,不包含目录下的递归子成员 + listObjectsRequest.setDelimiter("/"); + // 设置 marker, (marker 由上一次 list 获取到, 或者第一次 list marker 为空) + listObjectsRequest.setMarker(""); + // 设置最多 list 100 个成员,(如果不设置, 默认为 1000 个,最大允许一次 list 1000 个 key) + listObjectsRequest.setMaxKeys(100); + + ObjectListing objectListing = cc.listObjects(listObjectsRequest); + // 获取下次 list 的 marker + String nextMarker = objectListing.getNextMarker(); + // 判断是否已经 list 完, 如果 list 结束, 则 isTruncated 为 false, 否则为 true + boolean isTruncated = objectListing.isTruncated(); + List objectSummaries = objectListing.getObjectSummaries(); + for (COSObjectSummary cosObjectSummary : objectSummaries) { + // get file path + String key = cosObjectSummary.getKey(); + // get file length + long fileSize = cosObjectSummary.getSize(); + // get file etag + String eTag = cosObjectSummary.getETag(); + // get last modify time + Date lastModified = cosObjectSummary.getLastModified(); + // get file save type + String StorageClassStr = cosObjectSummary.getStorageClass(); + } + return objectListing; + } + + ; + + /** + * 查询一个 Bucket 所在的 Region。 + * + * @param bucketName + * @return + * @throws CosClientException + * @throws CosServiceException + */ + public static String getBucketLocation(String bucketName) throws CosClientException, CosServiceException { + COSClient cosClient = getCosClient(); + // bucket 的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 + String location = cosClient.getBucketLocation(bucketName); + return location; + } + + public static void main(String[] args) { + uploadFile(); +// downLoadFile(BUCKETNAME , KEY); + // deleteFile(BUCKETNAME , KEY01); +// createBucket("sunjunxian01-1251782781"); + //deleteBucket(); +// doesBucketExist("sunjunxian01-1251782781"); +// System.out.println(listObjects(BUCKETNAME)); + //System.out.println("BUCKETNAME的位置:" + getBucketLocation(BUCKETNAME)); + } + + /** + * 删除桶 + * + * @param bucketName + * @throws CosClientException + * @throws CosServiceException + */ + public void deleteBucket(String bucketName) throws CosClientException, CosServiceException { + COSClient cc = getCosClient(); + try { + cc.deleteBucket(bucketName); + } catch (CosClientException e) { + e.printStackTrace(); + } finally { + } + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/RandomMathLetter.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/RandomMathLetter.java new file mode 100644 index 0000000..a2fc8d3 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/RandomMathLetter.java @@ -0,0 +1,37 @@ +package com.ruoyi.util; + +import java.util.Random; + +/** + * 随机生成字母和数字组合 + * + * @author 魔金商城 on 2017/6/1. + */ +public class RandomMathLetter { + /** + * 产生随机字符串 + */ + private static Random randGen = null; + /** + * 数字和字母 + */ + private static char[] numbersAndLetters = null; + + /** + * 字符串 + */ + public static String randomString(int length) { + if (length < 1) { + return null; + } + if (randGen == null) { + randGen = new Random(); + numbersAndLetters = ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); + } + char[] randBuffer = new char[length]; + for (int i = 0; i < randBuffer.length; i++) { + randBuffer[i] = numbersAndLetters[randGen.nextInt(35)]; + } + return new String(randBuffer); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/RedisCacheErrorHandler.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/RedisCacheErrorHandler.java new file mode 100644 index 0000000..ed83962 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/RedisCacheErrorHandler.java @@ -0,0 +1,44 @@ +package com.ruoyi.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.Cache; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.stereotype.Service; + +/** + * Created by 魔金商城 on 18/2/5. + * redis 异常处理器 + */ +@Service +public class RedisCacheErrorHandler implements CacheErrorHandler { + + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(RedisCacheErrorHandler.class); + + @Override + public void handleCacheClearError(RuntimeException e, Cache cache) { + logger.error("handleCacheClearError", e); + } + + @Override + public void handleCacheGetError(RuntimeException e, Cache cache, Object o) { + logger.error("get from redis fail and cache:{} \r\n o:{}", cache, o); + logger.error("handleCacheGetError", e); + + } + + + @Override + public void handleCacheEvictError(RuntimeException e, Cache cache, Object o) { + logger.error("Evict from redis fail and cache:{} \r\n o:{}", cache, o); + logger.error("handleCacheEvictError", e); + } + + @Override + public void handleCachePutError(RuntimeException e, Cache cache, Object o, Object o1) { + logger.error("handleCachePutError", e); + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/SegchkWXPayConfigImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/SegchkWXPayConfigImpl.java new file mode 100644 index 0000000..1991448 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/SegchkWXPayConfigImpl.java @@ -0,0 +1,126 @@ +package com.ruoyi.util; + +import com.weixin.pay.WXPayConfig; +import com.weixin.pay.WXPayDomain; +import com.weixin.pay.constants.WXPayConstants; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +/** + * 测试/第二个微信支付实体的微信支付实现类 + * + * @author yclimb + * @date 2018/7/31 + */ +public class SegchkWXPayConfigImpl extends WXPayConfig { + + private byte[] certData; + private static SegchkWXPayConfigImpl INSTANCE; + + private String appId = WXPayConstants.APP_ID_XXX; + private String mchId = WXPayConstants.MCH_ID_XXX; + private String mchKey = WXPayConstants.API_KEY_XXX; + + private SegchkWXPayConfigImpl() throws Exception{ + + String certPath = WXPayConstants.APICLIENT_CERT_XXX; + File file = new File(certPath); + if(!file.exists()) + { + return; + } + InputStream certStream = new FileInputStream(file); + this.certData = new byte[(int) file.length()]; + certStream.read(this.certData); + certStream.close(); + } + + public static SegchkWXPayConfigImpl getInstance() throws Exception{ + if (INSTANCE == null) { + synchronized (SegchkWXPayConfigImpl.class) { + if (INSTANCE == null) { + INSTANCE = new SegchkWXPayConfigImpl(); + } + } + } + return INSTANCE; + } + + @Override + public String getAppID() { + return this.appId; + } + + @Override + public String getMchID() { + return this.mchId; + } + + @Override + public String getKey() { + return this.mchKey; + } + + @Override + public InputStream getCertStream() { + ByteArrayInputStream certBis; + certBis = new ByteArrayInputStream(this.certData); + return certBis; + } + + @Override + public int getHttpConnectTimeoutMs() { + return 2000; + } + + @Override + public int getHttpReadTimeoutMs() { + return 10000; + } + + @Override + public WXPayDomain getWXPayDomain() { + return WXPayDomainSimpleImpl.instance(); + } + + public String getPrimaryDomain() { + return "api.mch.weixin.qq.com"; + } + + public String getAlternateDomain() { + return "api2.mch.weixin.qq.com"; + } + + @Override + public int getReportWorkerNum() { + return 1; + } + + @Override + public int getReportBatchSize() { + return 2; + } + + public void setCertData(String certPath) throws Exception{ + File file = new File(certPath); + InputStream certStream = new FileInputStream(file); + this.certData = new byte[(int) file.length()]; + certStream.read(this.certData); + certStream.close(); + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + public void setMchKey(String mchKey) { + this.mchKey = mchKey; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/ShareCodeUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/ShareCodeUtils.java new file mode 100644 index 0000000..9586b29 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/ShareCodeUtils.java @@ -0,0 +1,64 @@ +package com.ruoyi.util; + +import java.util.Random; + +/** + * 邀请码生成器,算法原理:
    + * 1) 获取id: 1127738
    + * 2) 使用自定义进制转为:gpm6
    + * 3) 转为字符串,并在后面加'o'字符:gpm6o
    + * 4)在后面随机产生若干个随机数字字符:gpm6o7
    + * 转为自定义进制后就不会出现o这个字符,然后在后面加个'o',这样就能确定唯一性。最后在后面产生一些随机字符进行补全。
    + */ +public class ShareCodeUtils { + + /** + * 自定义进制(0,1没有加入,容易与o,l混淆) + */ + private static final char[] r = new char[]{'q', 'w', 'e', '8', 'a', 's', '2', 'd', 'z', 'x', '9', 'c', '7', 'p', '5', 'i', 'k', '3', 'm', 'j', 'u', 'f', 'r', '4', 'v', 'y', 'l', 't', 'n', '6', 'b', 'g', 'h'}; + + /** + * (不能与自定义进制有重复) + */ + private static final char b = 'o'; + + /** + * 进制长度 + */ + private static final int binLen = r.length; + + /** + * 序列最小长度 + */ + private static final int s = 6; + + /** + * 根据ID生成六位随机码 + * + * @param id ID + * @return 随机码 + */ + public static String toSerialCode(long id) { + char[] buf = new char[32]; + int charPos = 32; + + while ((id / binLen) > 0) { + int ind = (int) (id % binLen); + buf[--charPos] = r[ind]; + id /= binLen; + } + buf[--charPos] = r[(int) (id % binLen)]; + String str = new String(buf, charPos, (32 - charPos)); + // 不够长度的自动随机补全 + if (str.length() < s) { + StringBuilder sb = new StringBuilder(); + sb.append(b); + Random rnd = new Random(); + for (int i = 1; i < s - str.length(); i++) { + sb.append(r[rnd.nextInt(binLen)]); + } + str += sb.toString(); + } + return str; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/SmsUtil.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/SmsUtil.java new file mode 100644 index 0000000..704b03d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/SmsUtil.java @@ -0,0 +1,124 @@ +package com.ruoyi.util; + +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.MethodType; +import com.aliyuncs.profile.DefaultProfile; +import com.ruoyi.util.bean.RequestParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; + +/** + * 发送短信工具类 + * + * @author 魔金商城 on 2017/9/7. + */ +public class SmsUtil { + + private static final Logger logger = LoggerFactory.getLogger(SmsUtil.class); + + /** + * 发送短信-新 + * + * @param requestParam 请求中的参数实体类 + * @return 0 成功 1失败 + */ + public static int newSendSms(RequestParam requestParam) { + logger.info("newSendSms response info:{}", requestParam); + if (Objects.isNull(requestParam)) { + logger.info("newSendSms error due to requestParam is null"); + return 1; + } + //设置超时时间-可自行调整 + System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); + System.setProperty("sun.net.client.defaultReadTimeout", "10000"); + //初始化ascClient需要的几个参数 + final String product = "Dysmsapi";//短信API产品名称(短信产品名固定,无需修改) + final String domain = requestParam.getInterfaceUrl();//短信API产品域名(接口地址固定,无需修改) + //你的accessKeyId + final String accessKeyId = requestParam.getAccessKeyId(); + //你的accessKeySecret + final String accessKeySecret = requestParam.getAccessKeySecret(); + //组装请求对象 + SendSmsRequest sendSmsRequest = new SendSmsRequest(); + //使用post提交 + sendSmsRequest.setMethod(MethodType.POST); + //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式 + sendSmsRequest.setPhoneNumbers(requestParam.getPhoneNumbers()); + //必填:短信签名-可在短信控制台中找到 + sendSmsRequest.setSignName(requestParam.getSignName()); + //必填:短信模板-可在短信控制台中找到 + sendSmsRequest.setTemplateCode(requestParam.getTemplateCode()); + //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为(友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败) + sendSmsRequest.setTemplateParam("{\"code\":\"" + requestParam.getTemplateParam() + "\"}"); + //1.可选-上行短信扩展码(无特殊需求用户请忽略此字段):request.setSmsUpExtendCode("90997");//2.可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者:request.setOutId("yourOutId"); + //请求失败这里会抛ClientException异常 + SendSmsResponse sendSmsResponse; + try { + //初始化ascClient,暂时不支持多region + DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain); + sendSmsResponse = new DefaultAcsClient(DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret)).getAcsResponse(sendSmsRequest); + } catch (ClientException e) { + logger.error("newSendSms error{}:", e); + return 1; + } + logger.info("newSendSms response code:{} \r\n message:{}", sendSmsResponse.getCode(), sendSmsResponse.getMessage()); + return "OK".equals(sendSmsResponse.getCode()) ? 0 : 1; + } + + + /** + * 发送短信-新通用 + * + * @param requestParam 请求中的参数实体类 + * @return 0 成功 1失败 + */ + public static int newSendSmsCommon(RequestParam requestParam) { + logger.info("newSendSms response info:{}", requestParam); + if (Objects.isNull(requestParam)) { + logger.info("newSendSms error due to requestParam is null"); + return 1; + } + //设置超时时间-可自行调整 + System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); + System.setProperty("sun.net.client.defaultReadTimeout", "10000"); + //初始化ascClient需要的几个参数 + final String product = "Dysmsapi";//短信API产品名称(短信产品名固定,无需修改) + final String domain = requestParam.getInterfaceUrl();//短信API产品域名(接口地址固定,无需修改) + //你的accessKeyId + final String accessKeyId = requestParam.getAccessKeyId(); + //你的accessKeySecret + final String accessKeySecret = requestParam.getAccessKeySecret(); + //组装请求对象 + SendSmsRequest sendSmsRequest = new SendSmsRequest(); + //使用post提交 + sendSmsRequest.setMethod(MethodType.POST); + //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式 + sendSmsRequest.setPhoneNumbers(requestParam.getPhoneNumbers()); + //必填:短信签名-可在短信控制台中找到 + sendSmsRequest.setSignName(requestParam.getSignName()); + //必填:短信模板-可在短信控制台中找到 + sendSmsRequest.setTemplateCode(requestParam.getTemplateCode()); + //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为(友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败) + sendSmsRequest.setTemplateParam(requestParam.getSmsParamString()); + //1.可选-上行短信扩展码(无特殊需求用户请忽略此字段):request.setSmsUpExtendCode("90997");//2.可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者:request.setOutId("yourOutId"); + //请求失败这里会抛ClientException异常 + SendSmsResponse sendSmsResponse; + try { + //初始化ascClient,暂时不支持多region + DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain); + sendSmsResponse = new DefaultAcsClient(DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret)).getAcsResponse(sendSmsRequest); + } catch (ClientException e) { + logger.error("newSendSms error{}:", e); + return 1; + } + logger.info("newSendSms response code:{} \r\n message:{}", sendSmsResponse.getCode(), sendSmsResponse.getMessage()); + return "OK".equals(sendSmsResponse.getCode()) ? 0 : 1; + } + + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/SnowflakeIdWorker.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/SnowflakeIdWorker.java new file mode 100644 index 0000000..7100e4f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/SnowflakeIdWorker.java @@ -0,0 +1,171 @@ +package com.ruoyi.util; + + +/** + * Created by 魔金商城 on 17/11/02. + *

    + * Twitter_Snowflake
    + * SnowFlake的结构如下(每部分用-分开):
    + * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
    + * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
    + * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) + * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
    + * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
    + * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
    + * 加起来刚好64位,为一个Long型。
    + * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 + */ +public class SnowflakeIdWorker { + /** + * 开始时间截 (2015-01-01) + */ + private final long twepoch = 1420041600000L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long datacenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private long workerId; + + /** + * 数据中心ID(0~31) + */ + private long datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + //==============================Constructors===================================== + + /** + * 构造函数 + * + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeIdWorker(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/ThreadTask.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/ThreadTask.java new file mode 100644 index 0000000..4893cb6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/ThreadTask.java @@ -0,0 +1,33 @@ +package com.ruoyi.util; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by 魔金商城 on 17/6/20. + * 线程池 + */ +public class ThreadTask { + + private static final ThreadTask threadTask = new ThreadTask(); + /** + * 固定线程池 + */ + private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + + private ThreadTask() { + } + + public static ThreadTask getInstance() { + return threadTask; + } + + /** + * 加入线程池执行 + * + * @param runnable 执行线程 + */ + public void addTask(Runnable runnable) { + executorService.execute(runnable); + } +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/UnionPayUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/UnionPayUtils.java new file mode 100644 index 0000000..e69de29 diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/VerifyCodeUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/VerifyCodeUtils.java new file mode 100644 index 0000000..3701ce3 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/VerifyCodeUtils.java @@ -0,0 +1,202 @@ +package com.ruoyi.util; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Random; + +/** + * 验证码工具类 + * + * @author ruoyi + */ +public class VerifyCodeUtils { + // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 + public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; + + private static Random random = new SecureRandom(); + + /** + * 使用系统默认字符源生成验证码 + * + * @param verifySize 验证码长度 + * @return + */ + public static String generateVerifyCode(int verifySize) { + return generateVerifyCode(verifySize, VERIFY_CODES); + } + + /** + * 使用指定源生成验证码 + * + * @param verifySize 验证码长度 + * @param sources 验证码字符源 + * @return + */ + public static String generateVerifyCode(int verifySize, String sources) { + if (sources == null || sources.length() == 0) { + sources = VERIFY_CODES; + } + int codesLen = sources.length(); + Random rand = new Random(System.currentTimeMillis()); + StringBuilder verifyCode = new StringBuilder(verifySize); + for (int i = 0; i < verifySize; i++) { + verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1))); + } + return verifyCode.toString(); + } + + /** + * 输出指定验证码图片流 + * + * @param w + * @param h + * @param os + * @param code + * @throws IOException + */ + public static void outputImage(int w, int h, OutputStream os, String code) throws IOException { + int verifySize = code.length(); + BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Random rand = new Random(); + Graphics2D g2 = image.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color[] colors = new Color[5]; + Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, + Color.ORANGE, Color.PINK, Color.YELLOW}; + float[] fractions = new float[colors.length]; + for (int i = 0; i < colors.length; i++) { + colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; + fractions[i] = rand.nextFloat(); + } + Arrays.sort(fractions); + + g2.setColor(Color.GRAY);// 设置边框色 + g2.fillRect(0, 0, w, h); + + Color c = getRandColor(200, 250); + g2.setColor(c);// 设置背景色 + g2.fillRect(0, 2, w, h - 4); + + // 绘制干扰线 + Random random = new Random(); + g2.setColor(getRandColor(160, 200));// 设置线条的颜色 + for (int i = 0; i < 20; i++) { + int x = random.nextInt(w - 1); + int y = random.nextInt(h - 1); + int xl = random.nextInt(6) + 1; + int yl = random.nextInt(12) + 1; + g2.drawLine(x, y, x + xl + 40, y + yl + 20); + } + + // 添加噪点 + float yawpRate = 0.05f;// 噪声率 + int area = (int) (yawpRate * w * h); + for (int i = 0; i < area; i++) { + int x = random.nextInt(w); + int y = random.nextInt(h); + int rgb = getRandomIntColor(); + image.setRGB(x, y, rgb); + } + + shear(g2, w, h, c);// 使图片扭曲 + + g2.setColor(getRandColor(100, 160)); + int fontSize = h - 4; + Font font = new Font("Algerian", Font.ITALIC, fontSize); + g2.setFont(font); + char[] chars = code.toCharArray(); + for (int i = 0; i < verifySize; i++) { + AffineTransform affine = new AffineTransform(); + affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), + (w / verifySize) * i + fontSize / 2, h / 2); + g2.setTransform(affine); + g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); + } + + g2.dispose(); + ImageIO.write(image, "jpg", os); + } + + private static Color getRandColor(int fc, int bc) { + if (fc > 255) { + fc = 255; + } + if (bc > 255) { + bc = 255; + } + int r = fc + random.nextInt(bc - fc); + int g = fc + random.nextInt(bc - fc); + int b = fc + random.nextInt(bc - fc); + return new Color(r, g, b); + } + + private static int getRandomIntColor() { + int[] rgb = getRandomRgb(); + int color = 0; + for (int c : rgb) { + color = color << 8; + color = color | c; + } + return color; + } + + private static int[] getRandomRgb() { + int[] rgb = new int[3]; + for (int i = 0; i < 3; i++) { + rgb[i] = random.nextInt(255); + } + return rgb; + } + + private static void shear(Graphics g, int w1, int h1, Color color) { + shearX(g, w1, h1, color); + shearY(g, w1, h1, color); + } + + private static void shearX(Graphics g, int w1, int h1, Color color) { + + int period = random.nextInt(2); + + boolean borderGap = true; + int frames = 1; + int phase = random.nextInt(2); + + for (int i = 0; i < h1; i++) { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); + g.copyArea(0, i, w1, 1, (int) d, 0); + if (borderGap) { + g.setColor(color); + g.drawLine((int) d, i, 0, i); + g.drawLine((int) d + w1, i, w1, i); + } + } + + } + + private static void shearY(Graphics g, int w1, int h1, Color color) { + + int period = random.nextInt(40) + 10; // 50; + + boolean borderGap = true; + int frames = 20; + int phase = 7; + for (int i = 0; i < w1; i++) { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); + g.copyArea(i, 0, 1, h1, 0, (int) d); + if (borderGap) { + g.setColor(color); + g.drawLine(i, (int) d, i, 0); + g.drawLine(i, (int) d + h1, i, h1); + } + + } + } +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WXPayDomainSimpleImpl.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WXPayDomainSimpleImpl.java new file mode 100644 index 0000000..bd15eac --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WXPayDomainSimpleImpl.java @@ -0,0 +1,120 @@ +package com.ruoyi.util; + +import com.weixin.pay.WXPayConfig; +import com.weixin.pay.WXPayDomain; +import com.weixin.pay.constants.WXPayConstants; + +import org.apache.http.conn.ConnectTimeoutException; + +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; + +/** + * 微信支付域名实现类(官方简单版) + * + * @author yclimb + * @date 2018/8/17 + */ +public class WXPayDomainSimpleImpl implements WXPayDomain { + private WXPayDomainSimpleImpl() { + } + + private static class WxpayDomainHolder { + private static WXPayDomain holder = new WXPayDomainSimpleImpl(); + } + + public static WXPayDomain instance() { + return WxpayDomainHolder.holder; + } + + @Override + public synchronized void report(final String domain, long elapsedTimeMillis, final Exception ex) { + DomainStatics info = domainData.get(domain); + if (info == null) { + info = new DomainStatics(domain); + domainData.put(domain, info); + } + + // success + if (ex == null) { + if (info.succCount >= 2) { + // continue succ, clear error count + info.connectTimeoutCount = info.dnsErrorCount = info.otherErrorCount = 0; + } else { + ++info.succCount; + } + } else if (ex instanceof ConnectTimeoutException) { + info.succCount = info.dnsErrorCount = 0; + ++info.connectTimeoutCount; + } else if (ex instanceof UnknownHostException) { + info.succCount = 0; + ++info.dnsErrorCount; + } else { + info.succCount = 0; + ++info.otherErrorCount; + } + } + + @Override + public synchronized DomainInfo getDomain(final WXPayConfig config) { + DomainStatics primaryDomain = domainData.get(WXPayConstants.DOMAIN_API); + if (primaryDomain == null || + primaryDomain.isGood()) { + return new DomainInfo(WXPayConstants.DOMAIN_API, true); + } + + long now = System.currentTimeMillis(); + if (switchToAlternateDomainTime == 0) { + // first switch + switchToAlternateDomainTime = now; + return new DomainInfo(WXPayConstants.DOMAIN_API2, false); + } else if (now - switchToAlternateDomainTime < MIN_SWITCH_PRIMARY_MSEC) { + DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2); + if (alternateDomain == null || + alternateDomain.isGood() || + alternateDomain.badCount() < primaryDomain.badCount()) { + return new DomainInfo(WXPayConstants.DOMAIN_API2, false); + } else { + return new DomainInfo(WXPayConstants.DOMAIN_API, true); + } + } else { //force switch back + switchToAlternateDomainTime = 0; + primaryDomain.resetCount(); + DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2); + if (alternateDomain != null) { + alternateDomain.resetCount(); + } + return new DomainInfo(WXPayConstants.DOMAIN_API, true); + } + } + + static class DomainStatics { + final String domain; + int succCount = 0; + int connectTimeoutCount = 0; + int dnsErrorCount = 0; + int otherErrorCount = 0; + + DomainStatics(String domain) { + this.domain = domain; + } + + void resetCount() { + succCount = connectTimeoutCount = dnsErrorCount = otherErrorCount = 0; + } + + boolean isGood() { + return connectTimeoutCount <= 2 && dnsErrorCount <= 2; + } + + int badCount() { + return connectTimeoutCount + dnsErrorCount * 5 + otherErrorCount / 4; + } + } + + // 3 minutes + private final int MIN_SWITCH_PRIMARY_MSEC = 3 * 60 * 1000; + private long switchToAlternateDomainTime = 0; + private Map domainData = new HashMap(); +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletLoginResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletLoginResponse.java new file mode 100644 index 0000000..374291e --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletLoginResponse.java @@ -0,0 +1,132 @@ +package com.ruoyi.util; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +/** + * 微信小程序登录返回 + * + * @author SK + * @since 2018/6/13 + */ +public class WeChatAppletLoginResponse { + /** + * 用户唯一标志 + */ + @JSONField(name = "openid") + private String openid; + + /** + * 会话密钥 + */ + @JSONField(name = "session_key") + private String session_key; + + /** + * 联合登录id 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + */ + @JSONField(name = "unionid") + private String unionid; + + /** + * 错误码(出错时返回) + */ + @JSONField(name = "errcode") + private Integer errcode; + + /** + * 错误信息(出错时返回) + */ + @JSONField(name = "errmsg") + private String errmsg; + + public WeChatAppletLoginResponse(String openid, String session_key, String unionid) { + this.openid = openid; + this.session_key = session_key; + this.unionid = unionid; + } + + /** + * 转换为字符串 + */ + @Override + public String toString() { + return JSONObject.toJSONString(this); + } + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return this.errcode != null && this.errcode != 0 ; + } + + /** + * 返回错误码解释 + */ + @JsonIgnore + public String errCodeDesc() { + switch (this.errcode){ + case -1: return "系统繁忙,此时请开发者稍候再试"; + case 0: return "请求成功"; + case 40029: return "code 无效"; + case 45011: return "频率限制,每个用户每分钟100次"; + case 40226: return "高风险等级用户,小程序登录拦截 "; + default: return "未知错误"; + } + } + + + /** + * 判断是否有unionId + * + * @return 有返回true, 否则返回false + */ + public boolean hasUnionId() { + return !StringUtils.isEmpty(unionid); + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSession_key() { + return session_key; + } + + public void setSession_key(String session_key) { + this.session_key = session_key; + } + + public String getUnionid() { + return unionid; + } + + public void setUnionid(String unionid) { + this.unionid = unionid; + } + + public Integer getErrcode() { + return errcode; + } + + public void setErrcode(Integer errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUserInfo.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUserInfo.java new file mode 100644 index 0000000..c50fe05 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUserInfo.java @@ -0,0 +1,101 @@ +package com.ruoyi.util; + + +/** + * 微信小程序用户信息实体 + * + * @author SK + * @since 2018/6/13 + */ +public class WeChatAppletUserInfo { + + /** + * 错误信息 + */ + private String errMsg; + + /** + * 包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法 + */ + private String encryptedData; + + /** + * 加密算法的初始向量,详细见加密数据解密算法 + */ + private String iv; + + /** + * 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,参考文档 + */ + private String signature; + + /** + * 不包括敏感信息的原始数据字符串,用于计算签名。 + */ + private String rawData; + + /** + * 联合登录id 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + */ + private String unionId; + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public String getEncryptedData() { + return encryptedData; + } + + public void setEncryptedData(String encryptedData) { + this.encryptedData = encryptedData; + } + + public String getIv() { + return iv; + } + + public void setIv(String iv) { + this.iv = iv; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public String getRawData() { + return rawData; + } + + public void setRawData(String rawData) { + this.rawData = rawData; + } + + public String getUnionId() { + return unionId; + } + + public void setUnionId(String unionId) { + this.unionId = unionId; + } + + @Override + public String toString() { + return "WeChatAppletUserInfo{" + + "errMsg='" + errMsg + '\'' + + ", encryptedData='" + encryptedData + '\'' + + ", iv='" + iv + '\'' + + ", signature='" + signature + '\'' + + ", rawData='" + rawData + '\'' + + ", unionId='" + unionId + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUtils.java new file mode 100644 index 0000000..558d5e2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WeChatAppletUtils.java @@ -0,0 +1,311 @@ +package com.ruoyi.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.util.WeChatAppletLoginResponse; +import com.ruoyi.util.WeChatAppletUserInfo; +import com.ruoyi.util.WechatSetting; +import com.ruoyi.util.bean.SegUserProfile; +import com.ruoyi.util.bean.UserInfoProfile; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Objects; + +/** + * 微信小程序工具类 + * + * @author SK + * @since 2018/6/13 + */ +public class WeChatAppletUtils { + private static final Logger logger = LoggerFactory.getLogger(WeChatAppletUtils.class); + /** + * 获取登录信息地址 + */ + private final static String GET_LOGIN_INFO_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; + /** + * 新的获取登录信息地址 + */ + private final static String GET_LOGIN_INFO_URL1 = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; + /** + * 获取微信小程序access_token地址(参数为 appid 和 secret) + */ + private final static String GET_WECHAT_APPLET_ACCESS_TOKEN_ = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + /** + * 获取微信小程序分享码请求地址 + */ + private final static String GET_WECHAT_APPLET_SHARE_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"; + /** + * 获取微信小程序直播房间列表地址 + */ + private final static String GET_WECHAT_APPLET_LIVE_PLAYER_LIST_URL = "http://api.weixin.qq.com/wxa/business/getliveinfo?access_token=%s"; + + private WeChatAppletUtils() { + } + + /** + * 获取登录信息 + * + * @param code 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息 + * @param wechatSetting 微信设置 + * @return 微信小程序登录返回实体 + */ + public static WeChatAppletLoginResponse getLoginInfo(String code, WechatSetting wechatSetting) { + logger.debug("getLoginInfo and code:{} \r\n wechatSetting:{}", code, wechatSetting); + /*WeChatAppletLoginResponse weChatAppletLoginResponse = wechatSetting.getType() == 999999 + ? new WeChatAppletLoginResponse(code, code, code) + : JSON.parseObject(WechatUtils.executeHttpGet(String.format(GET_LOGIN_INFO_URL, wechatSetting.getAppId(), wechatSetting.getAppSecret(), code)), WeChatAppletLoginResponse.class);*/ +// WeChatAppletLoginResponse weChatAppletLoginResponse = null; + String s = WechatUtils.executeHttpGet(String.format(GET_LOGIN_INFO_URL, wechatSetting.getAppId(), wechatSetting.getAppSecret(), code)); + logger.warn("getLoginInfo res: ({})", s); + WeChatAppletLoginResponse weChatAppletLoginResponse = JSONObject.parseObject(s, WeChatAppletLoginResponse.class); +// logger.warn("getLoginInfo get WeChatAppletLoginResponse: {}", weChatAppletLoginResponse.toString()); + if (Objects.isNull(weChatAppletLoginResponse)) { + logger.error("getLoginInfo fail : weChatAppletLoginResponse is null"); + return null; + } + if (weChatAppletLoginResponse.isError()) { + logger.debug("getLoginInfo fail and errorMsg:({}) errCode:({})", weChatAppletLoginResponse.getErrmsg(), weChatAppletLoginResponse.getErrcode()); + return null; + } + logger.debug("getLoginInfo get user wechat info: {}", weChatAppletLoginResponse.toString()); + return weChatAppletLoginResponse; + } + + /** + * 根据用户信息UserProfile获取用户信息 + * + * @param sessionKey 会话密钥 + * @param segUserProfile 微信小程序用户信息实体 + * @return 用户unionId + */ + public static String getUserInfoFromUserProfile(String sessionKey, SegUserProfile segUserProfile) { + logger.debug("getUserInfoFromUserProfile and sessionKey:{} \r\n weChatAppletUserInfo:{}", sessionKey, segUserProfile); + String unionId = null; + if (Objects.isNull(segUserProfile)) { + logger.error("getUserInfoFromUserProfile fail:weChatAppletUserInfo is null "); + return null; + } + // 被加密的数据 + byte[] dataByte = Base64.decodeBase64(segUserProfile.getEncryptedData()); + // 加密秘钥 + byte[] aeskey = Base64.decodeBase64(sessionKey); + // 偏移量 + byte[] ivByte = Base64.decodeBase64(segUserProfile.getIv()); + + try { + /*int base = 16; + if (aeskey.length % base != 0) { + int groups = aeskey.length / base + (aeskey.length % base != 0 ? 1 : 0); + byte[] temp = new byte[groups * base]; + Arrays.fill(temp, (byte) 0); + System.arraycopy(aeskey, 0, temp, 0, aeskey.length); + aeskey = temp; + }*/ + byte[] resultByte = AesUtils.getInstance().decrypt(dataByte, aeskey, ivByte); + if (!ObjectUtils.isEmpty(resultByte)) { + String result = new String(resultByte, "UTF-8"); + return JSONObject.parseObject(result).toJSONString(); + } + return null; + } catch (Exception e) { + e.printStackTrace(); + } + return unionId; + } + + /** + * 根据用户信息获取unionId + * + * @param sessionKey 会话密钥 + * @param weChatAppletUserInfo 微信小程序用户信息实体 + * @return 用户unionId + */ + public static String getUnionIdFromUserInfo(String sessionKey, WeChatAppletUserInfo weChatAppletUserInfo) { + logger.debug("getUnionIdFromUserInfo and sessionKey:{} \r\n weChatAppletUserInfo:{}", sessionKey, weChatAppletUserInfo); + String unionId = null; + if (Objects.isNull(weChatAppletUserInfo)) { + logger.error("getUnionIdFromUserInfo fail:weChatAppletUserInfo is null "); + return null; + } + // 被加密的数据 + byte[] dataByte = Base64.decodeBase64(weChatAppletUserInfo.getEncryptedData()); + // 加密秘钥 + byte[] aeskey = Base64.decodeBase64(sessionKey); + // 偏移量 + byte[] ivByte = Base64.decodeBase64(weChatAppletUserInfo.getIv()); + + try { + byte[] resultByte = AesUtils.getInstance().decrypt(dataByte, aeskey, ivByte); + String userInfo = new String(resultByte, "UTF-8"); + unionId = JSON.parseObject(userInfo).getString("unionId"); + } catch (Exception e) { + e.printStackTrace(); + } + return unionId; + } + + /** + * 获取微信小程序access_token(有效期两小时) + * + * @param wechatSetting 微信设置实体 + * @return 微信小程序access_token + */ + public static String getAccessToken(WechatSetting wechatSetting) { + logger.debug("getAccessToken and wechatSetting:{} ", wechatSetting); + String accessTokenForShareUrl = String.format(GET_WECHAT_APPLET_ACCESS_TOKEN_, wechatSetting.getAppId(), wechatSetting.getAppSecret()); + JSONObject res = JSON.parseObject(CustomHttpUtils.doGet(accessTokenForShareUrl)); + if (!StringUtils.isEmpty(res.getString("errcode"))) { + if (!StringUtils.isEmpty(res.getString("errmsg"))) { + logger.error("getAccessToken Fail and errmsg:{}", res.getString("errmsg")); + } + return null; + } else { + return res.getString("access_token"); + } + } + + /** + * 获取json参数post请求返回值(微信小程序码) + * + * @param url 请求地址 + * @param jsonString 请求参数 + * @return 请求返回(ByteArrayInputStream格式,访问数组的字节输入流) + */ + public static ByteArrayInputStream getJsonRequestResult(String url, String jsonString) { + logger.debug("getWeChatAppletCode and url :{} \r\n jsonString :{} ", url, jsonString); + String result = null; + InputStream inputStream = null; + ByteArrayInputStream byteArrayInputStream = null; + BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + HttpPost httpRequest = new HttpPost(url); + httpRequest.setHeader("Content-type", "application/json; charset=utf-8"); + StringEntity requestParam = new StringEntity(jsonString, "UTF-8"); + requestParam.setContentType("application/json"); + try { + httpRequest.setEntity(requestParam); + HttpResponse response = httpClient.execute(httpRequest); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + HttpEntity entity = response.getEntity(); + inputStream = entity.getContent(); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + // 创建一个Buffer字符串 + byte[] buffer = new byte[1024]; + // 每次读取的字符串长度,如果为-1,代表全部读取完毕 + int len = 0; + // 使用一个输入流从buffer里把数据读取出来 + while ((len = inputStream.read(buffer)) != -1) { + // 用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度 + outStream.write(buffer, 0, len); + } + // 关闭输入流 + inputStream.close(); + // 把outStream里的数据写入内存 + byteArrayInputStream = new ByteArrayInputStream(outStream.toByteArray()); + } + } catch (IOException e) { + e.printStackTrace(); + logger.error(e.getMessage()); + } + logger.debug("getJsonRequestResult and result:{}", result == null ? "" : result); + return byteArrayInputStream; + } + + /** + * 数组的字节输入流转化为base64字符串 + * + * @param inputStream 输入流 + * @return base64字符串 + */ + public static String getBase64FromInputStream(InputStream inputStream) { + // 将图片文件转化为字节数组字符串,并对其进行Base64编码处理 + byte[] data = null; + // 读取图片字节数组 + try { + if (Objects.isNull(inputStream) || inputStream.available() <= 200) { + logger.error("getBase64FromInputStream fail due to inputStream is null"); + return null; + } + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + byte[] buff = new byte[100]; + int rc = 0; + while ((rc = inputStream.read(buff, 0, 100)) > 0) { + swapStream.write(buff, 0, rc); + } + data = swapStream.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return java.util.Base64.getEncoder().encodeToString(data); + } + + /** + * 获取微信小程序分享码请求地址 + * + * @param accessToken 微信小程序access_token + * @return 微信小程序分享码请求地址 + */ + public static String getWeChatAppletShareCodeUrl(String accessToken) { + if (StringUtils.isEmpty(accessToken)) { + logger.error("getWeChatAppletShareCodeUrl fail due to accessToken is null"); + return null; + } + return String.format(GET_WECHAT_APPLET_SHARE_CODE_URL, accessToken); + } + + /** + * 获取微信小程序直播列表地址 + * + * @param accessToken 微信小程序access_token + * @return 微信小程序直播列表地址 + */ + public static String getWeChatAppletLivePlayerListUrl(String accessToken) { + if (StringUtils.isEmpty(accessToken)) { + logger.error("getWeChatAppletLivePlayerListUrl fail due to accessToken is null"); + return null; + } + return String.format(GET_WECHAT_APPLET_LIVE_PLAYER_LIST_URL, accessToken); + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatSetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatSetting.java new file mode 100644 index 0000000..3b63348 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatSetting.java @@ -0,0 +1,297 @@ +package com.ruoyi.util; + +import org.springframework.util.StringUtils; + +/** + * 微信设置实体类 + */ +public class WechatSetting { + /** + * 公众号appId(必传) + */ + private String appId; + /** + * AppSecret(必传) + */ + private String appSecret; + /** + * 商户号(支付时必传) + */ + private String merchantNum; + /** + * API密钥(支付时必传) + */ + private String apiKey; + /** + * 支付回调(支付时必传) + */ + private String payCallback; + /** + * 网页授权回调地址(授权时必传) + */ + private String url; + /** + * 网站域名 (H5支付时必传) + */ + private String siteUrl; + + /** + * 网站名称(H5支付时必传) + */ + private String siteName; + + /** + * 终端ip地址 + */ + private String ip; + + /** + * 支付方式 1:公众号支付(openid必传) 2:H5支付 3:扫码支付 4:APP支付 5:小程序支付(openId必传) + */ + private int type; + + /** + * 公众号支付必传 openid(微信公众号支付) + */ + private String openId; + + + private String certFile; + + /** + * 构造微信支付参数实体 + * + * @param ip 终端ip + * @param type 支付方式 1:公众号支付(openid必传) 2:H5支付 3:扫码支付 4:APP支付 + * @param callBackUrl 微信异步回调地址 + * @return 返回构造微信支付参数实体 + */ + public static WechatSetting build(String ip, int type, String callBackUrl) { + WechatSetting wechatSetting = new WechatSetting(); + wechatSetting.ip = ip; + wechatSetting.type = type; + wechatSetting.payCallback = callBackUrl; + return wechatSetting; + } + + /** + * 是否是app支付 + * + * @return app支付返回true 否则返回false + */ + public boolean isAppPay() { + return 4 == this.type; + } + + /** + * 是否是h5支付 + * + * @return h5支付返回true 否则返回false + */ + public boolean isH5Pay() { + return 2 == this.type; + } + + /** + * 是否是扫码支付 + * + * @return 扫码支付返回true 否则返回false + */ + public boolean isQRPay() { + return 3 == this.type; + } + + /** + * 是否是公众号支付 + * + * @return 公众号支付返回true 否则返回false + */ + public boolean isOfficialAccountPay() { + return 1 == this.type; + } + + /** + * 是否是小程序支付 + * + * @return 小程序支付返回true 否则返回false + */ + public boolean isAppletPay() { + return 5 == this.type; + } + + /** + * 检测支付时的参数 + */ + public boolean checkPayParams() { + return !StringUtils.isEmpty(appId) && !StringUtils.isEmpty(appSecret) && + !StringUtils.isEmpty(merchantNum) && !StringUtils.isEmpty(apiKey); + } + + /** + * 增加openid + * + * @param openId 公众号支付必传 openid(微信公众号支付) + * @return 返回当前对象 + */ + public WechatSetting addOpenId(String openId) { + this.openId = openId; + return this; + } + + /** + * 增加网站名称 + * + * @param siteName 网站名称 + * @return 返回当前对象 + */ + public WechatSetting addSiteName(String siteName) { + this.siteName = siteName; + return this; + } + + /** + * 增加网站域名 + * + * @param siteUrl 网站域名 + * @return 返回当前对象 + */ + public WechatSetting addSiteUrl(String siteUrl) { + this.siteUrl = siteUrl; + return this; + } + + /** + * 检测H5支付时的参数 + */ + public boolean checkH5PayParams() { + return !StringUtils.isEmpty(siteUrl) && !StringUtils.isEmpty(siteName) && checkPayParams(); + } + + /** + * 检测授权时的参数 + */ + public boolean checkOAuthParams() { + return !StringUtils.isEmpty(appId) && !StringUtils.isEmpty(appSecret) && + !StringUtils.isEmpty(url); + } + + /** + * 检测小程序授权时的参数 + */ + public boolean checkAppletOAuthParams() { + return !StringUtils.isEmpty(appId) && !StringUtils.isEmpty(appSecret); + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } + + public String getMerchantNum() { + return merchantNum; + } + + public void setMerchantNum(String merchantNum) { + this.merchantNum = merchantNum; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getPayCallback() { + return payCallback; + } + + public void setPayCallback(String payCallback) { + this.payCallback = payCallback; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSiteUrl() { + return siteUrl; + } + + public void setSiteUrl(String siteUrl) { + this.siteUrl = siteUrl; + } + + public String getSiteName() { + return siteName; + } + + public void setSiteName(String siteName) { + this.siteName = siteName; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + @Override + public String toString() { + return "WechatSetting{" + + "appId='" + appId + '\'' + + ", appSecret='" + appSecret + '\'' + + ", merchantNum='" + merchantNum + '\'' + + ", apiKey='" + apiKey + '\'' + + ", payCallback='" + payCallback + '\'' + + ", url='" + url + '\'' + + ", siteUrl='" + siteUrl + '\'' + + ", siteName='" + siteName + '\'' + + ", ip='" + ip + '\'' + + ", type=" + type + + ", openId='" + openId + '\'' + + '}'; + } + + public String getCertFile() { + return certFile; + } + + public void setCertFile(String certFile) { + this.certFile = certFile; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatUtils.java new file mode 100644 index 0000000..4d0a6f9 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/WechatUtils.java @@ -0,0 +1,715 @@ +package com.ruoyi.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.util.md5.MD5Utils; +import com.ruoyi.util.bean.*; +import com.ruoyi.util.*; +import com.weixin.pay.WXPay; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + + +/** + * 微信工具类 + */ +public class WechatUtils { + + /** + * 支付异步回调成功后需返回的xml + */ + public final static String SUCCESS_RETURN = "SUCCESSOK"; + /** + * 成功 + */ + public final static String SUCCESS = "SUCCESS"; + /** + * 公众号支付 + */ + public final static int OFFICIAL_ACCOUNT_PAY = 1; + /** + * H5支付 + */ + public final static int H5_PAY = 2; + /** + * 扫码支付 + */ + public final static int QR_PAY = 3; + /** + * app支付 + */ + public final static int APP_PAY = 4; + /** + * 小程序支付 + */ + public final static int APPLET_PAY = 5; + /** + * 调试日志 + */ + private static final Logger logger = LoggerFactory.getLogger(WechatUtils.class); + /** + * 获取code地址 + */ + private final static String GET_CODE_URL = + "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect"; + /** + * 获取access_token地址 + */ + private final static String GET_ACCESS_TOKEN_URL = + "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; + /** + * 获取用户信息地址 + */ + private final static String GET_USERINFO_URL = + "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN"; + /** + * 小程序,公众号支付用户零钱地址 + */ + private final static String MMPAY_MKT_TRANSFERS = + "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; + /** + * 静默授权 + */ + private final static String SNSAPI_BASE = "snsapi_base"; + /** + * 用户授权 + */ + private final static String SNSAPI_USERINFO = "snsapi_userinfo"; + /** + * 微信支付统一下单地址 + */ + private final static String UNION_SUBMIT_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; + /** + * 获取微信分享access_token地址(参数为 appid 和 secret) + */ + private final static String GET_ACCESS_TOKEN_FOR_SHARE_URL = + "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + /** + * 获取微信分享jsapi_ticket地址(参数为 access_token) + */ + private final static String GET_JSAPI_TICKET_URL = + "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi"; + + private WechatUtils() { + } + + /** + * 获取静默授权地址 + * + * @param fromUrl 拦截前链接 + * @param wechatSetting 微信设置实体 + * @return 静默授权地址 + */ + public static String getCodeUrlBase(String fromUrl, WechatSetting wechatSetting) { + logger.debug("getCodeUrlBase and fromUrl:{} \r\n wechatSetting:{}", fromUrl, wechatSetting); + return String.format(GET_CODE_URL, wechatSetting.getAppId(), wechatSetting.getUrl(), SNSAPI_BASE, fromUrl); + } + + /** + * 获取用户授权地址 + * + * @param fromUrl 拦截前链接 + * @param wechatSetting 微信设置实体 + * @return 用户授权地址 + */ + public static String getCodeUrlInfo(String fromUrl, WechatSetting wechatSetting) { + logger.debug("getCodeUrlInfo and fromUrl:{}\r\n wechatSetting:{} ", fromUrl, wechatSetting); + return String.format(GET_CODE_URL, wechatSetting.getAppId(), wechatSetting.getUrl(), SNSAPI_USERINFO, fromUrl); + } + + /** + * 获取网页授权access_token + * + * @param code 微信code + * @param state 与code一起返回的状态码(额外参数) + * @param wechatSetting 微信设置实体 + * @return 网页授权返回实体类 + */ + public static AccessTokenResult getAccessToken(String code, String state, WechatSetting wechatSetting) { + AccessTokenResult res; + logger.debug("getAccessToken and code:{}\r\n wechatSetting:{} ", code, wechatSetting); + String accessTokenUrl = String.format(GET_ACCESS_TOKEN_URL, wechatSetting.getAppId(), wechatSetting.getAppSecret(), code); + res = JSON.parseObject(executeHttpGet(accessTokenUrl), AccessTokenResult.class); + if (res.isError()) { + if (!StringUtils.isEmpty(res.getErrmsg())) { + logger.error("getAccessToken Fail and errmsg:{}", res.getErrmsg()); + } + return null; + } else { + res.setRedirectUrl(state); + return res; + } + + } + + /** + * 获取微信分享access_token + * + * @param wechatSetting 微信设置实体 + * @return 微信分享access_token + */ + public static String getAccessTokenForShare(WechatSetting wechatSetting) { + logger.debug("getAccessToken and wechatSetting:{} ", wechatSetting); + String accessTokenForShareUrl = String.format(GET_ACCESS_TOKEN_FOR_SHARE_URL, wechatSetting.getAppId(), wechatSetting.getAppSecret()); + JSONObject res = JSON.parseObject(executeHttpGet(accessTokenForShareUrl)); + if (!StringUtils.isEmpty(res.getString("errcode"))) { + if (!StringUtils.isEmpty(res.getString("errmsg"))) { + logger.error("getAccessTokenForShare Fail and errmsg:{}", res.getString("errmsg")); + } + return null; + } else { + return res.getString("access_token"); + } + } + + /** + * 获取微信分享jsapi_ticket + * + * @param access_token 凭证 + * @return 微信分享jsapi_ticket + */ + public static String getJsapiTicketForShare(String access_token) { + logger.debug("getAccessToken and access_token:{} ", access_token); + String jsapiTicketForShareUrl = String.format(GET_JSAPI_TICKET_URL, access_token); + JSONObject res = JSON.parseObject(executeHttpGet(jsapiTicketForShareUrl)); + if (Integer.parseInt(res.getString("errcode")) != 0) { + if (!StringUtils.isEmpty(res.getString("errmsg"))) { + logger.error("getJsapiTicketForShare Fail and errmsg:{}", res.getString("errmsg")); + } + return null; + } else { + return res.getString("ticket"); + } + } + + /** + * 获取用户信息 + * + * @param accessToken 网页授权接口调用凭证 + * @param openId 用户的唯一标识 + * @return 用户信息返回实体类 + */ + public static UserInfoResult getUserInfo(String accessToken, String openId) { + logger.debug("getUserInfo and access_token:{}\r\n openid:{} ", accessToken, openId); + + String userInfoUrl = String.format(GET_USERINFO_URL, accessToken, openId); + UserInfoResult res = JSON.parseObject(executeHttpGet(userInfoUrl), UserInfoResult.class); + if (res.isError()) { + if (!StringUtils.isEmpty(res.getErrmsg())) { + logger.error("getUserInfo Fail and errmsg:{}", res.getErrmsg()); + } + return null; + } else { + return res; + } + } + + /** + * 获取预支付信息 + * + * @param wechatSetting 微信设置实体 + * @param orderInfoForPay 订单信息 + * @return 预支付信息 + */ + public static PrepayResult getPrepay(WechatSetting wechatSetting, OrderInfoForPay orderInfoForPay) { + logger.debug("getPrepay and \r\n wechatSetting:{} \r\n orderInfoForPay:{} ", wechatSetting, orderInfoForPay); + String xml = getWxPayParm(wechatSetting, orderInfoForPay); + String res = executeHttpPost(UNION_SUBMIT_ORDER_URL, xml); + logger.debug("getPrepay and res:{}", res); + + //将xml字符串转换为java对象 + JaxbUtil resultBinder = new JaxbUtil(PrepayResult.class); + PrepayResult prepayResult = resultBinder.fromXml(res); + if (!prepayResult.isError()) { + //公众号支付时增加返回信息 + if (wechatSetting.isOfficialAccountPay() || wechatSetting.isAppletPay()) { + SortedMap packageParams = new TreeMap<>(); + prepayResult.setPackage(); + prepayResult.setSign_type("MD5"); + prepayResult.setTime_stamp(getTimeStamp()); + packageParams.put("appId", prepayResult.getAppid()); + packageParams.put("timeStamp", prepayResult.getTime_stamp()); + packageParams.put("nonceStr", prepayResult.getNonce_str()); + packageParams.put("package", prepayResult.getPackage_()); + packageParams.put("signType", prepayResult.getSign_type()); + prepayResult.setPay_sign(createSign(packageParams, wechatSetting.getApiKey())); + } + else if (wechatSetting.isAppPay()) { + // app支付获得签名 + SortedMap packageParams = new TreeMap<>(); + prepayResult.setTime_stamp(getTimeStamp()); + packageParams.put("appid", prepayResult.getAppid()); + packageParams.put("timestamp", prepayResult.getTime_stamp()); + packageParams.put("noncestr", prepayResult.getNonce_str()); + packageParams.put("package", "Sign=WXPay"); + packageParams.put("partnerid", wechatSetting.getMerchantNum()); + packageParams.put("prepayid", prepayResult.getPrepay_id()); + prepayResult.setPay_sign(createSign(packageParams, wechatSetting.getApiKey())); + } + return prepayResult; + } else { + if (!StringUtils.isEmpty(prepayResult.getErr_code_des())) { + logger.error("getPrepay Fail and errcode:{} \r\n returnmsg:{} \r\n errormsg:{} ", prepayResult.getReturn_msg(), prepayResult.getErr_code(), prepayResult.getErr_code_des()); + } + return null; + } + } + + + /** + * 获取提现信息 + * + * @param wechatSetting 微信设置实体 + * @param cashInfoForPay 订单信息 + * @return 预支付信息 + */ + public static WxTransferResult getTransfers(WechatSetting wechatSetting, OrderInfoForPay cashInfoForPay) { + logger.debug("getPrepay and \r\n wechatSetting:{} \r\n orderInfoForPay:{} ", wechatSetting, cashInfoForPay); + String xml = getWxPayParm(wechatSetting, cashInfoForPay); + String res = executeHttpPost(MMPAY_MKT_TRANSFERS, xml); + logger.debug("getPrepay and res:{}", res); + + //将xml字符串转换为java对象 + JaxbUtil resultBinder = new JaxbUtil(WxTransferResult.class); + WxTransferResult wxTransferResult = resultBinder.fromXml(res); + if (!wxTransferResult.isError()) { + //公众号支付时增加返回信息 + if (wechatSetting.isOfficialAccountPay() || wechatSetting.isAppletPay()) { + SortedMap packageParams = new TreeMap<>(); + wxTransferResult.setPackage(); + wxTransferResult.setSign_type("MD5"); + wxTransferResult.setTime_stamp(getTimeStamp()); + packageParams.put("appId", wxTransferResult.getMch_appid()); + packageParams.put("timeStamp", wxTransferResult.getPayment_time()); + packageParams.put("nonceStr", wxTransferResult.getNonce_str()); + packageParams.put("package", wxTransferResult.getPackage_()); + packageParams.put("signType", wxTransferResult.getSign_type()); + wxTransferResult.setPay_sign(createSign(packageParams, wechatSetting.getApiKey())); + } else if (wechatSetting.isAppPay()) { + // app支付获得签名 + SortedMap packageParams = new TreeMap<>(); + wxTransferResult.setTime_stamp(getTimeStamp()); + packageParams.put("appid", wxTransferResult.getMch_appid()); + packageParams.put("timestamp", wxTransferResult.getTime_stamp()); + packageParams.put("noncestr", wxTransferResult.getNonce_str()); + packageParams.put("package", "Sign=WXPay"); + packageParams.put("partnerid", wechatSetting.getMerchantNum()); + packageParams.put("prepayid", wxTransferResult.getPrepay_id()); + wxTransferResult.setPay_sign(createSign(packageParams, wechatSetting.getApiKey())); + } + return wxTransferResult; + } else { + if (!StringUtils.isEmpty(wxTransferResult.getErr_code_des())) { + logger.error("getPrepay Fail and returnmsg:{} \r\n errormsg:{} ", wxTransferResult.getReturn_msg(), wxTransferResult.getErr_code_des()); + } + return null; + } + } + + /** + * 获取统一下单请求参数 + * + * @param wechatSetting 微信设置实体 + * @param orderInfoForPay 订单信息 + * @return 统一下单请求参数 + */ + private static String getWxPayParm(WechatSetting wechatSetting, OrderInfoForPay orderInfoForPay) { + logger.debug("getWxPayParm and wechatSetting:{} \r\n orderInfoForPay:{} ", wechatSetting, orderInfoForPay); + SortedMap packageParams = new TreeMap<>(); + // 金额转化为分为单位 + int finalmoney = Integer.parseInt(String.format("%.2f", orderInfoForPay.getPrice()).replace(".", "")); + //交易方式 + String tradeType = ""; + //场景信息 + String sceneInfo; + //商品ID + String productId; + //公众号支付 + if (wechatSetting.isOfficialAccountPay() || wechatSetting.isAppletPay()) { + //用户唯一标识 + packageParams.put("openid", wechatSetting.getOpenId()); + tradeType = "JSAPI"; + } + //H5支付 + if (wechatSetting.isH5Pay()) { + tradeType = "MWEB"; + sceneInfo = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"" + wechatSetting.getSiteUrl() + "\",\"wap_name\": \"" + wechatSetting.getSiteName() + "\"}}"; + packageParams.put("scene_info", sceneInfo); + } + //扫码支付 + if (wechatSetting.isQRPay()) { + tradeType = "NATIVE"; + productId = String.valueOf(orderInfoForPay.getGoodsId()); + packageParams.put("product_id", productId); + } + + // APP支付 + if (wechatSetting.isAppPay()) { + tradeType = "APP"; + } + //公众账号ID + packageParams.put("appid", wechatSetting.getAppId()); + //商户号 + packageParams.put("mch_id", wechatSetting.getMerchantNum()); + //随机字符串 + packageParams.put("nonce_str", getRandomString()); + //商品描述 + packageParams.put("body", getSubGoodName(orderInfoForPay.getGoodsName())); + //附加数据(支付类型) + packageParams.put("attach", orderInfoForPay.getType() + ""); + //商户订单号 + packageParams.put("out_trade_no", orderInfoForPay.getOrderCode() + "-" + getTimeStamp()); + //标价金额 + packageParams.put("total_fee", String.valueOf(finalmoney)); + //终端IP + packageParams.put("spbill_create_ip", wechatSetting.getIp());//本地测试需替换为外网ip + //通知地址 + packageParams.put("notify_url", wechatSetting.getPayCallback()); + //交易类型 + packageParams.put("trade_type", tradeType); + //签名 + packageParams.put("sign", createSign(packageParams, wechatSetting.getApiKey())); + + return getRequestXml(packageParams); + } + + /** + * 获取企业支付请求参数 + * + * @param wechatSetting 微信设置实体 + * @param cashInfoForPay 订单信息 + * @return 统一下单请求参数 + */ + private static String getWxTransfersParm(WechatSetting wechatSetting, OrderInfoForPay cashInfoForPay) { + logger.debug("getWxPayParm and wechatSetting:{} \r\n orderInfoForPay:{} ", wechatSetting, cashInfoForPay); + SortedMap packageParams = new TreeMap<>(); + // 金额转化为分为单位 + int finalmoney = Integer.parseInt(String.format("%.2f", cashInfoForPay.getPrice()).replace(".", "")); + //交易方式 + String tradeType = ""; + //场景信息 + String sceneInfo; + //商品ID + String productId; + //公众号支付 + if (wechatSetting.isOfficialAccountPay() || wechatSetting.isAppletPay()) { + //用户唯一标识 + packageParams.put("openid", wechatSetting.getOpenId()); + tradeType = "JSAPI"; + } + //H5支付 + if (wechatSetting.isH5Pay()) { + tradeType = "MWEB"; + sceneInfo = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"" + wechatSetting.getSiteUrl() + "\",\"wap_name\": \"" + wechatSetting.getSiteName() + "\"}}"; + packageParams.put("scene_info", sceneInfo); + } + //扫码支付 + if (wechatSetting.isQRPay()) { + tradeType = "NATIVE"; + productId = String.valueOf(cashInfoForPay.getGoodsId()); + packageParams.put("product_id", productId); + } + + // APP支付 + if (wechatSetting.isAppPay()) { + tradeType = "APP"; + } + //商户账号appid + packageParams.put("mch_appid", wechatSetting.getAppId()); + //商户号 + packageParams.put("mchid", wechatSetting.getMerchantNum()); + //随机字符串 + packageParams.put("nonce_str", getRandomString()); + //附加数据(支付类型) + packageParams.put("check_name", "NO_CHECK"); + //商户订单号 + packageParams.put("partner_trade_no", cashInfoForPay.getOrderCode() + "-" + getTimeStamp()); + //金额 + packageParams.put("amount", String.valueOf(finalmoney)); + //付款备注 + packageParams.put("desc", cashInfoForPay.getType() == 2 ? "奖励提取" : "提现"); + //终端IP + packageParams.put("spbill_create_ip", wechatSetting.getIp());//本地测试需替换为外网ip + //签名 + packageParams.put("sign", createSign(packageParams, wechatSetting.getApiKey())); + + return getRequestXml(packageParams); + } + + + /** + * 截取商品名 + * + * @param goodName 商品名 + * @return 截取后的商品名 + */ + private static String getSubGoodName(String goodName) { + if (goodName.length() < 20) { + return goodName; + } else { + return goodName.substring(0, 19) + "..."; + } + } + + + /** + * 验证返回信息 + * + * @param inputStream 微信回调信息 + * @param wechatSetting 微信设置 + * @return 订单支付信息 + */ + public static OrderInfoAfterPay afterPayInfo(InputStream inputStream, WechatSetting wechatSetting) { + logger.debug("afterPayInfo and wechatSetting:{}", wechatSetting); + OrderInfoAfterPay orderInfoAfterPay = new OrderInfoAfterPay(); + orderInfoAfterPay.setSuccess(false); + BufferedReader br; + br = new BufferedReader(new InputStreamReader(inputStream)); + String line; + StringBuilder sb = new StringBuilder(); + try { + while ((line = br.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + + try { + br.close(); + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + //将xml字符串转换为java对象 + JaxbUtil resultBinder = new JaxbUtil(WechatNotifyResult.class); + WechatNotifyResult wechatNotifyResult = resultBinder.fromXml(sb.toString()); + //将xml字符串转换为map + SortedMap resultMap = new TreeMap<>(parseMapFromXmlStr(sb.toString())); + //签名 + String sign = createSign(resultMap, wechatSetting.getApiKey()); + + logger.info("wechat notify and wechatNotifyResult :{}", wechatNotifyResult); + + //验证是否失败,并验证签名 + if (!wechatNotifyResult.isError() && sign.equals(wechatNotifyResult.getSign())) { + //验证其他信息 + if (SUCCESS.equals(wechatNotifyResult.getResult_code()) + && SUCCESS.equals(wechatNotifyResult.getReturn_code()) + && wechatSetting.getAppId().equals(wechatNotifyResult.getAppid()) + && wechatSetting.getMerchantNum().equals(wechatNotifyResult.getMch_id()) + ) { + orderInfoAfterPay.setOrderCode(wechatNotifyResult.getOut_trade_no().split("-")[0]); + orderInfoAfterPay.setSuccess(true); + orderInfoAfterPay.setType(wechatNotifyResult.getAttach()); + orderInfoAfterPay.setTransCode(wechatNotifyResult.getTransaction_id()); + } + + } else { + logger.error("wechat afterPayInfo fail: returnmsg:{}\r\n errormsg:{}", wechatNotifyResult.getReturn_msg(), wechatNotifyResult.getErr_code_des()); + } + return orderInfoAfterPay; + } + + /** + * 获取请求xml + * + * @param packageParams 请求参数 + * @return 请求xml + */ + private static String getRequestXml(SortedMap packageParams) { + StringBuilder sb = new StringBuilder(); + sb.append(""); + Set es = packageParams.entrySet(); + for (Object e : es) { + Map.Entry entry = (Map.Entry) e; + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + if ("body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) { + sb.append("<").append(key).append(">").append(""); + } else { + sb.append("<").append(key).append(">").append(value).append(""); + } + } + sb.append(""); + logger.debug("getRequestXml and xml:{}", sb.toString()); + return sb.toString(); + } + + /** + * 签名 + * + * @param packageParams 签名参数 + * @param apiKey 商户key + * @return 签名 + */ + private static String createSign(SortedMap packageParams, String apiKey) { + + StringBuilder sb = new StringBuilder(); + Set es = packageParams.entrySet(); + for (Object e : es) { + Map.Entry entry = (Map.Entry) e; + String k = (String) entry.getKey(); + String v = (String) entry.getValue(); + if ((v != null) && (!"".equals(v)) && (!"sign".equals(k)) && + (!"key".equals(k))) { + sb.append(k).append("=").append(v).append("&"); + } + } + sb.append("key=").append(apiKey); + logger.debug("createSign and key:{}", apiKey); + logger.debug("createSign and stringSign:{}", sb.toString()); + String sign = MD5Utils.getInstance().createMd5(sb.toString()) + .toUpperCase(); + logger.debug("createSign and sign:{}", sign); + return sign; + + } + + /** + * 执行GET方法请求数据 + * + * @param url 请求地址 + * @return 返回数据 + */ + static String executeHttpGet(String url) { + logger.debug("executeHttpGet and url:{}", url); + String result = null; + BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + HttpGet httpRequest = new HttpGet(url); + + try { + //使用DefaultHttpClient类的execute方法发送HTTP GET请求,并返回HttpResponse对象。 + HttpResponse httpResponse = httpClient.execute(httpRequest);//其中HttpGet是HttpUriRequst的子类 + HttpEntity httpEntity = httpResponse.getEntity(); + result = EntityUtils.toString(httpEntity, "UTF-8");//取出应答字符串 + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 执行POST方法请求数据 + * + * @param url 请求地址 + * @param xml 请求参数 + * @return 返回数据 + */ + public static String executeHttpPost(String url, String xml) { + logger.debug("executeHttpPost and url:{}", url); + String result = null; + BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + HttpPost httpRequest = new HttpPost(url); + + try { + httpRequest.setEntity(new StringEntity(xml, "UTF-8")); + //使用DefaultHttpClient类的execute方法发送HTTP GET请求,并返回HttpResponse对象。 + HttpResponse httpResponse = httpClient.execute(httpRequest);//其中HttpGet是HttpUriRequst的子类 + HttpEntity httpEntity = httpResponse.getEntity(); + result = EntityUtils.toString(httpEntity, "UTF-8");//取出应答字符串 + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 获取随机字符串 + * + * @return 随机字符串 + */ + public static String getRandomString() { + String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + Random random = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 32; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } + + /** + * 获取时间戳 + * + * @return 时间戳(秒数) + */ + public static String getTimeStamp() { + return String.valueOf(System.currentTimeMillis() / 1000L); + } + + /** + * 将xml字符串转换成map + * + * @param xml xml + * @return Map + */ + private static Map parseMapFromXmlStr(String xml) { + Map map = new HashMap<>(); + Document doc; + try { + doc = DocumentHelper.parseText(xml); // 将字符串转为XML + Element rootElt = doc.getRootElement(); // 获取根节点 + List list = rootElt.elements();//获取根节点下所有节点 + for (Element element : list) { //遍历节点 + map.put(element.getName(), element.getText()); //节点的name为map的key,text为map的value + } + } catch (Exception e) { + e.printStackTrace(); + } + return map; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/YunUploadUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/YunUploadUtils.java new file mode 100644 index 0000000..0cd666d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/YunUploadUtils.java @@ -0,0 +1,219 @@ +package com.ruoyi.util; + +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSSClient; +import com.aliyun.oss.OSSException; +import com.aliyun.oss.model.PutObjectRequest; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.util.bean.OssYunConf; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import java.util.UUID; + +/** + * Created by 魔金商城 on 17/5/8. + * 又拍云上传工具 + */ +public class YunUploadUtils { + + private static final YunUploadUtils INSTANCE = new YunUploadUtils(); + /** + * 调试工具 + */ + private Logger logger = LoggerFactory.getLogger(YunUploadUtils.class); + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); + + private YunUploadUtils() { + } + + public static YunUploadUtils getInstance() { + return INSTANCE; + } + + + /** + * 获取文件保存路径 + * + * @param fileOriginName 用户上传文件名 + * @return 文件保存路径 + */ + private String getFilePath(String fileOriginName) { + String fileType = "jpg"; + if (!StringUtils.isEmpty(fileOriginName) && fileOriginName.contains(".")) { + fileType = fileOriginName.substring(fileOriginName.lastIndexOf(".") + 1); + } + String fileName = String.valueOf(System.currentTimeMillis()) + "." + fileType; + String date = simpleDateFormat.format(Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00")).getTime()); + return "/" + date + "/" + fileName; + } + + /** + * 判断是否是图片 + * + * @param bytes 字节数组 + * @return 是图片返回true 否则返回false + */ + private boolean isPicture(byte[] bytes) { + try { + BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes)); + return image != null; + } catch (IOException e) { + logger.error("file is not a picture ...", e); + return false; + } + } + + /** + * 上传腾讯云 + * + * @param file + * @param bytes 图片字节 + * @param type 上传的类型 0 图片 1 视频 + * @return 返回图片在又拍云的地址 + */ + public String uploadToQqOss(OssYunConf cloudStorageConfig, MultipartFile file, byte[] bytes, String fileOriginName, String type) { + return QqOssClient.uploadToQqOss(cloudStorageConfig, file, bytes, fileOriginName, type); + } + + /** + * 上传又拍云 + * + * @param upYunConf 又拍云设置 + * @param inputStream 输入流 + * @param bytes 图片字节 + * @return 返回图片在又拍云的地址 + */ + public String uploadToQqForBase64(OssYunConf upYunConf, InputStream inputStream, byte[] bytes, String fileOriginName) { + logger.debug("Being to uploadToUpYun....."); + if (org.apache.commons.lang3.ArrayUtils.isEmpty(bytes)) { + logger.error("uploadToUpYun fail due to bytes is empty ...."); + return ""; + } + return QqOssClient.uploadToUpYunForBase64(upYunConf, inputStream, bytes, fileOriginName, bytes); + } + + /** + * 上传阿里云 + * + * @param inputStream 输入流 + * @param bytes 图片字节 + * @param type 上传的类型 0 图片 1 视频 + * @return 返回图片在又拍云的地址 + */ + public String uploadToOssYun(OssYunConf config, InputStream inputStream, byte[] bytes, String fileOriginName, String type) { + String url = null; + try { + url = upload(config.getAccessKeyId(), config.getAccessKeySecret(), config.getBucketName(), config.getEndPoint(), + config.getPrefix(), getKey(config.getBucketName(), ""), inputStream); + + } catch (Exception e) { + return e.getMessage(); + } + return url; + } + + /** + * 上传又拍云 + * + * @param inputStream 输入流 + * @param bytes 图片字节 + * @return 返回图片在又拍云的地址 + */ + public String uploadToOssYunForBase64(OssYunConf config, InputStream inputStream, byte[] bytes, String fileOriginName) { + String url = null; + try { + url = upload(config.getAccessKeyId(), config.getAccessKeySecret(), config.getBucketName(), config.getEndPoint(), + config.getPrefix(), getKey(config.getBucketName(), ""), inputStream); + + } catch (Exception e) { + return e.getMessage(); + } + return url; + } + + /** + * 上传文件<>基础方法 + * + * @param accessKeyId 授权 ID + * @param accessKeySecret 授权密钥 + * @param bucketName 桶名 + * @param endpoint 节点名 + * @param styleName 样式名 + * @param key 文件名 + * @param inputStream 文件流 + * @return 访问路径 ,结果为null时说明上传失败 + */ + public String upload(String accessKeyId, String accessKeySecret, String bucketName, String endpoint, String + styleName, String key, InputStream inputStream) { + if (inputStream == null) { + return null; + } + String url = null; + OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); + try { + // 带进度条的上传 + ossClient.putObject(new PutObjectRequest(bucketName, key, inputStream)); + } catch (OSSException oe) { + oe.printStackTrace(); + key = null; + } catch (ClientException ce) { + ce.printStackTrace(); + key = null; + } catch (Exception e) { + e.printStackTrace(); + key = null; + } finally { + ossClient.shutdown(); + } + if (key != null) { + // 拼接文件访问路径。由于拼接的字符串大多为String对象,而不是""的形式,所以直接用+拼接的方式没有优势 + StringBuffer sb = new StringBuffer(); + sb.append("http://").append(bucketName).append(".").append(endpoint).append("/").append(key); + if (StringUtils.isNotBlank(styleName)) { + sb.append("/").append(styleName); + } + url = sb.toString(); + } + return url; + } + + /** + * 获取文件名(bucket里的唯一key) + * 上传和删除时除了需要bucketName外还需要此值 + * + * @param prefix 前缀(非必传),可以用于区分是哪个模块或子项目上传的文件 + * @param suffix 后缀(非必传), 可以是 png jpg 等 + * @return + */ + public String getKey(final String prefix, final String suffix) { + //生成uuid,替换 - 的目的是因为后期可能会用 - 将key进行split,然后进行分类统计 + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + //文件路径 + String path = DateUtils.parseDateToStr("yyyyMMdd", new Date()) + "-" + uuid; + + if (StringUtils.isNotBlank(prefix)) { + path = prefix + "-" + path; + } + if (suffix != null) { + if (suffix.startsWith(".")) { + path = path + suffix; + } else { + path = path + "." + suffix; + } + } + return path; + } + +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AccessTokenResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AccessTokenResult.java new file mode 100644 index 0000000..a84de79 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AccessTokenResult.java @@ -0,0 +1,164 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 网页授权返回实体类 + */ +public class AccessTokenResult { + + + /** + * 网页授权接口调用凭证 + */ + @JSONField(name = "access_token") + private String access_token; + + /** + * access_token接口调用凭证超时时间,单位(秒) + */ + @JSONField(name = "expires_in") + private int expires_in; + + /** + * 用户刷新access_token + */ + @JSONField(name = "refresh_token") + private String refresh_token; + + /** + * 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID + */ + @JSONField(name = "openid") + private String openid; + + /** + * 用户授权的作用域,使用逗号(,)分隔 + */ + @JSONField(name = "scope") + private String scope; + + /** + * 联合登录id + */ + @JSONField(name = "unionid") + private String unionid; + + /** + * 错误码 + */ + @JSONField(name = "errcode") + private String errcode; + + /** + * 重定向地址(出错时返回) + */ + private String redirectUrl; + + /** + * 错误信息(出错时返回) + */ + @JSONField(name = "errmsg") + private String errmsg; + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return !StringUtils.isEmpty(this.errcode); + } + + public String getAccess_token() { + return access_token; + } + + public void setAccess_token(String access_token) { + this.access_token = access_token; + } + + public int getExpires_in() { + return expires_in; + } + + public void setExpires_in(int expires_in) { + this.expires_in = expires_in; + } + + public String getRefresh_token() { + return refresh_token; + } + + public void setRefresh_token(String refresh_token) { + this.refresh_token = refresh_token; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getUnionid() { + return unionid; + } + + public void setUnionid(String unionid) { + this.unionid = unionid; + } + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } + + public String getRedirectUrl() { + return redirectUrl; + } + + public void setRedirectUrl(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + /** + * 转换为字符串 + */ + @Override + public String toString() { + return "AccessTokenResult{" + + "access_token='" + access_token + '\'' + + ", expires_in=" + expires_in + + ", refresh_token='" + refresh_token + '\'' + + ", openid='" + openid + '\'' + + ", scope='" + scope + '\'' + + ", unionid='" + unionid + '\'' + + ", errcode='" + errcode + '\'' + + ", redirectUrl='" + redirectUrl + '\'' + + ", errmsg='" + errmsg + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AliPaySetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AliPaySetting.java new file mode 100644 index 0000000..d0228f2 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/AliPaySetting.java @@ -0,0 +1,106 @@ +package com.ruoyi.util.bean; + +import org.springframework.util.StringUtils; + +/** + * 支付宝设置实体类 + */ +public class AliPaySetting { + /** + * APPID 即创建应用后生成 + */ + private String appId; + /** + * 开发者私钥,由开发者自己生成 + */ + private String appPrivateKey; + /** + * 支付宝公钥,由支付宝生成 + */ + private String alipayPublicKey; + /** + * 前台回调地址 + */ + private String beforeCallbackUrl; + /** + * 后台回调地址 + */ + private String backCallbackUrl; + + /** + * 构造阿里支付实体 + * + * @param beforeCallbackUrl 前台回调地址 + * @param backCallbackUrl 后台回调地址 + * @return 返回支付宝配置信息 + */ + public static AliPaySetting build(String beforeCallbackUrl, String backCallbackUrl) { + AliPaySetting aliPaySetting = new AliPaySetting(); + + //前台同步回调地址 + aliPaySetting.setBeforeCallbackUrl(beforeCallbackUrl); + //异步回调地址 + aliPaySetting.setBackCallbackUrl(backCallbackUrl); + + return aliPaySetting; + } + + /** + * 检测支付时的参数 + */ + public boolean checkPayParams() { + return !StringUtils.isEmpty(appId) && !StringUtils.isEmpty(appPrivateKey) && + !StringUtils.isEmpty(alipayPublicKey); + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppPrivateKey() { + return appPrivateKey; + } + + public void setAppPrivateKey(String appPrivateKey) { + this.appPrivateKey = appPrivateKey; + } + + public String getAlipayPublicKey() { + return alipayPublicKey; + } + + public void setAlipayPublicKey(String alipayPublicKey) { + this.alipayPublicKey = alipayPublicKey; + } + + public String getBeforeCallbackUrl() { + return beforeCallbackUrl; + } + + public void setBeforeCallbackUrl(String beforeCallbackUrl) { + this.beforeCallbackUrl = beforeCallbackUrl; + } + + public String getBackCallbackUrl() { + return backCallbackUrl; + } + + public void setBackCallbackUrl(String backCallbackUrl) { + this.backCallbackUrl = backCallbackUrl; + } + + @Override + public String toString() { + return "AliPaySetting{" + + "appId='" + appId + '\'' + + ", appPrivateKey='" + appPrivateKey + '\'' + + ", alipayPublicKey='" + alipayPublicKey + '\'' + + ", beforeCallbackUrl='" + beforeCallbackUrl + '\'' + + ", backCallbackUrl='" + backCallbackUrl + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/BeanUtils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/BeanUtils.java new file mode 100644 index 0000000..5ff34ae --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/BeanUtils.java @@ -0,0 +1,104 @@ +package com.ruoyi.util.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-segchk/src/main/java/com/ruoyi/util/bean/CommonWebResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/CommonWebResult.java new file mode 100644 index 0000000..0eb14ad --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/CommonWebResult.java @@ -0,0 +1,87 @@ +package com.ruoyi.util.bean; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 前端通用返回类 + * + * @author 徐凌峰 + */ +@ApiModel("接口返回公共对象") +public class CommonWebResult { + public static final CommonWebResult SUCCESS = new CommonWebResult<>(true); + public static final CommonWebResult FAIL = new CommonWebResult(false); + + static { + SUCCESS.setErrCode(0); + SUCCESS.setErrMsg("SUCCESS"); + } + + /** + * 返回给前端的业务数据 + */ + @ApiModelProperty("返回的具体业务数据") + private T data; + /** + * 错误码 + */ + private Integer errCode; + /** + * 错误信息 + */ + private String errMsg; + + public CommonWebResult(T data) { + this.data = data; + } + + public CommonWebResult() { + } + + public static CommonWebResult getSUCCESS() { + return SUCCESS; + } + + public static CommonWebResult getFAIL() { + return FAIL; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public Integer getErrCode() { + return errCode; + } + + public void setErrCode(Integer errCode) { + this.errCode = errCode; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public CommonWebResult data(T data) { + this.setData(data); + return this; + } + + @Override + public String toString() { + return "CommonWebResult{" + + "data=" + data + + ", errCode=" + errCode + + ", errMsg='" + errMsg + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailConf.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailConf.java new file mode 100644 index 0000000..6ae99c8 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailConf.java @@ -0,0 +1,58 @@ +package com.ruoyi.util.bean; + + +/** + * Created by 魔金商城 on 17/10/14. + * 邮箱配置类 + */ +public class EmailConf { + + /** + * 邮箱服务器的地址 + */ + private String host; + + /** + * 发送邮件人的用户名 + */ + private String userName; + + /** + * 发送邮件人的密码 + */ + private String password; + + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + 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; + } + + @Override + public String toString() { + return "EmailConf{" + + "host='" + host + '\'' + + ", userName='" + userName + '\'' + + ", password='" + password + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailContent.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailContent.java new file mode 100644 index 0000000..6d75acb --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/EmailContent.java @@ -0,0 +1,50 @@ +package com.ruoyi.util.bean; + + +/** + * Created by 魔金商城 on 17/10/14. + * 邮箱内容 + */ +public class EmailContent { + + + /** + * 邮件目的地 + */ + private String sendTo; + + + /** + * 邮件主题 + */ + private String subject; + + /** + * 邮件内容 + */ + private String text; + + public String getSendTo() { + return sendTo; + } + + public void setSendTo(String sendTo) { + this.sendTo = sendTo; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/LineColor.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/LineColor.java new file mode 100644 index 0000000..0674173 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/LineColor.java @@ -0,0 +1,55 @@ +package com.ruoyi.util.bean; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 颜色实体类 + * + * @author 魔金商城 created on 2020/4/14 + */ +@ApiModel(description = "颜色实体") +public class LineColor { + + /** + * 红色 + */ + @ApiModelProperty(value = "红色") + private int r; + + /** + * 绿色 + */ + @ApiModelProperty(value = "绿色") + private int g; + + /** + * 蓝色 + */ + @ApiModelProperty(value = "蓝色") + private int b; + + public int getR() { + return r; + } + + public void setR(int r) { + this.r = r; + } + + public int getG() { + return g; + } + + public void setG(int g) { + this.g = g; + } + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/MonYunSmsResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/MonYunSmsResponse.java new file mode 100644 index 0000000..4de8d83 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/MonYunSmsResponse.java @@ -0,0 +1,44 @@ +package com.ruoyi.util.bean; + + +/** + * 梦网云短信发送返回参数 + */ +public class MonYunSmsResponse { + /** + * 短信发送请求处理结果:0代表成功;非0代表失败。错误代码详见附录 + */ + Integer result; + /** + * 平台流水号:非0代表64位整型,对应Java和C#的long,不可用int解析。result非0时,msgid为0 + */ + Long msgid; + /** + * 用户自定义流水号:默认与请求报文multimt包结构内第一条数据的custid保持一致,若请求报文中没有custid参数或值为空,则返回由梦网生成的代表本批短信的唯一编号,result非0时,custid为空 + */ + String custid; + + public Integer getResult() { + return result; + } + + public void setResult(Integer result) { + this.result = result; + } + + public Long getMsgid() { + return msgid; + } + + public void setMsgid(Long msgid) { + this.msgid = msgid; + } + + public String getCustid() { + return custid; + } + + public void setCustid(String custid) { + this.custid = custid; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoAfterPay.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoAfterPay.java new file mode 100644 index 0000000..956fc53 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoAfterPay.java @@ -0,0 +1,70 @@ +package com.ruoyi.util.bean; + + +/** + * 支付后返回信息实体类 + */ +public class OrderInfoAfterPay { + + /** + * 订单code + */ + private String orderCode; + + /** + * 判断支付是否成功 + */ + private boolean isSuccess = false; + + /** + * 支付类型 1:订单支付 2:预存款充值 + */ + private int type; + + /** + * 交易流水号 + */ + private String transCode; + + public String getOrderCode() { + return orderCode; + } + + public void setOrderCode(String orderCode) { + this.orderCode = orderCode; + } + + public boolean isSuccess() { + return isSuccess; + } + + public void setSuccess(boolean success) { + isSuccess = success; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getTransCode() { + return transCode; + } + + public void setTransCode(String transCode) { + this.transCode = transCode; + } + + @Override + public String toString() { + return "OrderInfoAfterPay{" + + "orderCode='" + orderCode + '\'' + + ", isSuccess=" + isSuccess + + ", type=" + type + + ", transCode='" + transCode + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoForPay.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoForPay.java new file mode 100644 index 0000000..7148fc0 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OrderInfoForPay.java @@ -0,0 +1,86 @@ +package com.ruoyi.util.bean; + + +import java.math.BigDecimal; + +/** + * 待付订单信息 + */ +public class OrderInfoForPay { + + /** + * 订单code(或主订单code,必传) + */ + private String orderCode; + + /** + * 单品名称(必传) + */ + private String goodsName; + + /** + * 单品ID 扫码支付必传(微信支付) + */ + private long goodsId; + + /** + * 订单的最终价格 (用户实际付款的金额,必传) + */ + private BigDecimal price; + + /** + * 支付类型 1:订单支付 2:预存款充值(必传) + */ + private int type; + + public String getOrderCode() { + return orderCode; + } + + public void setOrderCode(String orderCode) { + this.orderCode = orderCode; + } + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public long getGoodsId() { + return goodsId; + } + + public void setGoodsId(long goodsId) { + this.goodsId = goodsId; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + @Override + public String toString() { + return "OrderInfoForPay{" + + "orderCode='" + orderCode + '\'' + + ", goodsName='" + goodsName + '\'' + + ", goodsId=" + goodsId + + ", price=" + price + + ", type=" + type + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OssYunConf.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OssYunConf.java new file mode 100644 index 0000000..038feef --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/OssYunConf.java @@ -0,0 +1,114 @@ +package com.ruoyi.util.bean; + + +/** + * Created by 魔金商城 on 17/5/8. + * 又拍云配置 + */ + +public class OssYunConf { + + private String accessKeyId; + private String accessKeySecret; + private String bucketName; + private String endPoint; + private String styleName; + private String prefix; + private String address; + + private OssYunConf() { + + } + + private OssYunConf(String accessKeyId, String accessKeySecret, String bucketName, String endPoint, String styleName, String prefix, String address) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + this.bucketName = bucketName; + this.endPoint = endPoint; + this.styleName = styleName; + this.prefix = prefix; + this.address = address; + } + + /** + * @param accessKeyId + * @param accessKeySecret + * @param bucketName + * @param endPoint + * @param styleName + * @param prefix + * @return + */ + public static OssYunConf buildOssYunConf(String accessKeyId, String accessKeySecret, String bucketName, String endPoint, String styleName, String prefix, String address) { + return new OssYunConf(accessKeyId, accessKeySecret, bucketName, endPoint, styleName, prefix, address); + } + + public String getAccessKeyId() { + return accessKeyId; + } + + public void setAccessKeyId(String accessKeyId) { + this.accessKeyId = accessKeyId; + } + + public String getAccessKeySecret() { + return accessKeySecret; + } + + public void setAccessKeySecret(String accessKeySecret) { + this.accessKeySecret = accessKeySecret; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getEndPoint() { + return endPoint; + } + + public void setEndPoint(String endPoint) { + this.endPoint = endPoint; + } + + public String getStyleName() { + return styleName; + } + + public void setStyleName(String styleName) { + this.styleName = styleName; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public String toString() { + return "OssYunConf{" + + "accessKeyId='" + accessKeyId + '\'' + + ", accessKeySecret='" + accessKeySecret + '\'' + + ", bucketName='" + bucketName + '\'' + + ", endPoint='" + endPoint + '\'' + + ", styleName='" + styleName + '\'' + + ", prefix='" + prefix + '\'' + + ", address='" + address + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/PrepayResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/PrepayResult.java new file mode 100644 index 0000000..7d92027 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/PrepayResult.java @@ -0,0 +1,307 @@ +package com.ruoyi.util.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 统一下单接口返回实体类 + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "xml") +@ApiModel(description = "统一下单接口返回实体类") +public class PrepayResult { + + /** + * 返回状态码 + */ + @XmlElement(name = "return_code") + @ApiModelProperty(value = "返回状态码") + private String return_code; + + /** + * 返回信息 + */ + @XmlElement(name = "return_msg") + @ApiModelProperty(value = "返回信息") + private String return_msg; + + /** + * 公众账号ID + */ + @XmlElement(name = "appid") + @ApiModelProperty(value = "公众账号ID") + private String appid; + + /** + * 商户号 + */ + @XmlElement(name = "mch_id") + @ApiModelProperty(value = "商户号") + private String mch_id; + + /** + * 随机字符串 + */ + @XmlElement(name = "nonce_str") + @ApiModelProperty(value = "随机字符串") + private String nonce_str; + + /** + * 签名 + */ + @XmlElement(name = "sign") + @ApiModelProperty(value = "签名") + private String sign; + + /** + * 业务结果 + */ + @XmlElement(name = "result_code") + @ApiModelProperty(value = "业务结果") + private String result_code; + + /** + * 错误代码 + */ + @XmlElement(name = "err_code") + @ApiModelProperty(value = "错误代码") + private String err_code; + + /** + * 错误代码描述 + */ + @XmlElement(name = "err_code_des") + @ApiModelProperty(value = "错误代码描述") + private String err_code_des; + + /** + * 交易类型 + */ + @XmlElement(name = "trade_type") + @ApiModelProperty(value = "交易类型") + private String trade_type; + + /** + * 预支付交易会话标识 + */ + @XmlElement(name = "prepay_id") + @ApiModelProperty(value = "预支付交易会话标识") + private String prepay_id; + + /** + * 二维码链接 + */ + @XmlElement(name = "code_url") + @ApiModelProperty(value = "二维码链接") + private String code_url; + + /** + * H5支付链接 + */ + @XmlElement(name = "mweb_url") + @ApiModelProperty(value = "H5支付链接") + private String mweb_url; + + /** + * 时间戳(公众号支付时返回) + */ + @ApiModelProperty(value = "时间戳(公众号支付时返回)") + private String time_stamp; + + /** + * 订单详情扩展字符串(公众号支付时返回) + */ + @ApiModelProperty(value = "订单详情扩展字符串(公众号支付时返回)") + private String package_; + /** + * 签名方式(公众号支付时返回) + */ + @ApiModelProperty(value = " 签名方式(公众号支付时返回)") + private String sign_type; + /** + * 签名(公众号支付时返回) + */ + @ApiModelProperty(value = "签名(公众号支付时返回)") + private String pay_sign; + + /** + * 生成订单详情扩展字符串 + */ + @JsonIgnore + public void setPackage() { + this.package_ = "prepay_id=" + prepay_id; + } + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return "FAIL".equals(this.return_code) || "FAIL".equals(this.result_code); + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getCode_url() { + return code_url; + } + + public void setCode_url(String code_url) { + this.code_url = code_url; + } + + public String getMweb_url() { + return mweb_url; + } + + public void setMweb_url(String mweb_url) { + this.mweb_url = mweb_url; + } + + public String getTime_stamp() { + return time_stamp; + } + + public void setTime_stamp(String time_stamp) { + this.time_stamp = time_stamp; + } + + public String getPackage_() { + return package_; + } + + public void setPackage_(String package_) { + this.package_ = package_; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getPay_sign() { + return pay_sign; + } + + public void setPay_sign(String pay_sign) { + this.pay_sign = pay_sign; + } + + @Override + public String toString() { + return "PrepayResult{" + + "return_code='" + return_code + '\'' + + ", return_msg='" + return_msg + '\'' + + ", appid='" + appid + '\'' + + ", mch_id='" + mch_id + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", sign='" + sign + '\'' + + ", result_code='" + result_code + '\'' + + ", err_code='" + err_code + '\'' + + ", err_code_des='" + err_code_des + '\'' + + ", trade_type='" + trade_type + '\'' + + ", prepay_id='" + prepay_id + '\'' + + ", code_url='" + code_url + '\'' + + ", mweb_url='" + mweb_url + '\'' + + ", time_stamp='" + time_stamp + '\'' + + ", package_='" + package_ + '\'' + + ", sign_type='" + sign_type + '\'' + + ", pay_sign='" + pay_sign + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/RequestParam.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/RequestParam.java new file mode 100644 index 0000000..80a6d05 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/RequestParam.java @@ -0,0 +1,147 @@ +package com.ruoyi.util.bean; + + +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; + +/** + * 发送短信请求变量实体类 + * + * @author 魔金商城 on 2017/9/7. + */ +public class RequestParam extends SendSmsRequest { + /** + * 短信接收号码 + * (支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式) + * 样例取值:15000000000 + * 是否必填:是 + */ + private String phoneNumbers; + /** + * 短信签名 + * 样例取值:云通信 + * 是否必填:是 + */ + private String signName; + /** + * 短信模板ID + * 样例取值:SMS_0000 + * 是否必填:是 + */ + private String templateCode; + /** + * 短信模板变量 + * (友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\r\n,否则会导致JSON在服务端解析失败) + * 样例取值:{“code”:”1234”,”product”:”ytx”} + * 是否必填:否 + */ + private String templateParam; + /** + * 上行短信扩展码,无特殊需要此字段的用户请忽略此字段 + * 样例取值:90999 + * 是否必填:否 + */ + private String smsUpExtendCode; + /** + * 外部流水扩展字段 + * 样例取值:abcdefgh + * 是否必填:否 + */ + private String outId; + /** + * 短信接口URL + */ + private String interfaceUrl; + /** + * accessKeyId + */ + private String accessKeyId; + /** + * accessKeySecret + */ + private String accessKeySecret; + + /** + * 参数 + */ + private String SmsParamString; + + public String getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(String phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } + + public String getSignName() { + return signName; + } + + public void setSignName(String signName) { + this.signName = signName; + } + + public String getTemplateCode() { + return templateCode; + } + + public void setTemplateCode(String templateCode) { + this.templateCode = templateCode; + } + + public String getTemplateParam() { + return templateParam; + } + + public void setTemplateParam(String templateParam) { + this.templateParam = templateParam; + } + + public String getSmsUpExtendCode() { + return smsUpExtendCode; + } + + public void setSmsUpExtendCode(String smsUpExtendCode) { + this.smsUpExtendCode = smsUpExtendCode; + } + + public String getOutId() { + return outId; + } + + public void setOutId(String outId) { + this.outId = outId; + } + + public String getInterfaceUrl() { + return interfaceUrl; + } + + public void setInterfaceUrl(String interfaceUrl) { + this.interfaceUrl = interfaceUrl; + } + + public String getAccessKeyId() { + return accessKeyId; + } + + public void setAccessKeyId(String accessKeyId) { + this.accessKeyId = accessKeyId; + } + + public String getAccessKeySecret() { + return accessKeySecret; + } + + public void setAccessKeySecret(String accessKeySecret) { + this.accessKeySecret = accessKeySecret; + } + + public String getSmsParamString() { + return SmsParamString; + } + + public void setSmsParamString(String smsParamString) { + SmsParamString = smsParamString; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/SegUserProfile.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/SegUserProfile.java new file mode 100644 index 0000000..f5023c6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/SegUserProfile.java @@ -0,0 +1,107 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 用户信息返回实体类 + */ +public class SegUserProfile { + + /** + * 用户信息对象 + */ + @JSONField(name = "userInfo") + private String userInfo; + + /** + * 不包括敏感信息的原始数据字符串,用于计算签名 + */ + @JSONField(name = "rawData") + private String rawData; + + /** + * 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息 + */ + @JSONField(name = "signature") + private String signature; + + /** + * 包括敏感数据在内的完整用户信息的加密数据 + */ + @JSONField(name = "encryptedData") + private String encryptedData; + + /** + * 加密算法的初始向量 + */ + @JSONField(name = "iv") + private String iv; + + /** + * 敏感数据对应的云 ID + */ + @JSONField(name = "cloudID") + private String cloudID; + + public String getUserInfo() { + return userInfo; + } + + public void setUserInfo(String userInfo) { + this.userInfo = userInfo; + } + + public String getRawData() { + return rawData; + } + + public void setRawData(String rawData) { + this.rawData = rawData; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public String getEncryptedData() { + return encryptedData; + } + + public void setEncryptedData(String encryptedData) { + this.encryptedData = encryptedData; + } + + public String getIv() { + return iv; + } + + public void setIv(String iv) { + this.iv = iv; + } + + public String getCloudID() { + return cloudID; + } + + public void setCloudID(String cloudID) { + this.cloudID = cloudID; + } + + @Override + public String toString() { + return "SegUserProfile{" + + "userInfo='" + userInfo + '\'' + + ", rawData='" + rawData + '\'' + + ", signature='" + signature + '\'' + + ", encryptedData='" + encryptedData + '\'' + + ", iv='" + iv + '\'' + + ", cloudID='" + cloudID + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UnionPaySetting.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UnionPaySetting.java new file mode 100644 index 0000000..6bb45a5 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UnionPaySetting.java @@ -0,0 +1,44 @@ +package com.ruoyi.util.bean; + + +/** + * 银联支付设置实体 + */ +public class UnionPaySetting { + /** + * 商户号 + */ + private String merchantNum; + /** + * 前台回调地址 + */ + private String beforeCallbackUrl; + /** + * 后台回调地址 + */ + private String backCallbackUrl; + + public String getMerchantNum() { + return merchantNum; + } + + public void setMerchantNum(String merchantNum) { + this.merchantNum = merchantNum; + } + + public String getBeforeCallbackUrl() { + return beforeCallbackUrl; + } + + public void setBeforeCallbackUrl(String beforeCallbackUrl) { + this.beforeCallbackUrl = beforeCallbackUrl; + } + + public String getBackCallbackUrl() { + return backCallbackUrl; + } + + public void setBackCallbackUrl(String backCallbackUrl) { + this.backCallbackUrl = backCallbackUrl; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserConstants.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserConstants.java new file mode 100644 index 0000000..0e038ce --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserConstants.java @@ -0,0 +1,89 @@ +package com.ruoyi.util.bean; + +/** + * 用户常量信息 + * + * @author shenzhuan + */ +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"; + + /** + * 校验返回结果码 + */ + public final static String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoProfile.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoProfile.java new file mode 100644 index 0000000..7a8531a --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoProfile.java @@ -0,0 +1,120 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 用户信息返回实体类 + */ +public class UserInfoProfile { + + /** + * 用户昵称 + */ + @JSONField(name = "nickName") + private String nickName; + + /** + * 用户头像图片的 URL + */ + @JSONField(name = "avatarUrl") + private String avatarUrl; + + /** + * 用户性别 + */ + @JSONField(name = "gender") + private String gender; + + /** + * 用户所在国家 + */ + @JSONField(name = "country") + private String country; + + /** + * 省份 + */ + @JSONField(name = "province") + private String province; + + /** + * 城市 + */ + @JSONField(name = "city") + private String city; + + /** + * 语言 + */ + @JSONField(name = "language") + private String language; + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public void setAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + @Override + public String toString() { + return "UserInfoProfile{" + + "nickName='" + nickName + '\'' + + ", avatarUrl='" + avatarUrl + '\'' + + ", gender='" + gender + '\'' + + ", country='" + country + '\'' + + ", province='" + province + '\'' + + ", city='" + city + '\'' + + ", language='" + language + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoResult.java new file mode 100644 index 0000000..9c7e4e7 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/UserInfoResult.java @@ -0,0 +1,179 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.StringUtils; + +/** + * 用户信息返回实体类 + */ +public class UserInfoResult { + + /** + * 用户唯一标志 + */ + @JSONField(name = "openid") + private String openid; + + /** + * 昵称 + */ + @JSONField(name = "nickname") + private String nickname; + + /** + * 性别 + */ + @JSONField(name = "sex") + private String sex; + + /** + * 省份 + */ + @JSONField(name = "province") + private String province; + + /** + * 城市 + */ + @JSONField(name = "city") + private String city; + + /** + * 国家 + */ + @JSONField(name = "country") + private String country; + + /** + * + */ + @JSONField(name = "headimgurl") + private String headimgurl; + + /** + * 联合登录id 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + */ + @JSONField(name = "unionid") + private String unionid; + + /** + * 错误码(出错时返回) + */ + @JSONField(name = "errcode") + private String errcode; + + /** + * 错误信息(出错时返回) + */ + @JSONField(name = "errmsg") + private String errmsg; + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return !StringUtils.isEmpty(this.errcode); + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getHeadimgurl() { + return headimgurl; + } + + public void setHeadimgurl(String headimgurl) { + this.headimgurl = headimgurl; + } + + public String getUnionid() { + return unionid; + } + + public void setUnionid(String unionid) { + this.unionid = unionid; + } + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + /** + * 转换为字符串 + */ + @Override + public String toString() { + return "UserInfoResult{" + + "openid='" + openid + '\'' + + ", nickname='" + nickname + '\'' + + ", sex='" + sex + '\'' + + ", province='" + province + '\'' + + ", city='" + city + '\'' + + ", country='" + country + '\'' + + ", headimgurl='" + headimgurl + '\'' + + ", unionid='" + unionid + '\'' + + ", errcode='" + errcode + '\'' + + ", errmsg='" + errmsg + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WeChatAppletCodeRequest.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WeChatAppletCodeRequest.java new file mode 100644 index 0000000..593b555 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WeChatAppletCodeRequest.java @@ -0,0 +1,104 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 生成微信小程序码请求实体类 + * + * @author 魔金商城 created on 2020/4/14 + */ +@ApiModel(description = "生成微信小程序码请求实体") +public class WeChatAppletCodeRequest { + + /** + * 参数,最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + */ + @ApiModelProperty(value = "参数") + @JSONField(name = "scene") + private String scene; + + /** + * 路径,必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面 + */ + @ApiModelProperty(value = "路径") + @JSONField(name = "page") + private String page; + + /** + * 二维码的宽度,单位 px,最小 280px,最大 1280px,默认 430 + */ + @ApiModelProperty(value = "二维码的宽度") + @JSONField(name = "width") + private int width; + + /** + * 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false + */ + @ApiModelProperty(value = "是否自动配置线条颜色") + @JSONField(name = "auto_color") + private boolean auto_color; + + /** + * 颜色实体,auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 + */ + @ApiModelProperty(value = "颜色实体") + @JSONField(name = "line_color") + private LineColor line_color; + + /** + * 是否需要透明底色,为 true 时,生成透明底色的小程序,默认 false + */ + @ApiModelProperty(value = "是否需要透明底色") + @JSONField(name = "is_hyaline") + private boolean is_hyaline; + + public String getScene() { + return scene; + } + + public void setScene(String scene) { + this.scene = scene; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public boolean isAuto_color() { + return auto_color; + } + + public void setAuto_color(boolean auto_color) { + this.auto_color = auto_color; + } + + public LineColor getLine_color() { + return line_color; + } + + public void setLine_color(LineColor line_color) { + this.line_color = line_color; + } + + public boolean isIs_hyaline() { + return is_hyaline; + } + + public void setIs_hyaline(boolean is_hyaline) { + this.is_hyaline = is_hyaline; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatApletPrepayResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatApletPrepayResult.java new file mode 100644 index 0000000..b443ae3 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatApletPrepayResult.java @@ -0,0 +1,121 @@ +package com.ruoyi.util.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 微信公众号,小程序支付返回实体类 + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "xml") +@ApiModel(description = "微信公众号,小程序支付返回实体类") +public class WechatApletPrepayResult { + + /** + * 返回状态码 + */ + @XmlElement(name = "appId") + @ApiModelProperty(value = "appId") + private String appId; + + /** + * 随机字符串 + */ + @XmlElement(name = "nonceStr") + @ApiModelProperty(value = "随机字符串") + private String nonceStr; + + /** + * 订单详情扩展字符串(公众号支付时返回) + */ + @XmlElement(name = "package_") + @ApiModelProperty(value = "订单详情扩展字符串(公众号支付时返回)") + private String package_; + + /** + * 签名方式 + */ + @XmlElement(name = "signType") + @ApiModelProperty(value = "签名方式(公众号支付时返回)") + private String signType; + + /** + * 时间戳 + */ + @XmlElement(name = "timeStamp") + @ApiModelProperty(value = "时间戳(公众号支付时返回)") + private String timeStamp; + + /** + * 签名 + */ + @XmlElement(name = "paySign") + @ApiModelProperty(value = "签名(公众号支付时返回)") + private String paySign; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getNonceStr() { + return nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public String getPackage_() { + return package_; + } + + public void setPackage_(String package_) { + this.package_ = package_; + } + + public String getSignType() { + return signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + + public String getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getPaySign() { + return paySign; + } + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + @Override + public String toString() { + return "WechatApletPrepayResult{" + + "appId='" + appId + '\'' + + ", nonceStr='" + nonceStr + '\'' + + ", package_='" + package_ + '\'' + + ", signType='" + signType + '\'' + + ", timeStamp='" + timeStamp + '\'' + + ", paySign='" + paySign + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatNotifyResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatNotifyResult.java new file mode 100644 index 0000000..44f7197 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatNotifyResult.java @@ -0,0 +1,225 @@ +package com.ruoyi.util.bean; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 统一下单接口返回实体类 + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "xml") +public class WechatNotifyResult { + + /** + * 返回状态码 + */ + @XmlElement(name = "return_code") + private String return_code; + + /** + * 返回信息 + */ + @XmlElement(name = "return_msg") + private String return_msg; + + /** + * 公众账号ID + */ + @XmlElement(name = "appid") + private String appid; + + /** + * 商户号 + */ + @XmlElement(name = "mch_id") + private String mch_id; + + /** + * 随机字符串 + */ + @XmlElement(name = "nonce_str") + private String nonce_str; + + /** + * 签名 + */ + @XmlElement(name = "sign") + private String sign; + + /** + * 业务结果 + */ + @XmlElement(name = "result_code") + private String result_code; + + /** + * 错误代码 + */ + @XmlElement(name = "err_code") + private String err_code; + + /** + * 错误代码描述 + */ + @XmlElement(name = "err_code_des") + private String err_code_des; + + /** + * 交易类型 + */ + @XmlElement(name = "trade_type") + private String trade_type; + + /** + * 附加参数(交易类型) + */ + @XmlElement(name = "attach") + private int attach; + + /** + * 订单号 + */ + @XmlElement(name = "out_trade_no") + private String out_trade_no; + + /** + * 微信交易流水号 + */ + @XmlElement(name = "transaction_id") + private String transaction_id; + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return "FAIL".equals(this.return_code); + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public int getAttach() { + return attach; + } + + public void setAttach(int attach) { + this.attach = attach; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + @Override + public String toString() { + return "WechatNotifyResult{" + + "return_code='" + return_code + '\'' + + ", return_msg='" + return_msg + '\'' + + ", appid='" + appid + '\'' + + ", mch_id='" + mch_id + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", sign='" + sign + '\'' + + ", result_code='" + result_code + '\'' + + ", err_code='" + err_code + '\'' + + ", err_code_des='" + err_code_des + '\'' + + ", trade_type='" + trade_type + '\'' + + ", attach=" + attach + + ", out_trade_no='" + out_trade_no + '\'' + + ", transaction_id='" + transaction_id + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponse.java new file mode 100644 index 0000000..6a14738 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponse.java @@ -0,0 +1,69 @@ +package com.ruoyi.util.bean; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.math.BigDecimal; + +/** + * 微信支付返回实体(订单支付) + */ +@ApiModel(description = "微信支付返回实体") +public class WechatPayResponse { + + /** + * 订单code + */ + @ApiModelProperty(value = "订单code") + private String orderCode; + + /** + * 订单总金额 + */ + @ApiModelProperty(value = "订单总金额") + private BigDecimal orderMoney; + + /** + * 扫码支付url + */ + @ApiModelProperty(value = "扫码支付url") + private String codeUrl; + + /** + * mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。 + */ + @ApiModelProperty(value = "mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。") + private String mwebUrl; + + public String getOrderCode() { + return orderCode; + } + + public void setOrderCode(String orderCode) { + this.orderCode = orderCode; + } + + public BigDecimal getOrderMoney() { + return orderMoney; + } + + public void setOrderMoney(BigDecimal orderMoney) { + this.orderMoney = orderMoney; + } + + public String getCodeUrl() { + return codeUrl; + } + + public void setCodeUrl(String codeUrl) { + this.codeUrl = codeUrl; + } + + public String getMwebUrl() { + return mwebUrl; + } + + public void setMwebUrl(String mwebUrl) { + this.mwebUrl = mwebUrl; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponseForRecharge.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponseForRecharge.java new file mode 100644 index 0000000..89a892d --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WechatPayResponseForRecharge.java @@ -0,0 +1,62 @@ +package com.ruoyi.util.bean; + + +import java.math.BigDecimal; + +/** + * 微信支付返回实体(充值) + */ +public class WechatPayResponseForRecharge { + + /** + * 订单code + */ + private String transCode; + + /** + * 订单总金额 + */ + private BigDecimal money; + + /** + * 扫码支付url + */ + private String codeUrl; + + /** + * mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。 + */ + private String mwebUrl; + + public String getTransCode() { + return transCode; + } + + public void setTransCode(String transCode) { + this.transCode = transCode; + } + + public BigDecimal getMoney() { + return money; + } + + public void setMoney(BigDecimal money) { + this.money = money; + } + + public String getCodeUrl() { + return codeUrl; + } + + public void setCodeUrl(String codeUrl) { + this.codeUrl = codeUrl; + } + + public String getMwebUrl() { + return mwebUrl; + } + + public void setMwebUrl(String mwebUrl) { + this.mwebUrl = mwebUrl; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawRequest.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawRequest.java new file mode 100644 index 0000000..5443edd --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawRequest.java @@ -0,0 +1,73 @@ +package com.ruoyi.util.bean; + + +import java.math.BigDecimal; + +/** + * Created by 魔金商城 on 18/2/7. + * 提现请求实体 + */ +public class WithdrawRequest { + + /** + * 交流流水号 + */ + private String tradeNo; + + /** + * 支付包账户 + */ + private String account; + + /** + * 支付包实名认证姓名 + */ + private String name; + + /** + * 提现金额 + */ + private BigDecimal money; + + public String getTradeNo() { + return tradeNo; + } + + public void setTradeNo(String tradeNo) { + this.tradeNo = tradeNo; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getMoney() { + return money; + } + + public void setMoney(BigDecimal money) { + this.money = money; + } + + @Override + public String toString() { + return "WithdrawRequest{" + + "tradeNo='" + tradeNo + '\'' + + ", account='" + account + '\'' + + ", name='" + name + '\'' + + ", money=" + money + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawResponse.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawResponse.java new file mode 100644 index 0000000..998b02f --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WithdrawResponse.java @@ -0,0 +1,77 @@ +package com.ruoyi.util.bean; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * Created by 魔金商城 on 18/02/07. + * 提现返回实体 + */ +@ApiModel(description = "提现返回实体") +public class WithdrawResponse { + + /** + * 返回code + */ + @ApiModelProperty(value = "返回code") + private String code; + /** + * 业务code + */ + @ApiModelProperty(value = "业务code") + private String subCode; + + private WithdrawResponse() { + + } + + /** + * 构造提现返回实体 + * + * @param code 返回code + * @param subCode 业务返回code + * @return 返回提现返回实体 + */ + public static WithdrawResponse build(String code, String subCode) { + WithdrawResponse withdrawResponse = new WithdrawResponse(); + withdrawResponse.code = code; + withdrawResponse.subCode = subCode; + return withdrawResponse; + } + + /** + * 构造系统异常实体 + * + * @return 返回提现相应实体 + */ + public static WithdrawResponse buildSystemError() { + WithdrawResponse withdrawResponse = new WithdrawResponse(); + withdrawResponse.code = "-10001"; + return withdrawResponse; + } + + /** + * 是否提现成功 + * + * @return 成功返回true + */ + public boolean isSuccess() { + return "10000".equals(this.code); + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getSubCode() { + return subCode; + } + + public void setSubCode(String subCode) { + this.subCode = subCode; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WxTransferResult.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WxTransferResult.java new file mode 100644 index 0000000..b042b07 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/bean/WxTransferResult.java @@ -0,0 +1,352 @@ +package com.ruoyi.util.bean; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 统一下单接口返回实体类 + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "xml") +@ApiModel(description = "统一下单接口返回实体类") +public class WxTransferResult { + + /** + * 返回状态码 + */ + @XmlElement(name = "return_code") + @ApiModelProperty(value = "返回状态码") + @JSONField(name = "return_code") + private String return_code; + + /** + * 返回信息 + */ + @XmlElement(name = "return_msg") + @ApiModelProperty(value = "返回信息") + @JSONField(name = "return_msg") + private String return_msg; + + /** + * 公众账号ID + */ + @XmlElement(name = "mch_appid") + @ApiModelProperty(value = "商户appid") + @JSONField(name = "mch_appid") + private String mch_appid; + + /** + * 商户号 + */ + @XmlElement(name = "mchid") + @ApiModelProperty(value = "商户号") + @JSONField(name = "mchid") + private String mchid; + + /** + * 随机字符串 + */ + @XmlElement(name = "nonce_str") + @ApiModelProperty(value = "随机字符串") + @JSONField(name = "nonce_str") + private String nonce_str; + + /** + * 签名 + */ + @XmlElement(name = "sign") + @ApiModelProperty(value = "签名") + private String sign; + + /** + * 业务结果 + */ + @XmlElement(name = "result_code") + @ApiModelProperty(value = "业务结果") + @JSONField(name = "result_code") + private String result_code; + + /** + * 错误代码 + */ + @XmlElement(name = "err_code") + @ApiModelProperty(value = "错误代码") + @JSONField(name = "err_code") + private String err_code; + + /** + * 错误代码描述 + */ + @XmlElement(name = "err_code_des") + @ApiModelProperty(value = "错误代码描述") + @JSONField(name = "err_code_des") + private String err_code_des; + + /** + * 商户订单号 + */ + @XmlElement(name = "partner_trade_no") + @ApiModelProperty(value = "商户订单号") + @JSONField(name = "partner_trade_no") + private String partner_trade_no; + + /** + * 微信付款单号 + */ + @XmlElement(name = "payment_no") + @ApiModelProperty(value = "微信付款单号") + @JSONField(name = "payment_no") + private String payment_no; + + /** + * 付款成功时间 + */ + @XmlElement(name = "payment_time") + @ApiModelProperty(value = "付款成功时间") + @JSONField(name = "payment_time") + private String payment_time; + + /** + * 预支付交易会话标识 + */ + @XmlElement(name = "prepay_id") + @ApiModelProperty(value = "预支付交易会话标识") + @JSONField(name = "prepay_id") + private String prepay_id; + + /** + * 二维码链接 + */ + @XmlElement(name = "code_url") + @ApiModelProperty(value = "二维码链接") + private String code_url; + + /** + * H5支付链接 + */ + @XmlElement(name = "mweb_url") + @ApiModelProperty(value = "H5支付链接") + private String mweb_url; + + /** + * 时间戳(公众号支付时返回) + */ + @ApiModelProperty(value = "时间戳(公众号支付时返回)") + private String time_stamp; + + /** + * 订单详情扩展字符串(公众号支付时返回) + */ + @ApiModelProperty(value = "订单详情扩展字符串(公众号支付时返回)") + private String package_; + /** + * 签名方式(公众号支付时返回) + */ + @ApiModelProperty(value = " 签名方式(公众号支付时返回)") + private String sign_type; + /** + * 签名(公众号支付时返回) + */ + @ApiModelProperty(value = "签名(公众号支付时返回)") + private String pay_sign; + + /** + * 生成订单详情扩展字符串 + */ + @JsonIgnore + public void setPackage() { + this.package_ = "prepay_id=" + prepay_id; + } + + /** + * 判断是否失败 + */ + @JsonIgnore + public boolean isError() { + return "FAIL".equals(this.return_code); + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getMch_appid() { + return mch_appid; + } + + public void setMch_appid(String mch_appid) { + this.mch_appid = mch_appid; + } + + public String getMchid() { + return mchid; + } + + public void setMchid(String mchid) { + this.mchid = mchid; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getPartner_trade_no() { + return partner_trade_no; + } + + public void setPartner_trade_no(String partner_trade_no) { + this.partner_trade_no = partner_trade_no; + } + + public String getPayment_no() { + return payment_no; + } + + public void setPayment_no(String payment_no) { + this.payment_no = payment_no; + } + + public String getPayment_time() { + return payment_time; + } + + public void setPayment_time(String payment_time) { + this.payment_time = payment_time; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getCode_url() { + return code_url; + } + + public void setCode_url(String code_url) { + this.code_url = code_url; + } + + public String getMweb_url() { + return mweb_url; + } + + public void setMweb_url(String mweb_url) { + this.mweb_url = mweb_url; + } + + public String getTime_stamp() { + return time_stamp; + } + + public void setTime_stamp(String time_stamp) { + this.time_stamp = time_stamp; + } + + public String getPackage_() { + return package_; + } + + public void setPackage_(String package_) { + this.package_ = package_; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getPay_sign() { + return pay_sign; + } + + public void setPay_sign(String pay_sign) { + this.pay_sign = pay_sign; + } + + @Override + public String toString() { + return "WxTransferResult{" + + "return_code='" + return_code + '\'' + + ", return_msg='" + return_msg + '\'' + + ", mch_appid='" + mch_appid + '\'' + + ", mchid='" + mchid + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", sign='" + sign + '\'' + + ", result_code='" + result_code + '\'' + + ", err_code='" + err_code + '\'' + + ", err_code_des='" + err_code_des + '\'' + + ", partner_trade_no='" + partner_trade_no + '\'' + + ", payment_no='" + payment_no + '\'' + + ", payment_time='" + payment_time + '\'' + + ", prepay_id='" + prepay_id + '\'' + + ", code_url='" + code_url + '\'' + + ", mweb_url='" + mweb_url + '\'' + + ", time_stamp='" + time_stamp + '\'' + + ", package_='" + package_ + '\'' + + ", sign_type='" + sign_type + '\'' + + ", pay_sign='" + pay_sign + '\'' + + '}'; + } +} diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5.java new file mode 100644 index 0000000..af73692 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5.java @@ -0,0 +1,59 @@ +package com.ruoyi.util.md5; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5 { + + private MD5() { + } + + public final static String getMessageDigest(byte[] buffer) { + //首先初始化一个字符数组,用来存放每个16进制字符 + char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + try { + // 拿到一个MD5转换器(如果想要SHA1参数换成"SHA1") + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); + // buffer 是输入字符串转换得到的字节数组 + mdTemp.update(buffer); + // 转换并返回结果,也是字节数组,包含16个元素 + byte[] md = mdTemp.digest(); + + int j = md.length; + // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)) + 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); + } catch (Exception e) { + return null; + } + } + + public static String hex(byte[] array) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < array.length; ++i) { + sb.append(Integer.toHexString((array[i] + & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString(); + } + + public static String md5Hex(String message) { + try { + MessageDigest md = + MessageDigest.getInstance("MD5"); + return hex(md.digest(message.getBytes("CP1252"))); + } catch (NoSuchAlgorithmException e) { + } catch (UnsupportedEncodingException e) { + } + return null; + } +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5Utils.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5Utils.java new file mode 100644 index 0000000..dabcfa4 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MD5Utils.java @@ -0,0 +1,121 @@ +package com.ruoyi.util.md5; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * md5工具类 + */ +public class MD5Utils { + + private static final MD5Utils INSTANCE = new MD5Utils(); + /** + * 调试日志 + */ + private Logger logger = LoggerFactory.getLogger(MD5Utils.class); + + private MD5Utils() { + + } + + public static MD5Utils getInstance() { + return INSTANCE; + } + + /** + * 判断订单号是否含有中文 + * + * @param waybillCode 订单号 + * @return true 含有中文 false 不含中文 + */ + public boolean isContainChinese(String waybillCode) { + + Pattern p = Pattern.compile("[\u4e00-\u9fa5]"); + Matcher m = p.matcher(waybillCode); + if (m.find()) { + return true; + } + return false; + } + + /** + * 创建md5值 + * + * @param string 待加密的字符串 + * @return 返回加密后的值 + */ + public String createMd5(String string) { + String result = ""; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(string.getBytes("utf-8")); + byte b[] = md.digest(); + int i; + StringBuilder buf = new StringBuilder(); + for (int offset = 0; offset < b.length; offset++) { + i = b[offset]; + if (i < 0) { + i += 256; + } + if (i < 16) { + buf.append("0"); + } + + buf.append(Integer.toHexString(i)); + } + return buf.toString(); + } catch (NoSuchAlgorithmException e) { + logger.error("createMd5 fail...", e); + } catch (UnsupportedEncodingException e) { + logger.error("createMd5 fail...", e); + } + return result; + } + + /** + * 生成md5值 + * + * @param is 输入流 + * @return 返回md5加密后的字符串 + * @throws IOException + */ + public String createMd5ForImageUpload(InputStream is) throws IOException { + char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + byte[] j = new byte[1024]; + while (true) { + int var14 = is.read(j); + if (var14 > 0) { + md5.update(j, 0, var14); + } + if (var14 == -1) { + is.skip(0L); + break; + } + } + } catch (NoSuchAlgorithmException var12) { + throw new RuntimeException(var12.getMessage()); + } finally { + is.close(); + } + byte[] var15 = md5.digest(); + int var16 = var15.length; + char[] finalValue = new char[var16 * 2]; + int k = 0; + for (byte encoded : var15) { + finalValue[k++] = hexDigits[encoded >> 4 & 15]; + finalValue[k++] = hexDigits[encoded & 15]; + } + return new String(finalValue); + } +} \ No newline at end of file diff --git a/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MessageSourceUtil.java b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MessageSourceUtil.java new file mode 100644 index 0000000..86b3dd6 --- /dev/null +++ b/ruoyi-segchk/src/main/java/com/ruoyi/util/md5/MessageSourceUtil.java @@ -0,0 +1,38 @@ +package com.ruoyi.util.md5; + +import com.ruoyi.common.utils.spring.SpringUtils; +import org.springframework.context.MessageSource; +import org.springframework.context.NoSuchMessageException; +import org.springframework.context.i18n.LocaleContextHolder; + + +/** + * 消息资源根据类 + * Created by 魔金商城 on 17/7/10. + */ +public final class MessageSourceUtil { + private static MessageSource messageSource; + + static { + init((MessageSource) SpringUtils.getBean(MessageSource.class)); + } + + public static void init(MessageSource messageSource) { + MessageSourceUtil.messageSource = messageSource; + } + + + /** + * 根据code 获得国际化文件中的值 + * + * @param code key + * @return 返回值 + */ + public static String getMessage(String code) { + try { + return messageSource.getMessage(code, null, LocaleContextHolder.getLocale()); + } catch (NoSuchMessageException e) { + return null; + } + } +} diff --git a/ruoyi-segchk/src/main/resources/mapper/member/WeChatCustomerLinkMapper.xml b/ruoyi-segchk/src/main/resources/mapper/member/WeChatCustomerLinkMapper.xml new file mode 100644 index 0000000..2ac0ebb --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/member/WeChatCustomerLinkMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + INSERT into ls_wx_customer_link + + + customer_id, + + + wx_union_id, + + + wx_open_id, + + + wx_applet_open_id, + + + + + #{customerId}, + + + #{unionId}, + + + #{openId}, + + + #{appletOpenId}, + + + + + DELETE from ls_wx_customer_link where customer_id=#{customerId} + + + + update ls_wx_customer_link + + + + wx_open_id=#{openId}, + + + wx_applet_open_id=#{appletOpenId}, + + + + where id=#{id}; + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkProviderIndexMapper.xml b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkProviderIndexMapper.xml new file mode 100644 index 0000000..568f7ab --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkProviderIndexMapper.xml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select openid, union_id, wechat_id, provider_id, nick_name, icon_url, phone_no, flag_id, District_id, create_time, del_time, update_time from segchk_provider_mgt + + + + + + + + insert into segchk_provider_mgt + + openid, + union_id, + wechat_id, + nick_name, + icon_url, + phone_no, + flag_id, + District_id, + create_time, + del_time, + update_time, + + + #{openid}, + #{unionId}, + #{wechatId}, + #{nickName}, + #{iconUrl}, + #{phoneNo}, + #{flagId}, + #{districtId}, + #{createTime}, + #{delTime}, + #{updateTime}, + + + + + update segchk_provider_mgt + + openid = #{openid}, + union_id = #{unionId}, + nick_name = #{nickName}, + icon_url = #{iconUrl}, + phone_no = #{phoneNo}, + flag_id = #{flagId}, + District_id = #{districtId}, + create_time = #{createTime}, + del_time = #{delTime}, + update_time = #{updateTime}, + + where provider_id = #{providerId} + + + + delete from segchk_provider_mgt where provider_id = #{providerId} + + + + delete from segchk_provider_mgt where provider_id in + + #{providerId} + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkStoreIndexMapper.xml b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkStoreIndexMapper.xml new file mode 100644 index 0000000..d2f5cbe --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkStoreIndexMapper.xml @@ -0,0 +1,801 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select provider_id, store_id, store_carousel, sort_id from segchk_carouse_mgt + + + insert into segchk_store_account (store_id, account, reward_id, charge_id, mod_time, provider_id) + + select suc.store_id, if(isnull(ssa.account), #{reward}, ssa.account + #{reward}) as account, reward_id, charge_id, now(), provider_id from + (select #{userRecommenders} as store_id + , #{rewardId} as reward_id + , #{chargeId} as charge_id + , #{providerId} as provider_id + ) suc + left join + ( + + select account, store_id from segchk_store_account where store_id = #{userRecommenders} order by account_id desc limit 1 + ) ssa + on ssa.store_id = suc.store_id + + + insert into segchk_comment_acc ( + star_count + , star_level + , store_id + , provider_id + , mod_time + , comment_id) + select + if(isnull(sca.star_count), ssc.cnt, ssc.cnt + sca.star_count) as star_count + , if(isnull(sca.star_level), ssc.star_level, ssc.star_level + sca.star_level) as start_level + , ssc.store_id + , ssc.provider_id + , now() + , ssc.comment_id from + (select provider_id, store_id, comment_id, 1 as cnt, star_level from segchk_service_comment where comment_id = #{commentId}) ssc + left join + (select provider_id, store_id, star_count, star_level from segchk_comment_acc where store_id = (select store_id from segchk_service_comment where comment_id = #{commentId}) order by update_id limit 1) sca + on sca.provider_id = ssc.provider_id and sca.store_id = ssc.store_id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkUserIndexMapper.xml b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkUserIndexMapper.xml new file mode 100644 index 0000000..f81ab3f --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/segchk/SegchkUserIndexMapper.xml @@ -0,0 +1,858 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into segchk_user_wechat + + provider_id, + user_id, + openid, + union_id, + nick_name, + icon_url, + mod_time, + + + #{providerId}, + #{userId}, + #{openid}, + #{unionId}, + #{nickName}, + #{iconUrl}, + now(), + + on duplicate key update + + provider_id = #{providerId}, + openid = #{openid}, + union_id = #{unionId}, + nick_name = #{nickName}, + icon_url = #{iconUrl}, + mod_time = now(), + + + + insert into segchk_user_account (user_id, account, provider_id, reward_id, charge_id, mod_time) + + select suc.user_id, if(isnull(ssa.account), #{reward}, ssa.account + #{reward}) as account, provider_id, reward_id, charge_id, now() from + (select + #{userRecommenders} as user_id + , #{rewardId} as reward_id + , #{chargeId} as charge_id + , #{providerId} as provider_id + ) suc + left join + ( + + select account, user_id from segchk_user_account where user_id = #{userRecommenders} order by account_id desc limit 1 + ) ssa + on ssa.user_id = suc.user_id + + + + update segchk_store_basic_info + + openid = #{openid}, + union_id = #{unionId}, + nick_name = #{nickName}, + icon_url = #{iconUrl}, + mod_time = now(), + + where store_id = #{userId} and provider_id = #{providerId} + + + + update segchk_provider_mgt + + openid = #{openid}, + union_id = #{unionId}, + wechat_id = #{wechatId}, + nick_name = #{nickName}, + icon_url = #{iconUrl}, + update_time = now(), + + where provider_id = #{providerId} + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/AreaMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/AreaMapper.xml new file mode 100644 index 0000000..cdac3e7 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/AreaMapper.xml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into ls_province + + + name, + + + sort, + + + del_flag, + + + create_time, + + + modify_time, + + + del_time, + + + + + #{name}, + + + #{sort}, + + + #{delFlag}, + + + #{createTime}, + + + #{modifyTime}, + + + #{delTime}, + + + + + + + insert into ls_city + + + name, + + + province_id, + + + sort, + + + del_flag, + + + create_time, + + + modify_time, + + + del_time, + + + + + #{name}, + + + #{provinceId}, + + + #{sort}, + + + #{delFlag}, + + + #{createTime}, + + + #{modifyTime}, + + + #{delTime}, + + + + + + + insert into ls_district + + + name, + + + city_id, + + + sort, + + + del_flag, + + + create_time, + + + modify_time, + + + del_time, + + + + + #{name}, + + + #{cityId}, + + + #{sort}, + + + #{delFlag}, + + + #{createTime}, + + + #{modifyTime}, + + + #{delTime}, + + + + + + + + + + + + + + + update ls_province + set del_flag = '1',del_time = now() + where id = #{provinceId} + + + + update ls_city + set del_flag = '1',del_time = now() + where id = #{cityId} + + + + update ls_district + set del_flag = '1',del_time = now() + where id = #{districtId} + + + + + + + + + update ls_province + + + name = #{name}, + + + sort = #{sort}, + + modify_time = now() + + where id = #{id} + + + + update ls_city + + + name = #{name}, + + + sort = #{sort}, + + modify_time = now() + + where id = #{id} + + + update ls_district + + + name = #{name}, + + + sort = #{sort}, + + modify_time = now() + + where id = #{id} + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/BaseInfoSetMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/BaseInfoSetMapper.xml new file mode 100644 index 0000000..49a749b --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/BaseInfoSetMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id,phone,logo,site_url,site_name,label_log,admin_logo,captcha_open,site_login,store_login,site_register,store_register,copyright_info,admin_index_logo, + store_open_protocol,register_protocol + ,user_privacy_agreement,vip_service_agreement + ,store_register_protocol,store_spu_audit,member_price_status,crowdfunding_protocol,h5_call_back_domain,pc_call_back_domain + + + + + UPDATE segchk_system_setting SET + phone=#{phone},logo=#{logo},site_url=#{siteUrl},site_name=#{siteName},label_log=#{labelLog},admin_logo=#{adminLogo}, + site_login=#{siteLoginPic},store_login=#{storeLoginPic},site_register=#{siteRegisterPic},store_register=#{storeRegisterPic}, + copyright_info=#{copyrightInfo},admin_index_logo=#{adminIndexLogo},store_open_protocol=#{storeOpenProtocol},register_protocol=#{siteRegisterProtocol} + ,user_privacy_agreement=#{userPrivacyAgreement}, + ,vip_service_agreement=#{vipServiceAgreement}, + store_register_protocol=#{storeRegisterProtocol},crowdfunding_protocol=#{crowdFundingProtocol}, + h5_call_back_domain=#{h5CallBackDomain},pc_call_back_domain=#{pcCallBackDomain} + + + UPDATE segchk_system_setting SET captcha_open = #{captchaOpen} + + + UPDATE segchk_system_setting SET store_spu_audit = #{storeSpuAudit} + + + UPDATE segchk_system_setting SET member_price_status = #{memberPriceStatus} + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsCityMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsCityMapper.xml new file mode 100644 index 0000000..cc125f1 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsCityMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + select id, name, province_id, sort, del_flag, create_time, modify_time, del_time from ls_city + + + + + + + + insert into ls_city + + name, + province_id, + sort, + del_flag, + create_time, + modify_time, + del_time, + + + #{name}, + #{provinceId}, + #{sort}, + #{delFlag}, + #{createTime}, + #{modifyTime}, + #{delTime}, + + + + + update ls_city + + name = #{name}, + province_id = #{provinceId}, + sort = #{sort}, + del_flag = #{delFlag}, + create_time = #{createTime}, + modify_time = #{modifyTime}, + del_time = #{delTime}, + + where id = #{id} + + + + delete from ls_city where id = #{id} + + + + delete from ls_city where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsDistrictMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsDistrictMapper.xml new file mode 100644 index 0000000..7543561 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsDistrictMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + select id, name, city_id, sort, del_flag, create_time, modify_time, del_time from ls_district + + + + + + + + insert into ls_district + + name, + city_id, + sort, + del_flag, + create_time, + modify_time, + del_time, + + + #{name}, + #{cityId}, + #{sort}, + #{delFlag}, + #{createTime}, + #{modifyTime}, + #{delTime}, + + + + + update ls_district + + name = #{name}, + city_id = #{cityId}, + sort = #{sort}, + del_flag = #{delFlag}, + create_time = #{createTime}, + modify_time = #{modifyTime}, + del_time = #{delTime}, + + where id = #{id} + + + + delete from ls_district where id = #{id} + + + + delete from ls_district where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsEmailSettingMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsEmailSettingMapper.xml new file mode 100644 index 0000000..8e8f2fe --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsEmailSettingMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + select id, sender_mail, sender_name, smtp_server, smtp_port, username, password from ls_email_setting + + + + + + + + insert into ls_email_setting + + sender_mail, + sender_name, + smtp_server, + smtp_port, + username, + password, + + + #{senderMail}, + #{senderName}, + #{smtpServer}, + #{smtpPort}, + #{username}, + #{password}, + + + + + update ls_email_setting + + sender_mail = #{senderMail}, + sender_name = #{senderName}, + smtp_server = #{smtpServer}, + smtp_port = #{smtpPort}, + username = #{username}, + password = #{password}, + + where id = #{id} + + + + delete from ls_email_setting where id = #{id} + + + + delete from ls_email_setting where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsProvinceMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsProvinceMapper.xml new file mode 100644 index 0000000..ff7e269 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsProvinceMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + select id, name, sort, del_flag, create_time, modify_time, del_time from ls_province + + + + + + + + insert into ls_province + + name, + sort, + del_flag, + create_time, + modify_time, + del_time, + + + #{name}, + #{sort}, + #{delFlag}, + #{createTime}, + #{modifyTime}, + #{delTime}, + + + + + update ls_province + + name = #{name}, + sort = #{sort}, + del_flag = #{delFlag}, + create_time = #{createTime}, + modify_time = #{modifyTime}, + del_time = #{delTime}, + + where id = #{id} + + + + delete from ls_province where id = #{id} + + + + delete from ls_province where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsSmsSettingMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsSmsSettingMapper.xml new file mode 100644 index 0000000..de42d01 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsSmsSettingMapper.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + select id, secret, url, sign, template_id, writeoff_template_id, virtual_order_template_id, `key`, audit_template_id, settlement_template_id, withdraw_template_id, status from segchk_sms_setting + + + + + + + + insert into segchk_sms_setting + + secret, + url, + sign, + template_id, + writeoff_template_id, + virtual_order_template_id, + key, + audit_template_id, + settlement_template_id, + withdraw_template_id, + + + #{secret}, + #{url}, + #{sign}, + #{templateId}, + #{writeoffTemplateId}, + #{virtualOrderTemplateId}, + #{key}, + #{auditTemplateId}, + #{settlementTemplateId}, + #{withdrawTemplateId}, + + + + + update segchk_sms_setting + + secret = #{secret}, + url = #{url}, + sign = #{sign}, + template_id = #{templateId}, + writeoff_template_id = #{writeoffTemplateId}, + virtual_order_template_id = #{virtualOrderTemplateId}, + key = #{key}, + audit_template_id = #{auditTemplateId}, + settlement_template_id = #{settlementTemplateId}, + withdraw_template_id = #{withdrawTemplateId}, + + where id = #{id} + + + + delete from segchk_sms_setting where id = #{id} + + + + delete from segchk_sms_setting where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsStationLetterMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsStationLetterMapper.xml new file mode 100644 index 0000000..17e1e03 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsStationLetterMapper.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + select id, customer_id, title, content, is_read, del_flag, create_time from ls_station_letter + + + insert into ls_station_letter + + (customer_id,title, content, is_read, del_flag,create_time) + values + + ( + #{stationLetter.customerId}, + #{stationLetter.title}, + #{stationLetter.content}, + '0', + '0', + now() + ) + + + + + + + + + UPDATE ls_station_letter SET del_flag = '1' WHERE id = #{id} + + + + UPDATE ls_station_letter SET is_read = '1' WHERE id = #{id} and customer_id = #{customerId} + + + + + + + + + insert into ls_station_letter + + customer_id, + title, + content, + is_read, + del_flag, + create_time, + + + #{customerId}, + #{title}, + #{content}, + #{isRead}, + #{delFlag}, + #{createTime}, + + + + + update ls_station_letter + + customer_id = #{customerId}, + title = #{title}, + content = #{content}, + is_read = #{isRead}, + del_flag = #{delFlag}, + create_time = #{createTime}, + + where id = #{id} + + + + delete from ls_station_letter where id = #{id} + + + + delete from ls_station_letter where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsSystemSeoMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsSystemSeoMapper.xml new file mode 100644 index 0000000..298201c --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsSystemSeoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + select id, title, key_word, seo_desc, is_open from ls_system_seo + + + + + + + + insert into ls_system_seo + + title, + key_word, + seo_desc, + is_open, + + + #{title}, + #{keyWord}, + #{seoDesc}, + #{isOpen}, + + + + + update ls_system_seo + + title = #{title}, + key_word = #{keyWord}, + seo_desc = #{seoDesc}, + is_open = #{isOpen}, + + where id = #{id} + + + + delete from ls_system_seo where id = #{id} + + + + delete from ls_system_seo where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/LsWxCustomerLinkMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/LsWxCustomerLinkMapper.xml new file mode 100644 index 0000000..30ccebd --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/LsWxCustomerLinkMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + select id, wx_union_id, customer_id, wx_open_id, wx_applet_open_id from ls_wx_customer_link + + + + + + + + insert into ls_wx_customer_link + + wx_union_id, + customer_id, + wx_open_id, + wx_applet_open_id, + + + #{wxUnionId}, + #{customerId}, + #{wxOpenId}, + #{wxAppletOpenId}, + + + + + update ls_wx_customer_link + + wx_union_id = #{wxUnionId}, + customer_id = #{customerId}, + wx_open_id = #{wxOpenId}, + wx_applet_open_id = #{wxAppletOpenId}, + + where id = #{id} + + + + delete from ls_wx_customer_link where id = #{id} + + + + delete from ls_wx_customer_link where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/OssMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/OssMapper.xml new file mode 100644 index 0000000..ae48799 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/OssMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + id, + access_key_id, + access_key_secret, + bucket_name, + end_point, + style_name, + prefix, + address + + + + + + + update ls_aliyun_oss_setting + + access_key_id = #{accessKeyId}, + access_key_secret = #{accessKeySecret}, + bucket_name = #{bucketName}, + end_point = #{endPoint}, + style_name = #{styleName}, + prefix = #{prefix}, + address = #{address}, + + where id = #{id} + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/SCommunityBuySettingMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/SCommunityBuySettingMapper.xml new file mode 100644 index 0000000..c8029c9 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/SCommunityBuySettingMapper.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + select id, name, audit, sms_audit_notice, sms_pay_notice, sms_commission_notice from s_community_buy_setting + + + + + + + + insert into s_community_buy_setting + + name, + audit, + sms_audit_notice, + sms_pay_notice, + sms_commission_notice, + + + #{name}, + #{audit}, + #{smsAuditNotice}, + #{smsPayNotice}, + #{smsCommissionNotice}, + + + + + update s_community_buy_setting + + name = #{name}, + audit = #{audit}, + sms_audit_notice = #{smsAuditNotice}, + sms_pay_notice = #{smsPayNotice}, + sms_commission_notice = #{smsCommissionNotice}, + + where id = #{id} + + + + delete from s_community_buy_setting where id = #{id} + + + + delete from s_community_buy_setting where id in + + #{id} + + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/mapper/setting/SegchkPaySettingMapper.xml b/ruoyi-segchk/src/main/resources/mapper/setting/SegchkPaySettingMapper.xml new file mode 100644 index 0000000..4cd8ec1 --- /dev/null +++ b/ruoyi-segchk/src/main/resources/mapper/setting/SegchkPaySettingMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + select id, codeType, column_name, column_value, provider_id from segchk_pay_setting + + + + + + + + insert into segchk_pay_setting + + codeType, + column_name, + column_value, + + + #{codetype}, + #{columnName}, + #{columnValue}, + + + + + update segchk_pay_setting + + codeType = #{codetype}, + column_name = #{columnName}, + column_value = #{columnValue}, + + where id = #{id} + + + + delete from segchk_pay_setting where id = #{id} + + + + delete from segchk_pay_setting where id in + + #{id} + + + + + + + + + + + DELETE FROM segchk_pay_setting WHERE codeType=#{codeType} + + + INSERT INTO segchk_pay_setting (codeType,`column_name`,column_value) VALUES + + ( + #{paySet.codeType},#{paySet.columnName},#{paySet.columnValue} + ) + + + \ No newline at end of file diff --git a/ruoyi-segchk/src/main/resources/templates/posters/bg.jpg b/ruoyi-segchk/src/main/resources/templates/posters/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ad7c1e6bbff2bef255a60c3e03267353842e565c GIT binary patch literal 192993 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